<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://hades.mech.northwestern.edu//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AndrewLong</id>
	<title>Mech - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://hades.mech.northwestern.edu//api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AndrewLong"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/AndrewLong"/>
	<updated>2026-05-15T01:21:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=8568</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=8568"/>
		<updated>2008-03-21T06:11:40Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Robot Snake */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[ME 333 end of course schedule]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axes, and then tracks the emitter with a laser. [http://depot.northwestern.edu/mht363/public_html/IR%20Track/Mar%2019%20IR%20tracker.mp4 See Spot Run.]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This remote control robotic snake uses servo motors with a traveling sine wave motion profile to mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic2.jpg|thumb|200px|The &#039;Steel Toe&#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
[[image:T14-project-action-08.jpg|thumb|200px|right]]&lt;br /&gt;
&lt;br /&gt;
This is a tilting touchsreen that allows the user to control a rolling ball. The feedback from the touchscreen allows the user to play the game of trying to keep the ball in the center of the screen. The game is set-up in an arcade-type fashion in which there is no way to win, only lose, and the machine will simply keep eating your money.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_setup1.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This prototype is a proof of concept model of a variable ratio transmission to be implemented in the 2008-2009 Formula SAE competition vehicle.  The gear ratio is determined by the distances between the pulley halves which are controllable electronically.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=KhgTNCfdwZw Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|Sweet Baseball Game|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Ball Balancing Challenge]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Ballbalancechallenge.JPG|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive game involving ball balancing on a touchscreen with touchscreen feedback and joystick action. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8567</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8567"/>
		<updated>2008-03-21T06:10:32Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller is to control multiple RC servos (seven in our case). See [[RC Servo Theory]] for a discussion of the control signal for an RC servo. The RC servo expects a pulse every 20ms, so a timer called Timer1 is set up to overflow every 20 ms and trigger an interrupt. When the interrupt is triggered, the counter for Timer1 is set to the value held by the constant &amp;lt;tt&amp;gt;TMR1_20MS&amp;lt;/tt&amp;gt; (defined as &amp;lt;tt&amp;gt;15536&amp;lt;/tt&amp;gt;), which will cause Timer1 to overflow 20 ms later and re-trigger the interrupt. &lt;br /&gt;
&lt;br /&gt;
As shown in the RC Servo Theory, the width of the high pulse determines the angle of the servo. As a result, the pulse width corresponding to the desired angle for each servo motor is calculated and the corresponding timer value is stored in an array called &amp;lt;tt&amp;gt;RCservo&amp;lt;/tt&amp;gt;. At the beginning of the interrupt, all the pins connected to the servos are set high. For the RC servos used in this project, the maximum pulse width can be 2.25 ms; therefore, &amp;lt;tt&amp;gt;Timer1&amp;lt;/tt&amp;gt; only needs to be polled for 2.25 ms. &amp;lt;tt&amp;gt;TMR1_2point25MS&amp;lt;/tt&amp;gt; is a constant corresponding to the value of &amp;lt;tt&amp;gt;Timer1&amp;lt;/tt&amp;gt; 2.25 ms after the interrupt begins and is defined as &amp;lt;tt&amp;gt;15536 + 6250&amp;lt;/tt&amp;gt;. While &amp;lt;tt&amp;gt;Timer1&amp;lt;/tt&amp;gt; is less than this variable, the counter is compared sequentially to the values in the &amp;lt;tt&amp;gt;RCservo&amp;lt;/tt&amp;gt; array plus 15536 (15536 must be added because the Timer1 started counting at 15536 instead of 0).  Since the &amp;lt;tt&amp;gt;RCservo&amp;lt;/tt&amp;gt; array corresponds to the pulse widths of the servos, when the value of &amp;lt;tt&amp;gt;Timer1&amp;lt;/tt&amp;gt; is greater than a value in &amp;lt;tt&amp;gt;RCservo&amp;lt;/tt&amp;gt; plus 15536, the corresponding pin is set low. After the sequence is complete, &amp;lt;tt&amp;gt;Timer1&amp;lt;/tt&amp;gt; is polled again and the process repeats until 2.25 ms have elapsed, which corresponds to when Timer1 is greater than &amp;lt;tt&amp;gt;TMR1_2point25MS&amp;lt;/tt&amp;gt;. After all the servo signals have been sent, the values in the &amp;lt;tt&amp;gt;RCservo&amp;lt;/tt&amp;gt; array are updated to prepare for the next 20ms interrupt. &lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train. With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was sufficient for this project.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos could be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8513</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8513"/>
		<updated>2008-03-21T04:17:51Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Servo Control Details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller is to control multiple RC servos (seven in our case). See [[RC Servo Theory]] for a discussion of the control signal for an RC servo. In this project, the pulse period for the servo is 20ms, so a timer called Timer1 is set up to overflow every 20 ms and trigger an interrupt. When the interrupt is triggered, the counter for Timer1 is set to the value held by the variable TMR1_20MS (defined as 15536), which will restart the sequence: cause Timer1 to overflow 20 ms later and re-trigger the interrupt. &lt;br /&gt;
&lt;br /&gt;
As shown in the RC Servo Theory, the width of the high pulse determines the angle of the servo. As a result, the pulse width corresponding to the desired angle for each servo motor is calculated and stored in an array called RCservo. At the beginning of the interrupt, all the pins connected to the servos are set high. For the RC servos used in this project, the maximum pulse width can be 2.25 ms; therefore, Timer1 is polled for only 2.25 ms. TMR1_2point25MS is a variable corresponding to the time 2.25 ms after the interrupt begins and is defined as 15536 + 6250. While Timer1 is less than this variable, the counter is compared sequentially to the values in the RCservo array plus 15536. 15536 must be added because the Timer1 started counting at 15536 instead of 0. Since the RCservo array corresponds to the pulse widths of the servos, when the value of Timer1 is greater than a value in RCservo plus 15536, the corresponding pin is set low. After the sequence is complete, Timer1 is polled again and the process repeats until 2.25 ms have elapsed, which corresponds to when Timer1 is greater than TMR1_2point25MS. After all the servo signals have been sent, the values in the RCservo array are updated to prepare for the next 20ms interrupt. &lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train. With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was sufficient for this project.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos could be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8512</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8512"/>
		<updated>2008-03-21T04:16:41Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Servo Control Details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller is to control multiple RC servos (seven in our case). A discussion of RC Servo Theory can be found [[RC Servo Theory|here]].In this project, the pulse period for the servo is 20ms, so a timer called Timer1 is set up to overflow every 20 ms and trigger an interrupt. When the interrupt is triggered, the counter for Timer1 is set to the value held by the variable TMR1_20MS (defined as 15536), which will restart the sequence: cause Timer1 to overflow 20 ms later and re-trigger the interrupt. &lt;br /&gt;
&lt;br /&gt;
As shown in the RC Servo Theory, the width of the high pulse determines the angle of the servo. As a result, the pulse width corresponding to the desired angle for each servo motor is calculated and stored in an array called RCservo. At the beginning of the interrupt, all the pins connected to the servos are set high. For the RC servos used in this project, the maximum pulse width can be 2.25 ms; therefore, Timer1 is polled for only 2.25 ms. TMR1_2point25MS is a variable corresponding to the time 2.25 ms after the interrupt begins and is defined as 15536 + 6250. While Timer1 is less than this variable, the counter is compared sequentially to the values in the RCservo array plus 15536. 15536 must be added because the Timer1 started counting at 15536 instead of 0. Since the RCservo array corresponds to the pulse widths of the servos, when the value of Timer1 is greater than a value in RCservo plus 15536, the corresponding pin is set low. After the sequence is complete, Timer1 is polled again and the process repeats until 2.25 ms have elapsed, which corresponds to when Timer1 is greater than TMR1_2point25MS. After all the servo signals have been sent, the values in the RCservo array are updated to prepare for the next 20ms interrupt. &lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train. With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was sufficient for this project.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos could be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8511</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8511"/>
		<updated>2008-03-21T04:15:10Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Servo Control Details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller is to control multiple RC servos (seven in our case). A discussion of RC Servo Theory can be found &amp;lt;here&amp;gt;.  In this project, the pulse period for the servo is 20ms, so a timer called Timer1 is set up to overflow every 20 ms and trigger an interrupt. When the interrupt is triggered, the counter for Timer1 is set to the value held by the variable TMR1_20MS (defined as 15536), which will restart the sequence: cause Timer1 to overflow 20 ms later and re-trigger the interrupt. &lt;br /&gt;
&lt;br /&gt;
As shown in the RC Servo Theory, the width of the high pulse determines the angle of the servo. As a result, the pulse width corresponding to the desired angle for each servo motor is calculated and stored in an array called RCservo. At the beginning of the interrupt, all the pins connected to the servos are set high. For the RC servos used in this project, the maximum pulse width can be 2.25 ms; therefore, Timer1 is polled for only 2.25 ms. TMR1_2point25MS is a variable corresponding to the time 2.25 ms after the interrupt begins and is defined as 15536 + 6250. While Timer1 is less than this variable, the counter is compared sequentially to the values in the RCservo array plus 15536. 15536 must be added because the Timer1 started counting at 15536 instead of 0. Since the RCservo array corresponds to the pulse widths of the servos, when the value of Timer1 is greater than a value in RCservo plus 15536, the corresponding pin is set low. After the sequence is complete, Timer1 is polled again and the process repeats until 2.25 ms have elapsed, which corresponds to when Timer1 is greater than TMR1_2point25MS. After all the servo signals have been sent, the values in the RCservo array are updated to prepare for the next 20ms interrupt. &lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train. With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was sufficient for this project.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos could be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8508</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8508"/>
		<updated>2008-03-21T04:14:26Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* PIC Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller is to control multiple RC servos (seven in our case). A discussion of RC Servo Theory can be found &amp;lt;here&amp;gt;.  In this project, the pulse period for the servo is 20ms, so a timer called Timer1 is set up to overflow every 20 ms and trigger an interrupt. When the interrupt is triggered, the counter for Timer1 is set to the value held by the variable TMR1_20MS (defined as 15536), which will restart the sequence: cause Timer1 to overflow 20 ms later and re-trigger the interrupt. &lt;br /&gt;
&lt;br /&gt;
As shown in the RC Servo Theory, the width of the high pulse determines the angle of the servo. As a result, the pulse width corresponding to the desired angle for each servo motor is calculated and stored in an array called RCservo. At the beginning of the interrupt, all the pins connected to the servos are set high. For the RC servos used in this project, the maximum pulse width can be 2.25 ms; therefore, Timer1 is polled for only 2.25 ms. TMR1_2point25MS is a variable corresponding to the time 2.25 ms after the interrupt begins and is defined as 15536 + 6250. While Timer1 is less than this variable, the counter is compared sequentially to the values in the RCservo array plus 15536. 15536 must be added because the Timer1 started counting at 15536 instead of 0. Since the RCservo array corresponds to the pulse widths of the servos, when the value of Timer1 is greater than a value in RCservo plus 15536, the corresponding pin is set low. After the sequence is complete, Timer1 is polled again and the process repeats until 2.25 ms have elapsed, which corresponds to when Timer1 is greater than TMR1_2point25MS. After all the servo signals have been sent, the values in the RCservo array are updated to prepare for the next 20ms interrupt. &lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train. With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was sufficient for this project. &lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos could be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8499</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8499"/>
		<updated>2008-03-21T04:00:05Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* High Torque Servos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS (defined as 15536), which will cause Timer1 to overflow 20ms later and re-trigger the interrupt.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS (defined as 15536 + 6250), Timer1 is polled, and the value is compared sequentially to the values in the RCservo array plus 15536 (because Timer1 started counting at 15536, not 0).  If the  value of Timer1 is greater than a value in (RCservo[x]+15536), the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos could be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8498</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8498"/>
		<updated>2008-03-21T03:56:25Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS (defined as 15536), which will cause Timer1 to overflow 20ms later and re-trigger the interrupt.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS (defined as 15536 + 6250), Timer1 is polled, and the value is compared sequentially to the values in the RCservo array plus 15536 (because Timer1 started counting at 15536, not 0).  If the  value of Timer1 is greater than a value in (RCservo[x]+15536), the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although polling the timer to control the length of a pulse has a lower resolution than using an interrupt (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution for the pulse was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake without housing]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake with housing]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8261</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8261"/>
		<updated>2008-03-20T20:11:02Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Serial Communication Details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio to a PC with a XBee radio. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake. When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8254</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8254"/>
		<updated>2008-03-20T19:56:04Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* PIC Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found in the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8252</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8252"/>
		<updated>2008-03-20T19:55:00Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in The Head Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC. The wiring diagram shows a schematic for the Xbee connection with the PIC. The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found the the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8251</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8251"/>
		<updated>2008-03-20T19:54:08Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in The Head Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake]&lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=wBcJkNHEaAs Video of 3 body segments moving]&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chassis Built Showing a Standoff and Batteries]]&lt;br /&gt;
[[image:BuiltChasis2_MLS.jpg|thumb|right|Chassis with Batteries Removed]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  Each segment of the snake contains a small circuit board (ServoBoard Schematic) which has a connector for the ribbon cable, a switch to control the power, and a power indicator LED.  Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC18F4520 Prototyping Board designed by Professor Peshkin was used.  Schematics of the board can be found here: [[Main_Page#PIC_18F4520_prototyping_board|18F4520_prototyping_board]].  The only change applied to the board was to replace the 20MHz clock with a 40MHz clock. This allowed the microcontroller to perform calculations faster, improving the resolution of the servo signal.  The ribbon cable was connected to the ground and port D pins on the PIC.&lt;br /&gt;
&lt;br /&gt;
An [[XBee_radio_communication_between_PICs|XBee radio]] was used to communicate between the microcontroller and the PC.  The [[XBee_radio_communication_between_PICs#XBee_Interface_Module|XBee Interface Board]] was used to provide a robust mechanical mount for the radio, as well as supply the 3.3V needed by the XBee.  On the PC side, another XBee interface board was plugged into the FTDI USB-Serial converter. Other than this, no special electronics were needed for the XBee radio.  The radio simply acted as a serial cable replacement  The snake was controlled by sending commands with a terminal program. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and receives data from a computer via serial communication.&lt;br /&gt;
&lt;br /&gt;
The main purpose of SnakeServos.c is to calculate the motion profile of the servos, and send a corresponding signal to each of the servos every 20 ms.  The code for this is found the the &amp;lt;tt&amp;gt;ISR_20MS&amp;lt;/tt&amp;gt; function in the code which is run every 20ms.&lt;br /&gt;
&lt;br /&gt;
A secondary function is to update the parameters that affect the motion of the snake.  The code for this can be found in the &amp;lt;tt&amp;gt;ISR_USART_RX&amp;lt;/tt&amp;gt; function, which is run every time a byte is received on the USART&#039;s receive buffer.&lt;br /&gt;
&lt;br /&gt;
====Servo Control Details====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication Details====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and period of the sine wave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
//use volatile keyword to avoid problems with optimizer&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);		//set timer to trigger an interrupt 20ms later&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);	//begin pulse for servo signal&lt;br /&gt;
   time=get_timer1();			//poll timer&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){	//end this loop after 2.25 ms&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){	&lt;br /&gt;
         output_low(SERVO_0);	//end the pulse when time is up&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();	//poll timer&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);	//set all servos low in case some pins are still high&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;	//increment time, wrap around if necessary to prevent overflow&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
	//load default values&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);	//enable Timer1 interrupt&lt;br /&gt;
   enable_interrupts(INT_RDA);		//enable USART receive interrupt&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
[http://www.youtube.com/watch?v=r_GOOFLnI6w Video of the robot snake 2]&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8174</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8174"/>
		<updated>2008-03-20T17:41:05Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in Each Body Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board (ServoBoard Schematic) contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. The actual circuit board can be seen in the image (A Complete Circuit Board on the Snake). Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8173</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8173"/>
		<updated>2008-03-20T17:40:40Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board (ServoBoard Schematic) contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. The actual circuit board can be seen in the image (A Complete Circuit Board on the Snake). Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|left|Ribbon Cable Schematic]][[image:ServoBoard_schematic_HLS.jpg|thumb|center|ServoBoard Schematic]][[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8172</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8172"/>
		<updated>2008-03-20T17:39:49Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in Each Body Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board (ServoBoard Schematic) contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. The actual circuit board can be seen in the image (A Complete Circuit Board on the Snake). Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|left|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|center|ServoBoard Schematic]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8171</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8171"/>
		<updated>2008-03-20T17:38:57Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board (ServoBoard Schematic) contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. The actual circuit board can be seen in the image (A Complete Circuit Board on the Snake). Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8170</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8170"/>
		<updated>2008-03-20T17:38:03Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board (ServoBoard Schematic) contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. The actual circuit board can be seen in the image (A Complete Circuit Board on the Snake). Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8169</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8169"/>
		<updated>2008-03-20T17:36:38Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in Each Body Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board (ServoBoard Schematic) contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8168</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8168"/>
		<updated>2008-03-20T17:36:15Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in Each Body Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board  contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8167</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8167"/>
		<updated>2008-03-20T17:35:36Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Electronics in Each Body Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line as shown in the ribbon cable schematic.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8166</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8166"/>
		<updated>2008-03-20T17:34:49Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Parts List (Digikey Part Number) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G): 1 per segment&lt;br /&gt;
*10 pos IDC cable header (A26267-ND): 1 per segment&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND): 1 per segment&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND): 1 per segment&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8165</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8165"/>
		<updated>2008-03-20T17:32:56Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Fully Assembled Body Segment */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries)&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8164</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8164"/>
		<updated>2008-03-20T17:31:29Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
===Parts List===&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
*Ball caster: For the head&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8163</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8163"/>
		<updated>2008-03-20T17:29:59Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* The Body Segments */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 1/2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8160</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8160"/>
		<updated>2008-03-20T17:27:25Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66, 72-73.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8159</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8159"/>
		<updated>2008-03-20T17:27:07Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Robot Snake Motion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations (Saito etal, 72-73):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8158</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8158"/>
		<updated>2008-03-20T17:26:17Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Snake Motion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path (Ma, 205). In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al, 66)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8157</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8157"/>
		<updated>2008-03-20T17:23:56Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 205-6.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8156</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8156"/>
		<updated>2008-03-20T17:23:43Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* References */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol 15, No 2 (2001): 206.&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8154</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8154"/>
		<updated>2008-03-20T17:22:29Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Advantages / Disadvantages of Robotic Snake Motion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
(Ma, 206)&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8152</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8152"/>
		<updated>2008-03-20T17:20:32Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Advantages */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of a snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain, since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand, since it can distribute its weight across a wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot.&lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8151</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8151"/>
		<updated>2008-03-20T17:19:34Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Snake Motion */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include serpentine movement, rectilinear movement, concertina movement and side-winding movement. The most common motion exhibited by most snakes is serpentine motion where each section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficients of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8150</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8150"/>
		<updated>2008-03-20T17:18:25Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. (Saito et al)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8149</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8149"/>
		<updated>2008-03-20T17:17:16Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;ref name=&amp;quot;Perry&amp;quot;&amp;gt;Perry&#039;s Handbook, Sixth Edition, McGraw-Hill Co., 1984.&amp;lt;/ref&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8147</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=8147"/>
		<updated>2008-03-20T17:12:53Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
In this project, we developed and built a robot to mimic serpentine motion of a snake. The robot is made up of several body segments and a head. Each body segment contains a RC servo, which is controlled by a PIC microntroller located in the head of the snake robot. This wiki page contains discussions of the motion of a snake, mechanical design, electronic design and PIC code. &lt;br /&gt;
&lt;br /&gt;
[http://www.youtube.com/watch?v=Sb8WqaLX1Vo Video of the robot snake.]&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
====Parts List====&lt;br /&gt;
&lt;br /&gt;
*Motors: Futaba S3004 standard ball bearing RC servo motor, Tower Hobbies LXZV41 $12.99&lt;br /&gt;
*Wheels: McMasterCarr Acetal Pulley for Fibrous Rope for 1/4&amp;quot; Rope Diameter, 3/4&amp;quot; OD McMasterCarr 8901T11 $1.66&lt;br /&gt;
*O-Rings (Tires): McMasterCarr Silicone O-Ring AS568A Dash Number 207, Packs of 50 McMasterCarr 9396K209 $7.60/50&lt;br /&gt;
*PVC Pipe: McMasterCarr Sewer &amp;amp; Drain Thin-Wall PVC Pipe Non-Perforated, 3&amp;quot; X 4-1/2&#039; L, Light Green McMasterCarr 2426K24 $7.06&lt;br /&gt;
*1/8th inch plastic for chassis: (Shop Stock) or McMasterCarr Polycarbonate Sheet 1/8&amp;quot; Thick, 12&amp;quot; X 12&amp;quot;, Clear, McMasterCarr, 8574K26 $6.32&lt;br /&gt;
*Dowel Pins: 1&amp;quot; long, 1/4&amp;quot; diameter &lt;br /&gt;
*Sheet Metal:  For the connecting segments&lt;br /&gt;
*Fasteners: Screws for the servos and chassis, washers for the standoffs&lt;br /&gt;
*Standoffs: Used 1&amp;quot; and 2&amp;quot; to achieve a level snake&lt;br /&gt;
*Velcro: To attach battery packs and housing to the chasis&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
====Standoffs ====&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Protection and Visual Appeal  ====&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
====Parts List (Digikey Part Number)====&lt;br /&gt;
&lt;br /&gt;
*PIC: PIC18F4520&lt;br /&gt;
*Oscillator: 40MHz Oscillator (X225-ND)&lt;br /&gt;
*RC Servo (see mechanical design) preferably high-torque &lt;br /&gt;
*10 wire IDC ribbon cable&lt;br /&gt;
*10 pos IDC cable socket (ASC10G)&lt;br /&gt;
*10 pos IDC cable header (A26267-ND)&lt;br /&gt;
*3 pos AAA battery holder (BH3AAA-W-ND)&lt;br /&gt;
*2 pos AAA battery holder (BH2AAA-W-ND)&lt;br /&gt;
*475 Ohm resistors (transmission line termination)&lt;br /&gt;
*Various switches to turn power electronics and the motors on/off&lt;br /&gt;
*Standard Protoboard, to mount connector from ribbon cable, and switches for each motor&lt;br /&gt;
*Xbee radio pair and PC &lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
====Electronics in Each Body Segment====&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.  The signal generated by the microcontroller is carried by the IDC ribbon cable, and each servo board taps into a single signal line and the reference ground line.  At each motor, a small circuit board contains the connector for the ribbon cable, a switch to control the power and a power indicator LED. This circuit board has a common ground, connecting the signal ground with the battery ground and receives power from the batteries. Because of the length of the ribbon cable, each signal line must be terminated with a 475 ohm resistor to prevent reflected &amp;quot;ghost&amp;quot; signals from interfering with the original signal.&lt;br /&gt;
&lt;br /&gt;
Each servo board also has its own power supply of 5 AAA cells, which gives each servo 7.5V.  Although the servos are only rated for 6V, 7.5V was used because more torque was needed.  The current drain (up to 500mA) caused the voltage across the cells to drop due to the high internal resistance of the alkaline cells.  NiMH rechargeable cells are more capable of handling high current draw applications, but are also much more expensive and can take several hours to charge.&lt;br /&gt;
&lt;br /&gt;
The robot snake can run for about 1 hour on the alkaline cells, after which the servos no longer have enough torque to generate the serpentine motion.&lt;br /&gt;
&lt;br /&gt;
====Electronics in The Head Segment====&lt;br /&gt;
 &lt;br /&gt;
The PIC /PIC board and power to the PIC Board&lt;br /&gt;
&lt;br /&gt;
The Xbee Radio&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC files used in this robotic snake, SnakeServos.c and main.h, which are shown below. main.h sets up  the default parameters used in SnakeServos.c. The microcontroller controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
====Servo Control====&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;s counter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
====Serial Communication====&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake.&lt;br /&gt;
&lt;br /&gt;
====SnakeServos.c====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels, as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
Wireless control from a laptop allowed easy demonstration of the snakes capabilities, and allowed others to easily control its movement.&lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
==== Position Sensors ====&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course or maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
==== Obstacle Avoidance ====&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
==== Power Supply ====&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that this robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
====High Torque Servos====&lt;br /&gt;
The servos in the snake have a large load but do not need to move very quickly, so high torque servos should be used instead of standard servos.  This would also prolong the battery life because the servos would be operating in a more efficient range.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7993</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7993"/>
		<updated>2008-03-20T01:37:57Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC codes used in this robotic snake, SnakeServos.C and main.h, which are shown below. main.h sets up all the default parameters used in SnakeServos.C. The microcontroler controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake. &lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Overall, the robotic snake was successful. &lt;br /&gt;
&lt;br /&gt;
Initially, the mechanical design included a single wheel mounted in the center of the pvc pipe. However, the motion of the snake was very difficult to control because the robotic snake became unstable very easily. As a result, the chassis was built to include two wheels as discussed in the mechanical design section, in order to provide stability which made the robot easier to control. &lt;br /&gt;
&lt;br /&gt;
The final robotic snake can be seen in action here. (insert link for youtube video)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
=== Position Sensors ===&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course of maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
=== Obstacle Avoidance ===&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
=== Power Supply ===&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that his robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7992</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7992"/>
		<updated>2008-03-20T01:24:08Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* PIC Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
&lt;br /&gt;
There are two PIC codes used in this robotic snake, SnakeServos.C and main.h, which are shown below. main.h sets up all the default parameters used in SnakeServos.C. The microcontroler controls the RC servos and communicates via serial communication to a computer. These two functions are discussed below. &lt;br /&gt;
&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated. As shown in the code, the serial communication allows the user to change the speed, the amplitude and phase of the sinewave, and the direction (forward, reverse, left and right) of the robotic snake. &lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
=== Position Sensors ===&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course of maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
=== Obstacle Avoidance ===&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
=== Power Supply ===&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that his robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7991</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7991"/>
		<updated>2008-03-20T01:11:30Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Next Steps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
The robotic snake was developed within five weeks, and proved to be a very successful demo. There are many options that could be researched and developed to add to this robot and discussed below.&lt;br /&gt;
&lt;br /&gt;
=== Position Sensors ===&lt;br /&gt;
Sensors could be added to the robot to allow it to know its position. This could be accomplished with a combination of encoders on a segment. Most likely, the middle segment should be used since it would be the approximate center of gravity. Knowledge of the position of the center of gravity would potentially the robotic snake to be sent to different locations or navigate (using dead reckoning) through a pre-determined obstacle course of maze.  The information from encoders could be sent to a computer to observe different snakelike motions with different parameters.&lt;br /&gt;
&lt;br /&gt;
=== Obstacle Avoidance ===&lt;br /&gt;
With optical sensors on the head of the snake, the robot would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
=== Power Supply ===&lt;br /&gt;
Currently, 5 AAA batteries are required for each servo, meaning that his robot requires many batteries. As a result, a different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7990</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7990"/>
		<updated>2008-03-20T00:50:30Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Servo Control */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1 is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
This snake was developed within five weeks, and proved to be a very successful demo.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further capabilities of the snake could include:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sensors to determine position:  This could be accomplished with a combination of encoders on the middle segment (which would detect forward motion, and the head (which would detect current direction).  This type of awareness would allow the snake to be sent to different locations or navigate (using dead reckoning) though a pre-determined obstacle course of maze.  These encoders would also allow for the different snakelike motions to be observed, for instance, how does changing only the amplitude affect the speed?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obstacle avoidance:  With optical sensors on the head of the snake, it would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Power supply: Currently 5 AAA batteries supply each servo, thus the snake uses way too many batteries. A different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=7989</id>
		<title>ME 333 final projects</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=ME_333_final_projects&amp;diff=7989"/>
		<updated>2008-03-20T00:43:35Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Robot Snake */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[ME 333 end of course schedule]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
== ME 333 Final Projects 2008 ==&lt;br /&gt;
&lt;br /&gt;
=== [[IR Tracker]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_Tracker_Main.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The IR Tracker (aka &amp;quot;Spot&amp;quot;) is a device that follows a moving infrared light. It continuously detects the position of an infrared emitter in two axises, and then tracks the emitter with a laser.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Robot Snake]] ===&lt;br /&gt;
[[Image:HLSSnakeMain.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This wirelessly controlled robotic snake uses servo motors with a traveling sine wave to  mimic serpentine motion.  The robotic snake is capable of moving forward, left, right and in reverse.   &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Programmable Stiffness Joint]] === &lt;br /&gt;
&lt;br /&gt;
[[Image:SteelToePic.jpg|thumb|200px|The &#039;Steel Toe&#039; programmable stiffness joint|right]]&lt;br /&gt;
&lt;br /&gt;
The Programmable Stiffness Joint varies rotational stiffness as desired by the user.  It is the first step in modeling the mechanical impedance of the human ankle joint (both stiffness and damping) for the purpose of determining the respective breakdown of the two properties over the gait cycle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Magnetic based sample purification]] ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== [[Continuously Variable Transmission]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:CVT_setup1.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
A continuously variable tramsission is intended to provide a transition from low to high gear ratios while keeping the engine input running at the max efficient speed. It is achieved by a system of variable radius pulleys and a v-belt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Granular Flow Rotating Sphere]] ===&lt;br /&gt;
&lt;br /&gt;
This device will be used to study the granular flow of particles within a rotating sphere. The sphere is filled with grains of varying size and then rotated about two different axes according to a series of position and angular velocity inputs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Vibratory Clock]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Vibratory_Clock.jpg|right|thumb|Vibratory Clock|200px]]&lt;br /&gt;
&lt;br /&gt;
The Vibratory Clock allows a small object to act as an hour &amp;quot;hand&amp;quot; on a horizontal circular platform that is actuated from underneath by three speakers.  The object slides around the circular platform, impelled by friction forces due to the vibration.  [http://www.youtube.com/watch?v=PV9utFL5J6w Check it out!]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[WiiMouse]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:HPIM1027.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
The WiiMouse is a handheld remote that can be used to move a cursor on a windows-based PC, via accelerometer input captured through device movement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Intelligent Oscillation Controller]] ===&lt;br /&gt;
&lt;br /&gt;
[[image:ME333_learning_oscillator.jpg|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
This device &amp;quot;learns&amp;quot; a forcing function that is applied to a spring and mass system to match an arbitrary, periodic acceleration profile.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [[Baseball]] ===&lt;br /&gt;
&lt;br /&gt;
[[Image:Baseball_Playfield.jpg|right|thumb|200px]]&lt;br /&gt;
&lt;br /&gt;
An interactive baseball game inspired by pinball, featuring pitching, batting, light up bases and a scoreboard to keep track of the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7988</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7988"/>
		<updated>2008-03-20T00:40:48Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
This snake was developed within five weeks, and proved to be a very successful demo.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further capabilities of the snake could include:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sensors to determine position:  This could be accomplished with a combination of encoders on the middle segment (which would detect forward motion, and the head (which would detect current direction).  This type of awareness would allow the snake to be sent to different locations or navigate (using dead reckoning) though a pre-determined obstacle course of maze.  These encoders would also allow for the different snakelike motions to be observed, for instance, how does changing only the amplitude affect the speed?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obstacle avoidance:  With optical sensors on the head of the snake, it would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Power supply: Currently 5 AAA batteries supply each servo, thus the snake uses way too many batteries. A different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7987</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7987"/>
		<updated>2008-03-20T00:40:19Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|right]]&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
This snake was developed within five weeks, and proved to be a very successful demo.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further capabilities of the snake could include:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sensors to determine position:  This could be accomplished with a combination of encoders on the middle segment (which would detect forward motion, and the head (which would detect current direction).  This type of awareness would allow the snake to be sent to different locations or navigate (using dead reckoning) though a pre-determined obstacle course of maze.  These encoders would also allow for the different snakelike motions to be observed, for instance, how does changing only the amplitude affect the speed?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obstacle avoidance:  With optical sensors on the head of the snake, it would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Power supply: Currently 5 AAA batteries supply each servo, thus the snake uses way too many batteries. A different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Snake_Robot_1.jpg&amp;diff=7986</id>
		<title>File:Snake Robot 1.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Snake_Robot_1.jpg&amp;diff=7986"/>
		<updated>2008-03-20T00:39:53Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7985</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7985"/>
		<updated>2008-03-20T00:39:41Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_1.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
This snake was developed within five weeks, and proved to be a very successful demo.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further capabilities of the snake could include:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sensors to determine position:  This could be accomplished with a combination of encoders on the middle segment (which would detect forward motion, and the head (which would detect current direction).  This type of awareness would allow the snake to be sent to different locations or navigate (using dead reckoning) though a pre-determined obstacle course of maze.  These encoders would also allow for the different snakelike motions to be observed, for instance, how does changing only the amplitude affect the speed?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obstacle avoidance:  With optical sensors on the head of the snake, it would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Power supply: Currently 5 AAA batteries supply each servo, thus the snake uses way too many batteries. A different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7984</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7984"/>
		<updated>2008-03-20T00:39:24Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
This snake was developed within five weeks, and proved to be a very successful demo.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further capabilities of the snake could include:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sensors to determine position:  This could be accomplished with a combination of encoders on the middle segment (which would detect forward motion, and the head (which would detect current direction).  This type of awareness would allow the snake to be sent to different locations or navigate (using dead reckoning) though a pre-determined obstacle course of maze.  These encoders would also allow for the different snakelike motions to be observed, for instance, how does changing only the amplitude affect the speed?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obstacle avoidance:  With optical sensors on the head of the snake, it would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Power supply: Currently 5 AAA batteries supply each servo, thus the snake uses way too many batteries. A different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Snake_Robot_Intro.jpg&amp;diff=7983</id>
		<title>File:Snake Robot Intro.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Snake_Robot_Intro.jpg&amp;diff=7983"/>
		<updated>2008-03-20T00:37:39Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7982</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7982"/>
		<updated>2008-03-20T00:37:28Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot_Intro.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|right|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_schematic_HLS.jpg|thumb|right|The Mainboard Schematic]]&lt;br /&gt;
[[image:RibbonCable_schematic_HLS.jpg|thumb|right|Ribbon Cable Schematic]]&lt;br /&gt;
[[image:ServoBoard_schematic_HLS.jpg|thumb|right|ServoBoard Schematic]]&lt;br /&gt;
&lt;br /&gt;
[[image:PICBoard_HLS.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
[[image:ServoBoard_Hooked_up_HLS.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
&lt;br /&gt;
The each segment of the snake contains a Futaba Standard RC Servo.  Each servo has 3 wires: power, ground, and signal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and not have to decrease the frequency of the servo signal pulse train.  With a 40MHz clock and seven servos, the resolution was about 8us, which was good enough for this purpose.&lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
===SnakeServos.c===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
Andy Long, Clara Smart, and Michael Hwang&#039;s snake robot code.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#device high_ints=TRUE        // this allows raised priority interrupts, which we need&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay(clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, UART1) &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;main.h&amp;gt;&lt;br /&gt;
#include &amp;lt;math.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Put your desired high duration here; &lt;br /&gt;
3200 is center  &lt;br /&gt;
1000 is 90 deg right &lt;br /&gt;
5400 is 90 deg left&lt;br /&gt;
*/&lt;br /&gt;
int16 RCservo[7];  &lt;br /&gt;
&lt;br /&gt;
volatile float a = A_DEFAULT;&lt;br /&gt;
volatile float b = B_DEFAULT;&lt;br /&gt;
volatile float c = C_DEFAULT;&lt;br /&gt;
&lt;br /&gt;
volatile float alpha;&lt;br /&gt;
volatile float gamma;&lt;br /&gt;
volatile float beta;&lt;br /&gt;
volatile float speed = 0;&lt;br /&gt;
volatile float prev_speed = SPEED_DEFAULT;&lt;br /&gt;
float t = 0; &lt;br /&gt;
&lt;br /&gt;
#INT_TIMER1 // designates that this is the routine to call when timer1 overflows&lt;br /&gt;
//generates servo signals&lt;br /&gt;
void ISR_20MS(){&lt;br /&gt;
   volatile unsigned int16 time;&lt;br /&gt;
   set_timer1(TMR1_20MS);&lt;br /&gt;
   SET_ALL_SERVOS(0b11111111);&lt;br /&gt;
   time=get_timer1();&lt;br /&gt;
   while(time &amp;lt; TMR1_2point25MS){&lt;br /&gt;
      if (time &amp;gt; (RCservo[0] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_0);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[1] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_1);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[2] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_2);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[3] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_3);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[4] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_4);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[5] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_5);&lt;br /&gt;
      }&lt;br /&gt;
      if (time &amp;gt; (RCservo[6] + TMR1_20MS)){&lt;br /&gt;
         output_low(SERVO_6);&lt;br /&gt;
      }&lt;br /&gt;
      time=get_timer1();&lt;br /&gt;
   }&lt;br /&gt;
   SET_ALL_SERVOS(0);&lt;br /&gt;
&lt;br /&gt;
    //3200 is center  //1000 is 90 deg right // 5400 is 90 deg left&lt;br /&gt;
   /*&lt;br /&gt;
   add value of sine wave with phase offset ((alpha*sin(t + X*beta), &lt;br /&gt;
   3200 for servo center position,&lt;br /&gt;
   an adjustment value to compensate for offsets when mounting servo horn (SERVO_X_ADJ),&lt;br /&gt;
   and bias (gamma) for turning.&lt;br /&gt;
   */&lt;br /&gt;
   &lt;br /&gt;
   RCservo[0]=(int16)(alpha*sin(t) + 3200 + SERVO_3_ADJ + gamma); &lt;br /&gt;
   RCservo[1]=(int16)(alpha*sin(t + 1*beta) + 3200 + SERVO_4_ADJ + gamma);&lt;br /&gt;
   RCservo[2]=(int16)(alpha*sin(t + 2*beta) + 3200 + gamma + SERVO_5_ADJ);&lt;br /&gt;
   RCservo[3]=(int16)(alpha*sin(t + 3*beta) + 3200 + gamma + SERVO_6_ADJ);&lt;br /&gt;
   RCservo[4]=(int16)(alpha*sin(t + 4*beta) + 3200 + gamma + SERVO_7_ADJ);&lt;br /&gt;
   RCservo[5]=(int16)(alpha*sin(t + 5*beta) + 3200 + gamma + SERVO_8_ADJ);&lt;br /&gt;
   RCservo[6]=(int16)(alpha*sin(t + 6*beta) + 3200 + gamma + SERVO_9_ADJ);&lt;br /&gt;
&lt;br /&gt;
   t+= speed;&lt;br /&gt;
   if (t &amp;gt; 2*pi){&lt;br /&gt;
      t = 0;&lt;br /&gt;
   }&lt;br /&gt;
   else if (t &amp;lt; 0){&lt;br /&gt;
      t = 2*pi;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#INT_RDA HIGH    //High-Priority Interrupt triggered by USART Rx&lt;br /&gt;
//parameter update&lt;br /&gt;
void ISR_USART_RX(){&lt;br /&gt;
   char input;&lt;br /&gt;
   if (kbhit()){&lt;br /&gt;
      input = getc();&lt;br /&gt;
      switch(input){&lt;br /&gt;
         case &#039;w&#039;: //accelerate&lt;br /&gt;
            speed += 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;s&#039;: //decelerate&lt;br /&gt;
            speed -= 0.002;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;x&#039;: //pause motion&lt;br /&gt;
            prev_speed = speed;&lt;br /&gt;
            speed = 0;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;z&#039;: //resume motion&lt;br /&gt;
            speed = prev_speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;c&#039;: //reverse speed&lt;br /&gt;
            speed = -speed;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;a&#039;: //increase left turn rate&lt;br /&gt;
            c -= 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;d&#039;: //increase right turn rate&lt;br /&gt;
            c += 1000;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;f&#039;: //set turn rate to 0&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma = 0;&lt;br /&gt;
         case &#039;t&#039;: //increase amplitude&lt;br /&gt;
            a += 10; &lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;g&#039;: //decrease amplitude&lt;br /&gt;
            a -= 10;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;y&#039;: //increase phases in body&lt;br /&gt;
            b += 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;h&#039;: //decrease phases in body&lt;br /&gt;
            b -= 0.1;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;1&#039;: //preset 1&lt;br /&gt;
            a = A_DEFAULT;&lt;br /&gt;
            b = B_default;&lt;br /&gt;
            c = C_default;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;  &lt;br /&gt;
         case &#039;2&#039;:  //preset 2&lt;br /&gt;
            a = 1400;&lt;br /&gt;
            b = 2*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;&lt;br /&gt;
         case &#039;3&#039;:  //preset 3&lt;br /&gt;
            a = 1000;&lt;br /&gt;
            b = 5*pi;&lt;br /&gt;
            c = C_DEFAULT;&lt;br /&gt;
            gamma=-c/num_segments;&lt;br /&gt;
            beta=b/num_segments;&lt;br /&gt;
            alpha=a*abs(sin(beta));&lt;br /&gt;
            speed=SPEED_DEFAULT;&lt;br /&gt;
            break;              &lt;br /&gt;
         default:&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void main() {&lt;br /&gt;
   a = A_DEFAULT;&lt;br /&gt;
   b = B_default;&lt;br /&gt;
   c = C_default;&lt;br /&gt;
   gamma=-c/num_segments;&lt;br /&gt;
   beta=b/num_segments;&lt;br /&gt;
   alpha=a*abs(sin(beta));&lt;br /&gt;
   speed=0;&lt;br /&gt;
   &lt;br /&gt;
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_4 );       &lt;br /&gt;
   set_timer1(0);&lt;br /&gt;
   &lt;br /&gt;
   enable_interrupts(INT_TIMER1);&lt;br /&gt;
   enable_interrupts(INT_RDA);&lt;br /&gt;
   enable_interrupts(GLOBAL);&lt;br /&gt;
      &lt;br /&gt;
   while (TRUE) {     &lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===main.h===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef __MAIN_H__&lt;br /&gt;
#define __MAIN_H__&lt;br /&gt;
&lt;br /&gt;
#define SET_ALL_SERVOS(x) output_d(x)&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
This chart matches the pin on the PIC to the wire on the ribbon cable&lt;br /&gt;
PIN WIRE IN USE&lt;br /&gt;
--- ---- -------&lt;br /&gt;
RD0  2&lt;br /&gt;
RD1  3      *&lt;br /&gt;
RD2  4      *&lt;br /&gt;
RD3  5      *&lt;br /&gt;
RD4  6      *&lt;br /&gt;
RD5  7      *&lt;br /&gt;
RD6  8      *&lt;br /&gt;
RD7  9      *&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
#define SERVO_3_ADJ 0&lt;br /&gt;
#define SERVO_4_ADJ 300&lt;br /&gt;
#define SERVO_5_ADJ (-150)&lt;br /&gt;
#define SERVO_6_ADJ 75&lt;br /&gt;
#define SERVO_7_ADJ (-200)&lt;br /&gt;
#define SERVO_8_ADJ 100&lt;br /&gt;
#define SERVO_9_ADJ (-150)&lt;br /&gt;
&lt;br /&gt;
#define SERVO_0 PIN_D1&lt;br /&gt;
#define SERVO_1 PIN_D2&lt;br /&gt;
#define SERVO_2 PIN_D3&lt;br /&gt;
#define SERVO_3 PIN_D4&lt;br /&gt;
#define SERVO_4 PIN_D5&lt;br /&gt;
#define SERVO_5 PIN_D6&lt;br /&gt;
#define SERVO_6 PIN_D7&lt;br /&gt;
&lt;br /&gt;
#define A_DEFAULT 1300&lt;br /&gt;
#define B_DEFAULT 3*pi&lt;br /&gt;
#define C_DEFAULT 0&lt;br /&gt;
&lt;br /&gt;
#define SPEED_DEFAULT 0.05&lt;br /&gt;
#define OMEGA_DEFAULT 1&lt;br /&gt;
#define num_segments 8&lt;br /&gt;
&lt;br /&gt;
#define TMR1_20MS 15536&lt;br /&gt;
#define TMR1_2point25MS 15536 + 6250&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
This snake was developed within five weeks, and proved to be a very successful demo.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Further capabilities of the snake could include:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sensors to determine position:  This could be accomplished with a combination of encoders on the middle segment (which would detect forward motion, and the head (which would detect current direction).  This type of awareness would allow the snake to be sent to different locations or navigate (using dead reckoning) though a pre-determined obstacle course of maze.  These encoders would also allow for the different snakelike motions to be observed, for instance, how does changing only the amplitude affect the speed?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Obstacle avoidance:  With optical sensors on the head of the snake, it would be able to sense an obstacle and either overide the wireless command and avoid it, or stop completely, and wait for further commands.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Power supply: Currently 5 AAA batteries supply each servo, thus the snake uses way too many batteries. A different power supply could be investigated.&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7645</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7645"/>
		<updated>2008-03-18T04:05:30Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Mechanical Debugging */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|center|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:HookedUpBoard.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
[[image:PICBoard.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and preserve the 20ms interrupt.  With a 40MHz clock, &lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7643</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7643"/>
		<updated>2008-03-18T04:04:24Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|center|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:HookedUpBoard.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
[[image:PICBoard.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and preserve the 20ms interrupt.  With a 40MHz clock, &lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7642</id>
		<title>Robot Snake</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Robot_Snake&amp;diff=7642"/>
		<updated>2008-03-18T04:03:48Z</updated>

		<summary type="html">&lt;p&gt;AndrewLong: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:Snake_Robot.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; Snake Robot &amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
==Team Members==&lt;br /&gt;
&lt;br /&gt;
*Michael Hwang - Electrical Engineer - Class 2008&lt;br /&gt;
*Andrew Long - Mechanical Engineer - Class 2009&lt;br /&gt;
*Clara Smart - Electrical Engineer - Class 2009&lt;br /&gt;
&lt;br /&gt;
[[image:Team23_Members.jpg|thumb|400pix|center|Hwang-Long-Smart]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Snake Motion ==&lt;br /&gt;
[[image:Snake_Motion.jpg|thumb|right|Source: [http://science.howstuffworks.com/snake3.htm How Stuff Works]]]&lt;br /&gt;
Snakes are able to adapt their movement to various environments. For instance, snakes can move across extreme environments such as sand, mud and water. Research has discovered there are four types of snake motion, as shown in the image.  These motions include; serpentine movement, rectilinear movement, concertina movement and side-winding movement.&amp;lt;ref&amp;gt;Ma, Shugen. &amp;quot;Analysis of creeping locomotion of a snake-like robot.&amp;quot; &#039;&#039;Advanced Robotics&#039;&#039; Vol.15, No.2 (2001): 205&amp;lt;/ref&amp;gt; The most common motion exhibited by most snakes is serpentine motion where section follows a similar path. In order for snakes to successfully locomote using serpentine motion, the belly of the snake must have anisotropic coefficient of friction for the normal and tangential directions. Specifically, the normal friction must be greater than the tangential friction. As a result, when the snake exhibits a force on the ground, it will move in the tangential direction without slipping in the normal direction.&amp;lt;ref&amp;gt;Saito, Fukaya, Iwasaki. &amp;quot;Serpentine Locomotion with Robotic Snakes&amp;quot;. &#039;&#039;IEEE Control Systems Magazine&#039;&#039; (Feb 2002): 66.&amp;lt;ref/&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advantages / Disadvantages of Robotic Snake Motion ==&lt;br /&gt;
&lt;br /&gt;
===Advantages===&lt;br /&gt;
&lt;br /&gt;
Many robots are limited by the use of motorized wheels. However, there are many advantages for building a robot that mimics the motion of a snake. Several advantages for movement of snake robot are listed below:&lt;br /&gt;
&lt;br /&gt;
*Move across uneven terrain since it is not dependent on wheels&lt;br /&gt;
*Possibly swim if water-proofed&lt;br /&gt;
*Move across soft ground such as sand since it can distribute its weight across wider area&lt;br /&gt;
&lt;br /&gt;
Also, from a systems standpoint, the snake robot can be very modular with many redundant segments. As a result, it is very easy to replace broken segments as well as shorten or lengthen the robot. &lt;br /&gt;
&lt;br /&gt;
===Disadvantages===&lt;br /&gt;
&lt;br /&gt;
Although there are many advantages for building a snake like robot, there are several disadvantages which are listed below:&lt;br /&gt;
&lt;br /&gt;
*Low power and movement efficiency&lt;br /&gt;
*High cost of actuators (servos or motors)&lt;br /&gt;
*Difficult to control high number of degrees of freedom&lt;br /&gt;
&lt;br /&gt;
Cite = Page 206&lt;br /&gt;
&lt;br /&gt;
== Robot Snake Motion ==&lt;br /&gt;
[[image:Serpentine_curves.jpg|thumb|300pix|right|Serpentine Curves]]&lt;br /&gt;
&lt;br /&gt;
Real snake motion does not follow specified equations. However, research has proven that the serpentine motion of a snake can be modeled with the following equations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x(s)= \int_{0}^{s} \cos (\zeta_\sigma) d\sigma&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;y(s)= \int_{0}^{s} \sin (\zeta_\sigma) d\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\zeta_\sigma= a \cos (b\sigma) +c\sigma &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the parameters &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; determine the shape of the serpentine motion. The graph shows how the parameters influence the serpentine curve. Basically, &#039;&#039;a&#039;&#039; changes the appearance of the curve, &#039;&#039;b&#039;&#039; changes the number of phases, and &#039;&#039;c&#039;&#039; changes the direction.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The serpentine curve can be modeled with a snake like robot by changing the relative angles between the snake robot segments using the following formula with the number of segments (n):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\phi_i = \alpha sin(\omega t +(i-1)\beta ) + \gamma, \left ( i=1, ..., n-1 \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;amp;alpha; , &amp;amp;beta; , and &amp;amp;gamma; are parameters used to characterize the serpentine curve and are dependent on &#039;&#039;a&#039;&#039;, &#039;&#039;b&#039;&#039;, and &#039;&#039;c&#039;&#039; as shown below:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\alpha = a \left | \sin \left ( \frac{\beta}{2} \right ) \right | &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\beta = \frac{b}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma = -\frac{c}{n} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The equations above for &amp;amp;phi;&amp;lt;sub&amp;gt;i&amp;lt;/sub&amp;gt;,&amp;amp;alpha;,&amp;amp;beta;, and &amp;amp;gamma; were used in this snake like robot as shown in the [[Robot Snake#PIC Code|code section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mechanical Design ==&lt;br /&gt;
[[image:FullSnake.jpg|thumb|right|The Snake]]&lt;br /&gt;
The robotic snake consists of a head segment and several body segments. The head segment houses the onboard microcontroller and xBee radio. The body segments house the servo motors and the batteries required to power each motor.  As the snake is designed to be modular, there is no limit to the number of body segments.  More segments will allow it to move more smoothly, while fewer segments will be easier to control.   For this design, seven body segments were used due to material limitations.&lt;br /&gt;
&lt;br /&gt;
Mechanically, the snake is designed to move in a serpentine motion, imitating the motion of a real snake.  As discussed above, real snakes move with anisotropic coefficients of friction. It is difficult to locate materials with this property, but passive wheels satisfy the friction requirements. The friction will be lower in the direction of rolling, thus providing the required difference in friction. The only problem with this approach is that the wheel may slide in the normal direction if the weight applied to the wheel is not sufficient. &lt;br /&gt;
&lt;br /&gt;
=== The Body Segments ===&lt;br /&gt;
[[image:Chasis.jpg|thumb|right|A Single Chasis Without a Servo]]&lt;br /&gt;
&lt;br /&gt;
Each of the body segments are identical and includes a chassis, a servo, a connector, standoffs and two passive wheels as can be seen in the picture. &lt;br /&gt;
&lt;br /&gt;
==== Chassis ====&lt;br /&gt;
&lt;br /&gt;
The base of the chassis is made from a thin (approx. 1/8th inch) piece of polycarbonate. The chassis must be wide enough to hold a servo motor with a AAA battery pack on each side and long enough for the servo and a standoff (the connection for the previous segment). The polycarbonate was cut into a rectangle to meet the specifications for our servo motor.  Five holes were then drilled in the rectangle, four to mount the servo and one for the standoff.  The holes are drilled to allow the servo to be located in the center of the chassis. &lt;br /&gt;
&lt;br /&gt;
==== Connector ====&lt;br /&gt;
&lt;br /&gt;
A connector was machined to attach to the servo horn of one body segment and to attach to the next segment&#039;s standoff. The length of this connector is about 3 inches and is just long enough to prevent collision between segments.  A shorter beam allows for greater torque.  This connection needs to be as tight as possible and the beam must be mounted perpendicular to the chassis.   &lt;br /&gt;
&lt;br /&gt;
[[image:ChasisUnderside.jpg|thumb|right|The Underside of a Chassis]]&lt;br /&gt;
&lt;br /&gt;
=== Standoffs ===&lt;br /&gt;
&lt;br /&gt;
Standoffs were used to attach the servo to the chassis and to attach the connector to the chassis. Two standoffs (1 in and 1/2 in) and several washers were used to make the connector parallel to the ground.&lt;br /&gt;
&lt;br /&gt;
==== Passive Wheels ====&lt;br /&gt;
[[image:Wheel.jpg|thumb|left|A Passive Wheel on the Dowel Pin]]&lt;br /&gt;
Passive wheels were mounted to the bottom of the chassis. Each wheel was made of a 3/4 inch pulley and an o-ring. The o-ring was used to increase friction with the ground.  The wheels have been set on polished metal dowel pins which allow the wheels to rotate more freely than when placed on wooden dowels.  The dowel pin axles were mounted (hot glue works but is not very strong) in the center of the segment. The center of the segment is not the center of the polycarbonate rectangle. Instead, the entire segment length is the distance from the standoff on one chassis to the center of the servo horn on the other. In this project, the length of the connector was made to be about half the length of the segment. Therefore, the wheels were placed at the same location as the stand off as can be seen in the image. The wheels are held in place with zip ties. &lt;br /&gt;
&lt;br /&gt;
==== Fully Assembled Body Segment ====&lt;br /&gt;
[[image:BuiltChasis.jpg|thumb|right|A Chasis Built Showing a Standoff and Batteries]]&lt;br /&gt;
A fully assembled chassis has a mounted servo and is connected to a segment on either side.  AAA batteries packs were attached to the sides of the motor with velcro to allow easy removal. The small electronic circuit board for each segment was mounted on the front of the motor to allow easy access to the switch.  (See Electronic Design for more information on the circuit board and batteries.&lt;br /&gt;
&lt;br /&gt;
=== The Head Segment ===&lt;br /&gt;
[[image:BallCaster.jpg|thumb|left|The Ball Caster Under the Front Segment]]&lt;br /&gt;
&lt;br /&gt;
The head segment is similar to the body segments except that it contains a PCB board with a PIC instead of a servo motor. The head segment is the same width but slightly longer than the body segment.  A ball caster was added to the front of the segment to help support the extra length and help the wheels stay on the ground.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Protection and Visual Appeal  ===&lt;br /&gt;
[[image:Housing.jpg|thumb|right|One Segment of the Housing]]&lt;br /&gt;
&lt;br /&gt;
As a final step, housing for each segment was created from 3&amp;quot; PVC pipe.  The pipe was cut into segments the same length as the chassis. The bottom of the pipe was cut off, allowing it to sit flat on the chassis. The housing provides a protective covering for the servo, batteries and electronics.  The pipe was attached with velcro straps which mounted under the chassis.  This housing can be easily removed to debug and to change batteries.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mechanical Debugging ===&lt;br /&gt;
&lt;br /&gt;
Wheels come off the ground:  Add washers to the standoffs to force the chassis to be parallel to the ground.&lt;br /&gt;
Wheels slide, but do not roll:  Increase frictionby either adding weight to the segment or changing the &amp;quot;tires&amp;quot; (the o-ring).&lt;br /&gt;
The segments slip when the servo rotates:  Tighten the screws for the connector standoffs, both above the beam and below the chassis.&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Electronics ==&lt;br /&gt;
&lt;br /&gt;
[[image:HookedUpBoard.jpg|thumb|right|A Complete Circuit Board on the Snake]]&lt;br /&gt;
[[image:PICBoard.jpg|thumb|right|The Electronics in the Head]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Needs description of servo - include discussion of how we aligned them (through code)&lt;br /&gt;
&lt;br /&gt;
Needs discussion on batteries.  Rechargeable vs Alkaline, 4 vs 5 etc.&lt;br /&gt;
&lt;br /&gt;
Needs circuit diagram for servo boards and/or picture&lt;br /&gt;
&lt;br /&gt;
Needs description of ribbon cable? (ie be careful with it)&lt;br /&gt;
&lt;br /&gt;
Needs reason for terminator&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PIC Code ==&lt;br /&gt;
===Servo Control===&lt;br /&gt;
The main function of the PIC microcontroller was to control multiple servos (seven in our case).  Timer1is set to overflow every 20 milliseconds and trigger an interrupt.  When the interrupt is triggered, Timer1&#039;scounter is set to the value held by TMR1_20MS, which will cause the interrupt to trigger again 20 ms later.  At the beginning of the interrupt, all the pins connected to the servos are set high.  While Timer1 is less than the value held by TMR1_2point25MS, Timer1 is polled, and the value is compared sequentially to the values in the RCservo array.  If the  value of Timer1 is greater than a value in RCservo, the the corresponding pin is set low.  After all the values have been compared, Timer1 is polled again and the process repeats until 2.25 ms have elapsed (when Timer1 &amp;gt; TMR1_2point25MS).  After all the servos signals have been sent, the values in the RCServo array are updated to prepare it for the next 20ms interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this method of timing the pulse trains has a lower resolution than using interrupts (see [http://peshkin.mech.northwestern.edu/pic/code/RCservoSoft/RCservoSoft.c RCservoSoft.c]), it allows one to add and remove servos more easily and preserve the 20ms interrupt.  With a 40MHz clock, &lt;br /&gt;
&lt;br /&gt;
===Serial Communication===&lt;br /&gt;
The PIC communicates serially with a XBee radio.  When a byte is received in the UART receive buffer, a high-priority interrupt is triggered.  The received byte is put into a switch-case statement, and the corresponding parameters are updated.&lt;br /&gt;
&lt;br /&gt;
== Results ==&lt;br /&gt;
&lt;br /&gt;
Initial Design Discussion? May not be necessary&lt;br /&gt;
&lt;br /&gt;
Discuss how it went well&lt;br /&gt;
&lt;br /&gt;
Link to you tube video (s)&lt;br /&gt;
&lt;br /&gt;
== Next Steps ==&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>AndrewLong</name></author>
	</entry>
</feed>