<?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=Matt+Watras</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=Matt+Watras"/>
	<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php/Special:Contributions/Matt_Watras"/>
	<updated>2026-06-07T02:20:44Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12908</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12908"/>
		<updated>2009-03-20T07:39:18Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you, kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|300px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a marionette that could move in a 2D plane via motors.  Our group decided to show movement by programming 5 different routines, each controlled by a button press. We used a 5 bar linkage with 2 RC Servos to motivate each arm with 2 degrees of freedom, and also added one RC Servo to each shoulder of the figure to allow it to rise off the ground, giving the appearance of moving its feet. Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll], whose joints we modified for easier motion. Also, we modeled the servo frame to resemble a stage for added effect. Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
[[Image:Marionette schematic.jpg|none|thumb|400px|]]&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. This not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Issues Encountered===&lt;br /&gt;
&lt;br /&gt;
* Method to move marionette arms with 2 degrees of freedom&lt;br /&gt;
** We originally considered a servo/track motor combination, where the track motor would move in one plane and the servo in a plane perpendicular to the track, thus combining to create 2 degrees of freedom. Switching to a linkage controlled by two fixed servos eliminated the construction headache associated with the servo/track method. A simple five-bar linkage was sufficient to provide our desired range of motion.&lt;br /&gt;
* Momentum build-up from fast and/or continued movement&lt;br /&gt;
** Since string connects the figure to the linkages, the figure is free to move independent of the linkages. This resulted in the marionette&#039;s arms rocking back and forth after the linkages stopped moving, which was particularly apparent after abrupt starts and stops. Slowing down the servo movement by changing position in small increments followed by delays, rather than changing position all at once, helped to alleviate this.&lt;br /&gt;
* Method to determine movement of marionette&lt;br /&gt;
** Our goal was not simply getting the figure to move, but to move in a controlled, predictable manner. Observing the servo positions while moving the linkages when the servos were unpowered let us derive simple formulas for movement in the X and Y planes.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Marionette_schematic.jpg&amp;diff=12907</id>
		<title>File:Marionette schematic.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Marionette_schematic.jpg&amp;diff=12907"/>
		<updated>2009-03-20T07:38:13Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12902</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12902"/>
		<updated>2009-03-20T07:08:38Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you, kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|300px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a marionette that could move in a 2D plane via motors.  Our group decided to show movement by programming 5 different routines, each controlled by a button press. We used a 5 bar linkage with 2 RC Servos to motivate each arm with 2 degrees of freedom, and also added one RC Servo to each shoulder of the figure to allow it to rise off the ground, giving the appearance of moving its feet. Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll], whose joints we modified for easier motion. Also, we modeled the servo frame to resemble a stage for added effect. Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. This not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Issues Encountered===&lt;br /&gt;
&lt;br /&gt;
* Method to move marionette arms with 2 degrees of freedom&lt;br /&gt;
** We originally considered a servo/track motor combination, where the track motor would move in one plane and the servo in a plane perpendicular to the track, thus combining to create 2 degrees of freedom. Switching to a linkage controlled by two fixed servos eliminated the construction headache associated with the servo/track method. A simple five-bar linkage was sufficient to provide our desired range of motion.&lt;br /&gt;
* Momentum build-up from fast and/or continued movement&lt;br /&gt;
** Since string connects the figure to the linkages, the figure is free to move independent of the linkages. This resulted in the marionette&#039;s arms rocking back and forth after the linkages stopped moving, which was particularly apparent after abrupt starts and stops. Slowing down the servo movement by changing position in small increments followed by delays, rather than changing position all at once, helped to alleviate this.&lt;br /&gt;
* Method to determine movement of marionette&lt;br /&gt;
** Our goal was not simply getting the figure to move, but to move in a controlled, predictable manner. Observing the servo positions while moving the linkages when the servos were unpowered let us derive simple formulas for movement in the X and Y planes.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12901</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12901"/>
		<updated>2009-03-20T07:07:43Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|300px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a marionette that could move in a 2D plane via motors.  Our group decided to show movement by programming 5 different routines, each controlled by a button press. We used a 5 bar linkage with 2 RC Servos to motivate each arm with 2 degrees of freedom, and also added one RC Servo to each shoulder of the figure to allow it to rise off the ground, giving the appearance of moving its feet. Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll], whose joints we modified for easier motion. Also, we modeled the servo frame to resemble a stage for added effect. Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. This not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Issues Encountered===&lt;br /&gt;
&lt;br /&gt;
* Method to move marionette arms with 2 degrees of freedom&lt;br /&gt;
** We originally considered a servo/track motor combination, where the track motor would move in one plane and the servo in a plane perpendicular to the track, thus combining to create 2 degrees of freedom. Switching to a linkage controlled by two fixed servos eliminated the construction headache associated with the servo/track method. A simple five-bar linkage was sufficient to provide our desired range of motion.&lt;br /&gt;
* Momentum build-up from fast and/or continued movement&lt;br /&gt;
** Since string connects the figure to the linkages, the figure is free to move independent of the linkages. This resulted in the marionette&#039;s arms rocking back and forth after the linkages stopped moving, which was particularly apparent after abrupt starts and stops. Slowing down the servo movement by changing position in small increments followed by delays, rather than changing position all at once, helped to alleviate this.&lt;br /&gt;
* Method to determine movement of marionette&lt;br /&gt;
** Our goal was not simply getting the figure to move, but to move in a controlled, predictable manner. Observing the servo positions while moving the linkages when the servos were unpowered let us derive simple formulas for movement in the X and Y planes.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12900</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12900"/>
		<updated>2009-03-20T06:54:43Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|300px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a marionette that could move in a 2D plane via motors.  Our group decided to show movement by programming 5 different routines, each controlled by a button press. We used a 5 bar linkage with 2 RC Servos to motivate each arm with 2 degrees of freedom, and also added one RC Servo to each shoulder of the figure to allow it to rise off the ground, giving the appearance of moving its feet. Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll], whose joints we modified for easier motion. Also, we modeled the servo frame to resemble a stage for added effect. Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12899</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12899"/>
		<updated>2009-03-20T06:52:08Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|300px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a marionette that could move in a 2D plane via motors.  Our group decided to show movement by programming 5 different routines, each controlled by a button press.  We used a 5 bar linkage with 2 RC Servos to motivate each arm with 2 degrees of freedom.  We also added one RC Servo to each shoulder of the figure to allow it to rise off the ground, giving the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll], whose joints we modified for easier motion. Also, we modeled the servo frame to resemble a stage for added effect.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12898</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12898"/>
		<updated>2009-03-20T06:46:09Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|300px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12897</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12897"/>
		<updated>2009-03-20T06:45:47Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|left|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12896</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12896"/>
		<updated>2009-03-20T06:45:28Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Team */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)                                    &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
[[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12894</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12894"/>
		<updated>2009-03-20T06:44:46Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|100px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12893</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12893"/>
		<updated>2009-03-20T06:44:28Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|120px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12891</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12891"/>
		<updated>2009-03-20T06:44:07Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “[http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12889</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12889"/>
		<updated>2009-03-20T06:43:34Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12888</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12888"/>
		<updated>2009-03-20T06:43:09Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12886</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12886"/>
		<updated>2009-03-20T06:42:20Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12884</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12884"/>
		<updated>2009-03-20T06:41:49Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Mechanical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|none|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12882</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12882"/>
		<updated>2009-03-20T06:40:17Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|none|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12881</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12881"/>
		<updated>2009-03-20T06:39:33Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|center|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12880</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12880"/>
		<updated>2009-03-20T06:39:17Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|left|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12878</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12878"/>
		<updated>2009-03-20T06:39:02Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Implementation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg|right|thumb|400px|Wired prototype]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12875</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12875"/>
		<updated>2009-03-20T06:37:31Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
===Implementation===&lt;br /&gt;
[[Image:Marionette Dsc04550.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=File:Marionette_Dsc04550.jpg&amp;diff=12873</id>
		<title>File:Marionette Dsc04550.jpg</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=File:Marionette_Dsc04550.jpg&amp;diff=12873"/>
		<updated>2009-03-20T06:37:04Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12862</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12862"/>
		<updated>2009-03-20T06:19:58Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Basic Build and Operation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run. Pull-down resistors connected from pins RA0-4 to ground ensure low values for all pins when the switches are not pushed.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12860</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12860"/>
		<updated>2009-03-20T06:18:41Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Primary Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
===Stage Construction===&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
===5 Bar Linkage Construction===&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
===Physical Limitation of Movement===&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
===Marionette Arm Construction===&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
===Marionette Back/Leg Movement===&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
===Finishing Touches of the Mechanical Design===&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;6&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;4.75K ohm 1/4W 1% metal film resistor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;475KXBK&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&amp;amp;name=475KXBK-ND Digikey]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12830</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12830"/>
		<updated>2009-03-20T06:00:21Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Primary Components */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor S3004]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12826</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12826"/>
		<updated>2009-03-20T05:58:40Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Results */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here].  We ended up able to map its movements onto an XY plane fairly closely. THis not only allowed us to create interesting dances, but also made it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement&lt;br /&gt;
*Add music that plays while dancing&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement&lt;br /&gt;
*Find ways to remove more string swaying&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
===YouTube video of our Marionette===&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
===Interesting Linkage Coupling Videos===&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
===Data Sheets===&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12820</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12820"/>
		<updated>2009-03-20T05:56:53Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Setup Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
===Setup Code===&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Example Routine===&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===Main Method===&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12815</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12815"/>
		<updated>2009-03-20T05:53:24Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula dance.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12814</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12814"/>
		<updated>2009-03-20T05:52:43Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section is our set up code, which contains everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12813</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12813"/>
		<updated>2009-03-20T05:51:51Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:TeamPicMarionette.JPG|right|thumb|350px|Team Photo  From left to right:  Victor, Jad, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 6 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-5 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section of code is our set up code.  This is everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12800</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12800"/>
		<updated>2009-03-20T05:44:39Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[http://hades.mech.northwestern.edu/wiki/index.php/ME_333_final_projects back to project list]&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:MarionetteTeam.JPG|right|thumb|350px|Team Photo  From left to right:  Jad, Victor, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 5 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-4 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RA0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section of code is our set up code.  This is everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reflection==&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12797</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12797"/>
		<updated>2009-03-20T05:44:07Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Marionette Wiki Page&lt;br /&gt;
[[Image:MarionettePicForIntro.JPG|thumb|right|350px|Here&#039;s looking at you kid]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:MarionetteTeam.JPG|right|thumb|200px|Team Photo  From left to right:  Jad, Victor, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor/Price&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All parts were available in the Mechatronics lab. The part number for the switch returned an error on the Jameco site.&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 5 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-4 on the PIC, and the supply voltage connects to the +5V regulated by the PIC PCB.&lt;br /&gt;
&lt;br /&gt;
The width of a pulse-width modulation signal determines the angle of each motor; this square wave is generated by code routines on the PIC provided by Prof. Peshkin, and output to the pins connected to the servos. Timed interrupts repeatedly set output pins low and high to create the square wave, and an argument passed to this function sets what percentage of the wave&#039;s period is high. This way, the each servo&#039;s position is set by a single numeric value- changing this value gradually over time can create the perception of continuous movement, from which we built our dancing routines.&lt;br /&gt;
&lt;br /&gt;
The push-button switches connect to the +5V supply and pins RC0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section of code is our set up code.  This is everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reflection==&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12776</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12776"/>
		<updated>2009-03-20T05:27:47Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Marionette Wiki Page&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)     [[Image:MarionetteTeam.JPG|right|thumb|200px|Team Photo  From left to right:  Jad, Victor, Matt.]]                               &lt;br /&gt;
* Victor Liu  (Mechanical Engineering)           &lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* [http://www.youtube.com/watch?v=eRolRlvKmyI Hula Dance]&lt;br /&gt;
* [http://www.youtube.com/watch?v=8yr8M590zaE Jumping Jack]&lt;br /&gt;
* [http://www.youtube.com/watch?v=IOnC6MSEzm8 Conducting]&lt;br /&gt;
* [http://www.youtube.com/watch?v=rxXlxNYYN7M Left arm pan while right foot tap then right arm pan while left foot taps]&lt;br /&gt;
* [http://www.youtube.com/watch?v=dvNr0Xz4hQ8 Left and right arm pointing up and going back to neutral position one after another while marching in place]&lt;br /&gt;
&lt;br /&gt;
Our puppet was a [http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe doll] that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.&lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators. A small button box made of PVC Expand foam sheets is attached to the side of the frame. The buttons are used to trigger the individual routines.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Front stage and descriptions&lt;br /&gt;
Image:stage_back.jpg|Back stage&lt;br /&gt;
Image:stage_side.jpg|Stage profile&lt;br /&gt;
Image:stage_cad.jpg|Initial design in CAD&lt;br /&gt;
Image:stage_cad_servos.jpg|Placement of servos in CAD&lt;br /&gt;
Image:stage_draft.jpg|General dimensions (inches)&lt;br /&gt;
Image:stage_buttons.jpg|Side-mounted button box&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|200px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|200px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
Six [http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor RC servos] are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no linkage could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|200px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC Expand foam sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
Not done yet.&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=1&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;Qty&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;Part&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Part No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Vendor&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;8-bit Microchip PIC microcontroller&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf 18F4520]&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www.microchipdirect.com/ProductSearch.aspx?Keywords=PIC18F4520 Microchip]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Futaba RC servo motor&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;S3004&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;[http://www3.towerhobbies.com/cgi-bin/wti0001p?&amp;amp;I=LXVW07 Tower Hobbies]&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;5&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Momentary push-button switch&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;26622PS&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Jameco&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 5 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-4 on the PIC, and the supply voltage is the +5V regulated by the PIC PCB. The width of a pulse-width modulation signal determines the angle of each motor; this signal is generated by code routines on the PIC and output to the associated pins on port D. The push-button switches connect to the +5V supply and pins RC0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section of code is our set up code.  This is everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reflection==&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
YouTube videos of our Marionette&lt;br /&gt;
*[http://www.youtube.com/watch?v=4_FOv3u4hiQ Full Routine w/ Curtain]&lt;br /&gt;
&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;br /&gt;
&lt;br /&gt;
Data Sheets&lt;br /&gt;
&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Actuators_Available_in_the_Mechatronics_Lab#Futaba_S3004_standard_ball_bearing_RC_servo_motor Futaba S3004 standard ball bearing RC servo motor]&lt;br /&gt;
*[http://hades.mech.northwestern.edu/wiki/index.php/Image:Gijoe_datasheet.jpg GIJoe Ninja Datasheet]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12688</id>
		<title>Marionette</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=Marionette&amp;diff=12688"/>
		<updated>2009-03-20T04:02:44Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Electrical Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Marionette Wiki Page&lt;br /&gt;
&lt;br /&gt;
==Team==&lt;br /&gt;
* Jad Carson  (Biomedical Engineering)&lt;br /&gt;
* Victor Liu  (Mechanical Engineering)&lt;br /&gt;
* Matt Watras (Electrical Engineering)&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The goal of this project was to make a Marionette that could move in a 2D plane via motors.  Our group decided to show movement by giving it 5 different routines with each one being controlled by a button press.  To give 2 degrees of freedom for the arms, we used a 5 bar linkage with 2 RC Servos for each arm.  We also added one RC Servo to each shoulder of the puppet to allow it to rise off the ground, giving it the appearance of moving its feet.  Our 5 routines were:&lt;br /&gt;
&lt;br /&gt;
* Hula Dance&lt;br /&gt;
* Jumping Jack&lt;br /&gt;
* Conducting&lt;br /&gt;
* Left arm pan while right foot tap then right arm pan while left foot taps&lt;br /&gt;
* Left and right arm pointing up and going back to neutral position one after another while marching in place&lt;br /&gt;
&lt;br /&gt;
Our puppet was a GI Joe doll that we loosened the arm joins of and we also built a stage for him to dance on.  While working on this project, we ran into a few obstacles that needed to be overcome.  First, we needed to decide how to mechanically move his arms so that he had 2 degrees of freedom.  Second, because we were making a marionette and therefore using string, we needed to take into account how his momentum affected his movement.  Finally, we needed to be able to control his movement so that we could have him go through our desired movement, such as pure X motion, pure Y motion, or a motion in between such as diagonal or a parabola.  &lt;br /&gt;
&lt;br /&gt;
==Mechanical Design==&lt;br /&gt;
The marionette is housed in a 24x15x13.5 inch frame constructed of mainly wood. This structure is intended to mimic a theater stage while providing a solid base for the puppet itself and the accompanying servos and electronics. Four plywood pieces are used to construct the frame and put together with wood screws. The top piece is about 4 inches shallower than the base pieces to accommodate the manipulators.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;gallery perrow=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
Image:stage_front.jpg|Stage Front&lt;br /&gt;
Image:stage_back.jpg|Stage Back&lt;br /&gt;
Image:stage_side.jpg|Stage Side&lt;br /&gt;
Image:stage_cad.jpg|CAD of initial design&lt;br /&gt;
Image:stage_cad_servos.jpg|CAD placement of servos&lt;br /&gt;
Image:stage_draft.jpg|General Dimensions&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:manipulator_positions.jpg|right|thumb|150px|Manipulator Positions]]&lt;br /&gt;
[[Image:manipulator_region.jpg|right|thumb|150px|Manipulator Region]]&lt;br /&gt;
&lt;br /&gt;
[[Image:gijoe_arm.jpg|left|thumb|180px|Arm Dismemberment and Reattachment]]&lt;br /&gt;
Six RC servos are used in this project. Four are used for the movement of the two arms, and two others are used to move the entire body. Arm movement is accomplished by incorporating a pair of 2 DOF parallel manipulators using the four servos. For each parallel manipulator, two servos placed 1.5 inches apart along the edge of the top platform provide actuation to a 5-bar linkage. Each section of the linkage is made the same length at 3 inches from the point of rotation. With this linkage geometry, the tip of the 5-bar linkage can sweep an area of the X-Y plane that is parallel to the front edge of the structure. Attached to the end tip of the 5-bar linkage is a string that is attached to the wrist of the puppet on the other end. A movement of the manipulator, therefore, generates a corresponding movement of the arm, just like an actual marionette.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Other types of complex linkages were explored that could provide a pure, straight-line motion. However, no type of linkages could provide both pure horizontal and vertical motions using two actuators. See the Links section for other linkages that we explored. &lt;br /&gt;
&lt;br /&gt;
[[Image:stage_top.jpg|right|thumb|180px|Top of the stage, showing the arrangement of the 6 servos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The max region of travel of the manipulator tip forms a curved rhombus. This region is limited by both the geometry of the linkages and the limitation of the servos. The rotational travel range for the servos is 180 degrees. Within this region, a Cartesian coordinate system could have been implemented that is a function of the rotational positions/velocities of the two servos. However due to the complex nature of such function, the X and Y coordinate of our manipulator simply follows the outline of the manipulator tip limit. For the tip to move in the X direction, both servos rotate in the same direction and at the same speed. For the Y direction, the servos would rotate in the opposite direction at the same speed. This implementation provides the largest travel given the manipulator range limit, and is also much less costly in terms of processor computation. Even with this simpler method, moving in a purely horizontal X direction in the Cartesian coordinate is implemented to a small degree, where the two servos are set to move at different speeds in the same direction. For this approach, the specific speeds of the servos are adjusted by trial-and-error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The GIJoe action figure, as manufactured, featured a much stiffer arm joints than desired for our purpose. Therefore, the arm joints are drilled out and re-tied together with strings, leaving a much looser arm movement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Initial design of the marionette included only the four front servos to move the arms. However, this provided a rather dull set of movements. Therefore, two extra servos are attached behind the first row of arm manipulating servos. These servos pull strings through an opening in the middle of the platform and are attached to the puppet’s shoulders. When the strings are relaxed, both feet of the puppet contact the ground. When both strings are pulled, the puppet will look like it is jumping. When one string is pulled, one foot will lift. If correctly correlated, sideways movement of the puppet can be achieved by lifting one foot and then the other (see the “Hula Dance” routine).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To finish off the construction, black PVC sheets are placed on the back and base of the frame to give it a “stage” look, which also masks the black strings quite well. In addition, a long piece of aluminum tubing is bent into shape and mounted on the back of the structure to provide support for the curtains. After the curtains are in place, none of the swing arms or electronics can be seen, giving an effect of a freestanding, free-moving puppet.&lt;br /&gt;
&lt;br /&gt;
==Electrical Design==&lt;br /&gt;
&lt;br /&gt;
Not done yet.&lt;br /&gt;
&lt;br /&gt;
===Primary Components===&lt;br /&gt;
&lt;br /&gt;
The primary electronic/electromechanical components of the marionette are:&lt;br /&gt;
&lt;br /&gt;
* 1 Microchip 18F4520 PIC microcontroller&lt;br /&gt;
* 5 Futaba S3004 standard ball bearing RC servo motors&lt;br /&gt;
* 5 Jameco 26622PS momentary push-button switches&lt;br /&gt;
&lt;br /&gt;
===Basic Build and Operation===&lt;br /&gt;
&lt;br /&gt;
The 5 Futaba RC servos, which control the marionette as described above, have 3 electrical connections: supply voltage, ground, and control signal. Control signals connect to pins RD0-4 on the PIC, and the supply voltage is the +5V regulated by the PIC PCB. The width of a pulse-width modulation signal determines the angle of each motor; this signal is generated by code routines on the PIC and output to the associated pins on port D. The push-button switches connect to the +5V supply and pins RC0-4 on the PIC. When pushed, a switch momentarily raises its associated pin high, which prompts the code of an associated routine to run.&lt;br /&gt;
&lt;br /&gt;
===Schematic===&lt;br /&gt;
&lt;br /&gt;
==Code==&lt;br /&gt;
&lt;br /&gt;
This first section of code is our set up code.  This is everything but the routines and main method.  &lt;br /&gt;
[[media:giJoe.c|Our full code is here]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;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;
&lt;br /&gt;
int16 RCservo[6];        // We used 6 servos.&lt;br /&gt;
int RCcount;&lt;br /&gt;
signed int16 i = 400;&lt;br /&gt;
int16 j = 400;&lt;br /&gt;
int m = 1;&lt;br /&gt;
int16 k = 400;&lt;br /&gt;
int16 n = 0;&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER2       // designates that this is the routine to call when timer2 overflows&lt;br /&gt;
void MyInterruptRoutine() {&lt;br /&gt;
 &lt;br /&gt;
   if (++RCcount &amp;gt;= 25) RCcount = 0;         // 25mS cycle to check all servos.  &lt;br /&gt;
 &lt;br /&gt;
   if ((RCcount &amp;amp; 3) == 0) {  // on the 4mS boundaries turn all the pins low&lt;br /&gt;
      output_low(PIN_D0);     // comment out the pins you don&#039;t want involved&lt;br /&gt;
      output_low(PIN_D1);&lt;br /&gt;
      output_low(PIN_D2);&lt;br /&gt;
      output_low(PIN_D3);&lt;br /&gt;
      output_low(PIN_D4);&lt;br /&gt;
      output_low(PIN_D5);&lt;br /&gt;
  &lt;br /&gt;
      set_timer3((int16) 60536 + RCservo[RCcount&amp;gt;&amp;gt;2]);     // yes 60536, not 65536.  Go high 4000uS (5000*0.8uS) from now, and sooner due to desired High period&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
#INT_TIMER3 fast           // &amp;quot;fast&amp;quot; allows Timer 3 to interrupt Timer 2&#039;s ISR&lt;br /&gt;
void InterruptTimer3() {   // this ISR is called when Timer 3 times out, to set one of the RC servo output pins high&lt;br /&gt;
   switch (RCcount&amp;gt;&amp;gt;2) {&lt;br /&gt;
      case 0:&lt;br /&gt;
         output_high(PIN_D0);     // This finishes setting up all our servos for use.&lt;br /&gt;
         break;&lt;br /&gt;
      case 1:&lt;br /&gt;
         output_high(PIN_D1);&lt;br /&gt;
         break;&lt;br /&gt;
      case 2:&lt;br /&gt;
         output_high(PIN_D2);&lt;br /&gt;
         break;&lt;br /&gt;
      case 3:&lt;br /&gt;
         output_high(PIN_D3);&lt;br /&gt;
         break;&lt;br /&gt;
      case 4:&lt;br /&gt;
         output_high(PIN_D4);&lt;br /&gt;
         break;&lt;br /&gt;
      case 5:&lt;br /&gt;
         output_high(PIN_D5);&lt;br /&gt;
         break;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoLeft(int16 x, int16 y) {  //This routine controls the two left arm servos in the X and Y direction.&lt;br /&gt;
   RCservo[0] = 1700 - x + y;       //Typing servoLeft(100,0) would move the arm in the X direction 100.&lt;br /&gt;
   RCservo[1] = 1700 - x - y;       //It uses the two servos of the arm together to move correctly.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoRight(int16 x, int16 y) {//This is the same as above except for the right arm.&lt;br /&gt;
   RCservo[2] = 1700 - x + y;&lt;br /&gt;
   RCservo[3] = 1700 - x - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void servoXY2(int16 x, int16 y) {  //This controls the feet.  X was for one shoulder and Y was for the other.&lt;br /&gt;
      RCservo[4] = 1400 + x ;&lt;br /&gt;
      RCservo[5] = 1900 - y;&lt;br /&gt;
      }&lt;br /&gt;
void servoArm(int16 x, int16 y){   //This is another way of controlling the left arm.  Instead of moving in a&lt;br /&gt;
      RCservo[0] = 1700 - x ;      //specific XY direction, using servoArm let you control the two servos for the&lt;br /&gt;
      RCservo[1] = 1700 - y;       //left arm individually, which made some movements easier to code for.&lt;br /&gt;
}&lt;br /&gt;
void servoArm2(int16 x, int16 y){  //This is the same as above but for the right arm.&lt;br /&gt;
      RCservo[2] = 1700 - x ;&lt;br /&gt;
      RCservo[3] = 1700 - y;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ZeroServos() {                 //This routine reset the servo positions back to neutral.  &lt;br /&gt;
      servoLeft(0,0);&lt;br /&gt;
      servoRight(0,0);&lt;br /&gt;
      servoXY2(0,0);&lt;br /&gt;
      i = 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section of code are our routines.  The routine showed here is our HulaHula routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void HulaHula(){                 //This is one of our routines, the Hula dance.  The if statements inside the&lt;br /&gt;
i=0;                             //while loops controlled the movement of the feet going up and down.&lt;br /&gt;
j=0;                             // k controlled how how each foot went and m controlled if the foot was going up&lt;br /&gt;
k=200;                           //or down.  i and j controlled the arm servos.  the delay_ms found in these routines &lt;br /&gt;
   while(i&amp;lt;700){                 //was to slow down the movements slightly.  this reduced the jerkyness which reduced &lt;br /&gt;
         servoArm(i,j);          //the swaying of the string so our movements were more controlled.&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(i,j);&lt;br /&gt;
         servoArm2(i,j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(k, 0);&lt;br /&gt;
         if(k &amp;gt; 2) m=2;&lt;br /&gt;
         if(k &amp;lt; 200) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
         }&lt;br /&gt;
   while(i&amp;lt;700){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i+1;&lt;br /&gt;
         j=j+1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
   delay_ms(500);&lt;br /&gt;
   while(i&amp;gt;0){&lt;br /&gt;
         servoArm(-i,-j);&lt;br /&gt;
         servoArm2(-i,-j);&lt;br /&gt;
         i=i-1;&lt;br /&gt;
         j=j-1;&lt;br /&gt;
         servoXY2(0, k);&lt;br /&gt;
         if(k &amp;gt; 200) m=2;&lt;br /&gt;
         if(k &amp;lt; 2) m = 1;&lt;br /&gt;
         if(m == 1) k=k+1;&lt;br /&gt;
         if(m == 2) k=k-1;&lt;br /&gt;
         delay_ms(1);&lt;br /&gt;
      }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After our routines, we have our Main method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void main() {&lt;br /&gt;
      setup_timer_2(T2_DIV_BY_4, 155, 16);       // clock at 16KHz; interrupt every 4*50nS * 4 * (77+1) * 16 = 1.0mS&lt;br /&gt;
      setup_timer_3(T3_INTERNAL | T3_DIV_BY_8); // Timer 3 is used for the High period for the RC servo signal, ticks every (4*50nS) * 4 = 0.8uS&lt;br /&gt;
&lt;br /&gt;
      enable_interrupts(INT_TIMER3);   &lt;br /&gt;
      enable_interrupts(INT_TIMER2);&lt;br /&gt;
      enable_interrupts(GLOBAL);&lt;br /&gt;
&lt;br /&gt;
   while (TRUE) {                   //This is the while loop in our main function.  it zeros the servos and then&lt;br /&gt;
          ZeroServos();             //waits for a button press.  When it gets a button press it does its&lt;br /&gt;
          if(input(PIN_A0))         //specified routine.&lt;br /&gt;
         {&lt;br /&gt;
            leftArmPoint();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A1))&lt;br /&gt;
         {&lt;br /&gt;
            HulaHula();&lt;br /&gt;
            HulaHula();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A2))&lt;br /&gt;
         {&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
            Jump();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A3))&lt;br /&gt;
         {&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
            Conduct();&lt;br /&gt;
         }&lt;br /&gt;
         if(input(PIN_A4))&lt;br /&gt;
         {&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
            Move4();&lt;br /&gt;
         }&lt;br /&gt;
         &lt;br /&gt;
      &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Results==&lt;br /&gt;
&lt;br /&gt;
Our robot marionette worked as we wanted it to.  The five routines we programmed into it showcased its ability to control each arm independently and in interesting movements through the XY plane.  We also showed the ability to control the arms and legs at the same time to develop more complicated looking patterns.  Our marionette going through its dances can be seen [http://www.youtube.com/watch?v=4_FOv3u4hiQ here]  We ended up able to map its movements onto an XY plane fairly closely which not only allowed to create interesting dances but also makes it easier to write new motions by just typing in coordinate pairs for our servoLeft() and servoRight() methods.&lt;br /&gt;
&lt;br /&gt;
===Next Steps===&lt;br /&gt;
*Enlarge the area of our XY plane of movement by trying different 5 bar linkage designs and servos.&lt;br /&gt;
*Add more Servos to the back/legs to create more options for movement.&lt;br /&gt;
*Add a rail and motor on the top to create 3D movement.&lt;br /&gt;
*Add music that plays while dancing.&lt;br /&gt;
*Try different types of input sensors, such as a way to map hand movement to puppet movement.&lt;br /&gt;
*Find ways to remove more string swaying.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Reflection==&lt;br /&gt;
&lt;br /&gt;
==Useful Links==&lt;br /&gt;
Interesting Linkage Coupling Videos&lt;br /&gt;
&lt;br /&gt;
*[http://www.youtube.com/watch?v=q12IV1MhQgc&amp;amp;NR=1 Tsebysev Mechanism]&lt;br /&gt;
*[http://www.youtube.com/watch?v=PtnvXDwMmgQ&amp;amp;feature=related Straight Line Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=U76Vg2vceA0&amp;amp;feature=related Chebysev&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=hSdW-i3nO1M&amp;amp;feature=related Peaucellier&#039;s Linkage]&lt;br /&gt;
*[http://www.youtube.com/watch?v=CufN43By79s Theo Jansen]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10448</id>
		<title>IR communication between PICs</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10448"/>
		<updated>2009-02-12T01:42:14Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Two PICs can easily communicate with one another using serial communication.  IR communication is a basic extension of this method which can be easily implemented with a microcontroller (PIC) through an IR Encoder/Decoder (endec) and an IR Transceiver.  The endec and transceiver used in this example support Serial IR (SIR) data rate, ranging from 9.6 kbps to 115.2 kbps.  The typical range of the transceiver is nominally from 2 inches to 2 feet and extends upwards of 12 feet.  The PIC, endec, and transceiver employed all support bidirectional use.  However, when a transceiver is transmitting it essentially blinds its receiver and therefore cannot attain true full-duplex communication; only half-duplex was used with the transceiver taking turns transmitting and receiving.&lt;br /&gt;
&lt;br /&gt;
When transmitting, the PIC sends the serial format data to the endec, which encodes (or modulates) it bit by bit.  This encoded data is then outputted as electrical pulses to the transceiver.  The transceiver converts these electrical pulses to IR light pulses.  When receiving, the transceiver receives IR light pulses (data), which are outputted as electrical pulses. The endec decodes (or demodulates) these electrical pulses, with the data then being transmitted by the endec UART back to the receiving PIC. This modulation/demodulation method is performed in accordance with the IrDA standard.&lt;br /&gt;
&lt;br /&gt;
Both the PIC and the endec used in this example were DIP packages, making them easy to prototype and inspect.  The transceiver, however, was a surface mount chip with an uncommon pin configuration (0.95 mm pitch), requiring a different mounting approach.  The simplest solution was to glue the transceiver onto one side of a similar-sized socket, and then soldering small wires from the pins of the transceiver onto the pins of the socket (see image). In the previous years, other mounting methods were tried, including the use of a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] or a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard]. However, these approaches saw limited success.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--We initially attempted to etch a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] for our circuit (see image).  However, due to the way this board is set up, this attempt only works with exact precision.  Unfortunately, due to the limited number of IR transceivers and copper-clad boards we had this approach led to a dead end.  Another possible solution to mount the IR transceiver was to use a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard].  These boards are more general and pre-fabricated for use with surface mount ICs (with a particular pitch or pin seperation).  Theoretically, both solutions will allow for connections to a solderless breadboard.  However, because none of the IR transceiver chips we could find came at the same pitch as the SchmartBoards, we could not use this approach.  Overall, since the IR transceiver chips did not come at standard pitches, we were unable to find a way to mount the IR chip.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
[[Image:IR_circuit.jpg|thumb|right|600px|Circuit Diagram]]&lt;br /&gt;
&lt;br /&gt;
The circuit diagram below shows a complete half-duplex IR communication circuit.  This circuit can either be used together with an identical circuit to communicate, with only one PIC transmitting at a time, or with a remote control.  The software on the PIC can be configured to respond to a variety of commands sent by the remote.  The electrical characteristics of the power supply and discrete components are given below.  Some of the ranges for the IR circuitry are also given below in parentheses.  In the circuit, there are two interfaces: the serial interface and the IR interface.&lt;br /&gt;
&lt;br /&gt;
===Serial Interface===&lt;br /&gt;
The serial interface is located between the PIC and the endec and sends data sequentially one bit at a time. The transmit (TX) and receive (RX) pins on the endec need to be connected between both ICs with a common ground.  The data passing between the two components on these lines have the standard 8-N-1 serial data format. 8-N-1 is a serial configuration in which there are 8 data bits, no parity bits and 1 stop bit. Data bits contain the information to be transmitted. A parity bit is a binary digit used to ensure data accuracy, while a stop bit is used to indicate the end of a data string. &lt;br /&gt;
&lt;br /&gt;
There is also a 16XCLK signal going to the endec from the PIC used to control the baud rate of the endec; that signal is a square wave pulse train at a frequency of 16*(the baud rate) and is generated in software. The &amp;lt;span style=&amp;quot;text-decoration: overline&amp;quot;&amp;gt;RESET&amp;lt;/span&amp;gt; signal on the endec could be controlled with software but is simply held high since the endec need not be reset.&lt;br /&gt;
&lt;br /&gt;
[[Image:Serial_ir_data_format.jpg|left|thumb|400px|Serial &amp;amp; IR Data Format]]&lt;br /&gt;
&lt;br /&gt;
===IR Interface===&lt;br /&gt;
The second interface — the IR interface — is located between the endec and the transceiver.  This interface is straightforward with the TXIR and RXIR pins of the endec connecting to the TXD and RXD pins of the transceiver, respectively, and also has a common ground.  The signals between these two components conform to the IrDA physical layer standard.  When a logic high or &#039;1&#039; is to be transmitted, a logic low will be sent to the transceiver.  When a logic low or &#039;0&#039; is to be transmitted, a logic high will be pulsed after 7-8 cycles of the 16XCLK signal for 3 cycles of the 16XCLK signal but no longer than 4 µs.&lt;br /&gt;
&lt;br /&gt;
===Optical Interface===&lt;br /&gt;
The optical interface refers to the actual IR energy being transmitted between two transceivers or a source and a receiver.  The optical signal is a modulated form of the signal between the Endec and the Transceiver at the Transceiver&#039;s carrier frequency, 38 kHz.  That means that when the Endec would transmit a pulse for 3 cycles at the 16XCLK frequency, the transceiver would start pulsing IR energy at 38 kHz until the pulse went low.  When the transceiver receive IR pulsed at 38 kHz, the duration of the IR pulses is the duration of the pulse sent to the Endec.&lt;br /&gt;
&lt;br /&gt;
===Electrical Characteristics===&lt;br /&gt;
&#039;&#039;Microcontroller ([http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V&lt;br /&gt;
*C&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; = 1µF&lt;br /&gt;
**V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; - Pin 11 &amp;amp; 32&lt;br /&gt;
**GND - Pin 12 &amp;amp; 31&lt;br /&gt;
**TX - Pin 25 (C6)&lt;br /&gt;
**RX - Pin 26 (C7)&lt;br /&gt;
**16XCLK - Pin 17 (C2/CCP1)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Encoder/Decoder ([http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf Microchip MCP2122-E/P])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V (1.8V-5.5V)&lt;br /&gt;
*C&amp;lt;sub&amp;gt;BYP&amp;lt;/sub&amp;gt; = 0.01µF&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Transceiver ([http://www.vishay.com/docs/82614/tfdu4300.pdf Vishay TFDU4300])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc1&amp;lt;/sub&amp;gt; = 5.0V (2.4V-5.5V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc2&amp;lt;/sub&amp;gt; = 5.0V (-0.3V-6.0V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;logic&amp;lt;/sub&amp;gt; = 5.0V (1.5V-5.5V)&lt;br /&gt;
*R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 47Ω&lt;br /&gt;
*C&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 0.1µF&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===	 &lt;br /&gt;
*IR Communication is only Half-Duplex (only one transceiver transmitting at a time)&lt;br /&gt;
*Transmission Distance maximum is about 12 feet (about 3ft in low power mode)&lt;br /&gt;
*Communication Speed can only go up to 115.2 kpbs&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
Example code for a simple IR communication receiver circuit:&lt;br /&gt;
&lt;br /&gt;
 /*&lt;br /&gt;
   ircomm.c Jennifer Breger, Brian Lesperance, Dan Pinkawa 2008-02-05&lt;br /&gt;
   Using the PIC&#039;s built-in UART, a counter continually is sent to one IR encoder/decoder.  Then&lt;br /&gt;
   the first IR encoder/decoder feeds its TXIR to the RXIR of a second IR encoder/decoder.  The &lt;br /&gt;
   second IR encoder/decoder then transmits back to the PIC what it is receiving.  When the&lt;br /&gt;
   transceiver circuit is properly mounted and inserted into the circuit, this code can be adapted&lt;br /&gt;
   for half-duplex communication w/ another IR communications circuit.&lt;br /&gt;
 */&lt;br /&gt;
 /*&lt;br /&gt;
    Edits by Jad Carson, Victor Liu, Matt Watras 2009-02-04&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=40000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 int timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program, receiver end&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int rx;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       rx = timed_getc();   // message from the PIC, and displays the value on the LEDs/Port D.&lt;br /&gt;
       output_d(rx);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Sample code for the transmitter sending a simple counting signal:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=40000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 int timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program, transmit end&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int i;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       for(i=0;i&amp;lt;16;i++) {&lt;br /&gt;
          putc(i);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
= External Links and Further Reading =&lt;br /&gt;
*[http://www.vishay.com/docs/82614/tfdu4300.pdf IR Transceiver (Vishay TFDU4300) Data Sheet]&lt;br /&gt;
&amp;lt;!--*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Transceiver Data Sheet]--&amp;gt;&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Encoder/Decoder (Microchip MCP2122) Data Sheet]&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html Copper-clad Board]&lt;br /&gt;
*[http://www.schmartboard.com/ Schmartboard (Prototyping boards for SMT)]&lt;br /&gt;
&lt;br /&gt;
== Relevant Technical Articles ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.commsdesign.com/showArticle.jhtml?articleID=192200654 Infrared communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Serial_communications Serial communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Surface_mount Surface mount technology]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/UART UART]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10447</id>
		<title>IR communication between PICs</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10447"/>
		<updated>2009-02-12T01:41:31Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
&lt;br /&gt;
Two PICs can easily communicate with one another using serial communication.  IR communication is a basic extension of this method which can be easily implemented with a microcontroller (PIC) through an IR Encoder/Decoder (endec) and an IR Transceiver.  The endec and transceiver used in this example support Serial IR (SIR) data rate, ranging from 9.6 kbps to 115.2 kbps.  The typical range of the transceiver is nominally from 2 inches to 2 feet and extends upwards of 12 feet.  The PIC, endec, and transceiver employed all support bidirectional use.  However, when a transceiver is transmitting it essentially blinds its receiver and therefore cannot attain true full-duplex communication; only half-duplex was used with the transceiver taking turns transmitting and receiving.&lt;br /&gt;
&lt;br /&gt;
When transmitting, the PIC sends the serial format data to the endec, which encodes (or modulates) it bit by bit.  This encoded data is then outputted as electrical pulses to the transceiver.  The transceiver converts these electrical pulses to IR light pulses.  When receiving, the transceiver receives IR light pulses (data), which are outputted as electrical pulses. The endec decodes (or demodulates) these electrical pulses, with the data then being transmitted by the endec UART back to the receiving PIC. This modulation/demodulation method is performed in accordance with the IrDA standard.&lt;br /&gt;
&lt;br /&gt;
Both the PIC and the endec used in this example were DIP packages, making them easy to prototype and inspect.  The transceiver, however, was a surface mount chip with an uncommon pin configuration (0.95 mm pitch), requiring a different mounting approach.  The simplest solution was to glue the transceiver onto one side of a similar-sized socket, and then soldering small wires from the pins of the transceiver onto the pins of the socket (see image). In the previous years, other mounting methods were tried, including the use of a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] or a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard]. However, these approaches saw limited success.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--We initially attempted to etch a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] for our circuit (see image).  However, due to the way this board is set up, this attempt only works with exact precision.  Unfortunately, due to the limited number of IR transceivers and copper-clad boards we had this approach led to a dead end.  Another possible solution to mount the IR transceiver was to use a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard].  These boards are more general and pre-fabricated for use with surface mount ICs (with a particular pitch or pin seperation).  Theoretically, both solutions will allow for connections to a solderless breadboard.  However, because none of the IR transceiver chips we could find came at the same pitch as the SchmartBoards, we could not use this approach.  Overall, since the IR transceiver chips did not come at standard pitches, we were unable to find a way to mount the IR chip.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
[[Image:IR_circuit.jpg|thumb|right|600px|Circuit Diagram]]&lt;br /&gt;
&lt;br /&gt;
The circuit diagram below shows a complete half-duplex IR communication circuit.  This circuit can either be used together with an identical circuit to communicate, with only one PIC transmitting at a time, or with a remote control.  The software on the PIC can be configured to respond to a variety of commands sent by the remote.  The electrical characteristics of the power supply and discrete components are given below.  Some of the ranges for the IR circuitry are also given below in parentheses.  In the circuit, there are two interfaces: the serial interface and the IR interface.&lt;br /&gt;
&lt;br /&gt;
===Serial Interface===&lt;br /&gt;
The serial interface is located between the PIC and the endec and sends data sequentially one bit at a time. The transmit (TX) and receive (RX) pins on the endec need to be connected between both ICs with a common ground.  The data passing between the two components on these lines have the standard 8-N-1 serial data format. 8-N-1 is a serial configuration in which there are 8 data bits, no parity bits and 1 stop bit. Data bits contain the information to be transmitted. A parity bit is a binary digit used to ensure data accuracy, while a stop bit is used to indicate the end of a data string. &lt;br /&gt;
&lt;br /&gt;
There is also a 16XCLK signal going to the endec from the PIC used to control the baud rate of the endec; that signal is a square wave pulse train at a frequency of 16*(the baud rate) and is generated in software. The &amp;lt;span style=&amp;quot;text-decoration: overline&amp;quot;&amp;gt;RESET&amp;lt;/span&amp;gt; signal on the endec could be controlled with software but is simply held high since the endec need not be reset.&lt;br /&gt;
&lt;br /&gt;
[[Image:Serial_ir_data_format.jpg|left|thumb|400px|Serial &amp;amp; IR Data Format]]&lt;br /&gt;
&lt;br /&gt;
===IR Interface===&lt;br /&gt;
The second interface — the IR interface — is located between the endec and the transceiver.  This interface is straightforward with the TXIR and RXIR pins of the endec connecting to the TXD and RXD pins of the transceiver, respectively, and also has a common ground.  The signals between these two components conform to the IrDA physical layer standard.  When a logic high or &#039;1&#039; is to be transmitted, a logic low will be sent to the transceiver.  When a logic low or &#039;0&#039; is to be transmitted, a logic high will be pulsed after 7-8 cycles of the 16XCLK signal for 3 cycles of the 16XCLK signal but no longer than 4 µs.&lt;br /&gt;
&lt;br /&gt;
===Optical Interface===&lt;br /&gt;
The optical interface refers to the actual IR energy being transmitted between two transceivers or a source and a receiver.  The optical signal is a modulated form of the signal between the Endec and the Transceiver at the Transceiver&#039;s carrier frequency, 38 kHz.  That means that when the Endec would transmit a pulse for 3 cycles at the 16XCLK frequency, the transceiver would start pulsing IR energy at 38 kHz until the pulse went low.  When the transceiver receive IR pulsed at 38 kHz, the duration of the IR pulses is the duration of the pulse sent to the Endec.&lt;br /&gt;
&lt;br /&gt;
===Electrical Characteristics===&lt;br /&gt;
&#039;&#039;Microcontroller ([http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V&lt;br /&gt;
*C&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; = 1µF&lt;br /&gt;
**V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; - Pin 11 &amp;amp; 32&lt;br /&gt;
**GND - Pin 12 &amp;amp; 31&lt;br /&gt;
**TX - Pin 25 (C6)&lt;br /&gt;
**RX - Pin 26 (C7)&lt;br /&gt;
**16XCLK - Pin 17 (C2/CCP1)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Encoder/Decoder ([http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf Microchip MCP2122-E/P])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V (1.8V-5.5V)&lt;br /&gt;
*C&amp;lt;sub&amp;gt;BYP&amp;lt;/sub&amp;gt; = 0.01µF&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Transceiver ([http://www.vishay.com/docs/82614/tfdu4300.pdf Vishay TFDU4300])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc1&amp;lt;/sub&amp;gt; = 5.0V (2.4V-5.5V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc2&amp;lt;/sub&amp;gt; = 5.0V (-0.3V-6.0V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;logic&amp;lt;/sub&amp;gt; = 5.0V (1.5V-5.5V)&lt;br /&gt;
*R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 47Ω&lt;br /&gt;
*C&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 0.1µF&lt;br /&gt;
&lt;br /&gt;
[[Image:copper_clad_board.jpg|right|thumb|400px|Copper-Clad Board with IR Transceiver]]		 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===	 &lt;br /&gt;
*IR Communication is only Half-Duplex (only one transceiver transmitting at a time)&lt;br /&gt;
*Transmission Distance maximum is about 12 feet (about 3ft in low power mode)&lt;br /&gt;
*Communication Speed can only go up to 115.2 kpbs&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
Example code for a simple IR communication receiver circuit:&lt;br /&gt;
&lt;br /&gt;
 /*&lt;br /&gt;
   ircomm.c Jennifer Breger, Brian Lesperance, Dan Pinkawa 2008-02-05&lt;br /&gt;
   Using the PIC&#039;s built-in UART, a counter continually is sent to one IR encoder/decoder.  Then&lt;br /&gt;
   the first IR encoder/decoder feeds its TXIR to the RXIR of a second IR encoder/decoder.  The &lt;br /&gt;
   second IR encoder/decoder then transmits back to the PIC what it is receiving.  When the&lt;br /&gt;
   transceiver circuit is properly mounted and inserted into the circuit, this code can be adapted&lt;br /&gt;
   for half-duplex communication w/ another IR communications circuit.&lt;br /&gt;
 */&lt;br /&gt;
 /*&lt;br /&gt;
    Edits by Jad Carson, Victor Liu, Matt Watras 2009-02-04&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=40000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 int timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program, receiver end&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int rx;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       rx = timed_getc();   // message from the PIC, and displays the value on the LEDs/Port D.&lt;br /&gt;
       output_d(rx);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Sample code for the transmitter sending a simple counting signal:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=40000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 int timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program, transmit end&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int i;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       for(i=0;i&amp;lt;16;i++) {&lt;br /&gt;
          putc(i);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
= External Links and Further Reading =&lt;br /&gt;
*[http://www.vishay.com/docs/82614/tfdu4300.pdf IR Transceiver (Vishay TFDU4300) Data Sheet]&lt;br /&gt;
&amp;lt;!--*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Transceiver Data Sheet]--&amp;gt;&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Encoder/Decoder (Microchip MCP2122) Data Sheet]&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520 Data Sheet]&lt;br /&gt;
*[http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html Copper-clad Board]&lt;br /&gt;
*[http://www.schmartboard.com/ Schmartboard (Prototyping boards for SMT)]&lt;br /&gt;
&lt;br /&gt;
== Relevant Technical Articles ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.commsdesign.com/showArticle.jhtml?articleID=192200654 Infrared communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Serial_communications Serial communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Surface_mount Surface mount technology]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/UART UART]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10093</id>
		<title>IR communication between PICs</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10093"/>
		<updated>2009-02-05T02:07:46Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: /* Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note: This wiki page does not describe a successful implementation of communication between an IR transceiver and a PIC.&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Two PICs can easily communicate with one another using serial communication.  IR communication is a basic extension of this method which can be easily implemented with a microcontroller (PIC) through an IR Encoder/Decoder (endec) and an IR Transceiver.  The endec and transceiver used in this example support Serial IR (SIR) data rate, ranging from 9.6 kbps to 115.2 kbps.  The typical range of the transceiver is nominally from 2 inches to 2 feet and extends upwards of 12 feet.  The PIC, endec, and transceiver employed all support bidirectional use.  However, when a transceiver is transmitting it essentially blinds its receiver and therefore cannot attain true full-duplex communication; only half-duplex was used with the transceiver taking turns transmitting and receiving.&lt;br /&gt;
&lt;br /&gt;
When transmitting, the PIC sends the serial format data to the endec, which encodes (or modulates) it bit by bit.  This encoded data is then outputted as electrical pulses to the transceiver.  The transceiver converts these electrical pulses to IR light pulses.  When receiving, the transceiver receives IR light pulses (data), which are outputted as electrical pulses. The endec decodes (or demodulates) these electrical pulses, with the data then being transmitted by the endec UART back to the receiving PIC. This modulation/demodulation method is performed in accordance with the IrDA standard.&lt;br /&gt;
&lt;br /&gt;
Both the PIC and the endec used in this example were DIP packages, making them easy to prototype and inspect.  The transceiver, however, was a surface mount chip with an uncommon pin configuration (0.95 mm pitch), requiring a different mounting approach.  We initially attempted to etch a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] for our circuit (see image).  However, due to the way this board is set up, this attempt only works with exact precision.  Unfortunately, due to the limited number of IR transceivers and copper-clad boards we had this approach led to a dead end.  Another possible solution to mount the IR transceiver was to use a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard].  These boards are more general and pre-fabricated for use with surface mount ICs (with a particular pitch or pin seperation).  Theoretically, both solutions will allow for connections to a solderless breadboard.  However, because none of the IR transceiver chips we could find came at the same pitch as the SchmartBoards, we could not use this approach.  Overall, since the IR transceiver chips did not come at standard pitches, we were unable to find a way to mount the IR chip.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
The circuit diagram below shows a complete half-duplex IR communication circuit.  This circuit can either be used together with an identical circuit to communicate, with only one PIC transmitting at a time, or with a remote control.  The software on the PIC can be configured to respond to a variety of commands sent by the remote.  The electrical characteristics of the power supply and discrete components are given below.  Some of the ranges for the IR circuitry are also given below in parentheses.  In the circuit, there are two interfaces: the serial interface and the IR interface.&lt;br /&gt;
&lt;br /&gt;
[[Image:Serial_ir_data_format.jpg|left|thumb|400px|Serial &amp;amp; IR Data Format]]&lt;br /&gt;
===Serial Interface===&lt;br /&gt;
The serial interface is located between the PIC and the endec and sends data sequentially one bit at a time. The transmit (TX) and receive (RX) pins on the endec need to be connected between both ICs with a common ground.  The data passing between the two components on these lines have the standard 8-N-1 serial data format. 8-N-1 is a serial configuration in which there are 8 data bits, no parity bits and 1 stop bit. Data bits contain the information to be transmitted. A parity bit is a binary digit used to ensure data accuracy, while a stop bit is used to indicate the end of a data string. &lt;br /&gt;
&lt;br /&gt;
There is also a 16XCLK signal going to the endec from the PIC used to control the baud rate of the endec; that signal is a square wave pulse train at a frequency of 16*(the baud rate) and is generated in software. The &amp;lt;span style=&amp;quot;text-decoration: overline&amp;quot;&amp;gt;RESET&amp;lt;/span&amp;gt; signal on the endec could be controlled with software but is simply held high since the endec need not be reset.&lt;br /&gt;
&lt;br /&gt;
===IR Interface===&lt;br /&gt;
The second interface — the IR interface — is located between the endec and the transceiver.  This interface is straightforward with the TXIR and RXIR pins of the endec connecting to the TXD and RXD pins of the transceiver, respectively, and also has a common ground.  The signals between these two components conform to the IrDA physical layer standard.  When a logic high or &#039;1&#039; is to be transmitted, a logic low will be sent to the transceiver.  When a logic low or &#039;0&#039; is to be transmitted, a logic high will be pulsed after 7-8 cycles of the 16XCLK signal for 3 cycles of the 16XCLK signal but no longer than 4 µs.&lt;br /&gt;
&lt;br /&gt;
===Optical Interface===&lt;br /&gt;
The optical interface refers to the actual IR energy being transmitted between two transceivers or a source and a receiver.  The optical signal is a modulated form of the signal between the Endec and the Transceiver at the Transceiver&#039;s carrier frequency, 38 kHz.  That means that when the Endec would transmit a pulse for 3 cycles at the 16XCLK frequency, the transceiver would start pulsing IR energy at 38 kHz until the pulse went low.  When the transceiver receive IR pulsed at 38 kHz, the duration of the IR pulses is the duration of the pulse sent to the Endec.&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_circuit.jpg|thumb|right|600px|Circuit Diagram]]&lt;br /&gt;
&lt;br /&gt;
===Electrical Characteristics===&lt;br /&gt;
&#039;&#039;Microcontroller ([http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V&lt;br /&gt;
*C&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; = 1µF&lt;br /&gt;
**V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; - Pin 11 &amp;amp; 32&lt;br /&gt;
**GND - Pin 12 &amp;amp; 31&lt;br /&gt;
**TX - Pin 25 (C6)&lt;br /&gt;
**RX - Pin 26 (C7)&lt;br /&gt;
**16XCLK - Pin 17 (C2/CCP1)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Encoder/Decoder ([http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf Microchip MCP2122-E/P])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V (1.8V-5.5V)&lt;br /&gt;
*C&amp;lt;sub&amp;gt;BYP&amp;lt;/sub&amp;gt; = 0.01µF&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Transceiver ([http://www.vishay.com/docs/82614/tfdu4300.pdf Vishay TFDU4300])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc1&amp;lt;/sub&amp;gt; = 5.0V (2.4V-5.5V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc2&amp;lt;/sub&amp;gt; = 5.0V (-0.3V-6.0V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;logic&amp;lt;/sub&amp;gt; = 5.0V (1.5V-5.5V)&lt;br /&gt;
*R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 47Ω&lt;br /&gt;
*C&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 0.1µF&lt;br /&gt;
&lt;br /&gt;
[[Image:copper_clad_board.jpg|right|thumb|400px|Copper-Clad Board with IR Transceiver]]		 &lt;br /&gt;
=== Surface Mount Prototyping ===	  &lt;br /&gt;
*Transceiver lead pitch = 0.95mm	 &lt;br /&gt;
*Multiple options for installation	 &lt;br /&gt;
**SchmartBoard	 &lt;br /&gt;
**Copper-clad board etching&lt;br /&gt;
**Microchip MCP212X Developer&#039;s Daughter Boards (suitable only for this specific IR application)&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===	 &lt;br /&gt;
*IR Communication is only Half-Duplex (only one transceiver transmitting at a time)&lt;br /&gt;
*Transmission Distance maximum is about 12 feet (about 3ft in low power mode)&lt;br /&gt;
*Communication Speed can only go up to 115.2 kpbs&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
Example code for a simple IR communication circuit w/o the use of a transceiver:&lt;br /&gt;
&lt;br /&gt;
 /*&lt;br /&gt;
   ircomm.c Jennifer Breger, Brian Lesperance, Dan Pinkawa 2008-02-05&lt;br /&gt;
   Using the PIC&#039;s built-in UART, a counter continually is sent to one IR encoder/decoder.  Then&lt;br /&gt;
   the first IR encoder/decoder feeds its TXIR to the RXIR of a second IR encoder/decoder.  The &lt;br /&gt;
   second IR encoder/decoder then transmits back to the PIC what it is receiving.  When the&lt;br /&gt;
   transceiver circuit is properly mounted and inserted into the circuit, this code can be adapted&lt;br /&gt;
   for half-duplex communication w/ another IR communications circuit.&lt;br /&gt;
 */&lt;br /&gt;
 /*&lt;br /&gt;
    Edits by Jad Carson, Victor Liu, Matt Watras 2009-02-04&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=40000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 int timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program, receiver end&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int rx;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       rx = timed_getc();   // message from the PIC, and displays the value on the LEDs/Port D.&lt;br /&gt;
       output_d(rx);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 // Main program, transmit end&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int i;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       for(i=0;i&amp;lt;16;i++) {&lt;br /&gt;
          putc(i);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
= External Links and Further Reading =&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Transceiver Data Sheet]&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Encoder/Decoder Data Sheet]&lt;br /&gt;
*[http://www.schmartboard.com/ Schmartboard (Prototyping boards for SMT)]&lt;br /&gt;
&lt;br /&gt;
== Relevant Technical Articles ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.commsdesign.com/showArticle.jhtml?articleID=192200654 Infrared communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Serial_communications Serial communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Surface_mount Surface mount technology]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/UART UART]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10092</id>
		<title>IR communication between PICs</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10092"/>
		<updated>2009-02-05T02:03:21Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note: This wiki page does not describe a successful implementation of communication between an IR transceiver and a PIC.&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Two PICs can easily communicate with one another using serial communication.  IR communication is a basic extension of this method which can be easily implemented with a microcontroller (PIC) through an IR Encoder/Decoder (endec) and an IR Transceiver.  The endec and transceiver used in this example support Serial IR (SIR) data rate, ranging from 9.6 kbps to 115.2 kbps.  The typical range of the transceiver is nominally from 2 inches to 2 feet and extends upwards of 12 feet.  The PIC, endec, and transceiver employed all support bidirectional use.  However, when a transceiver is transmitting it essentially blinds its receiver and therefore cannot attain true full-duplex communication; only half-duplex was used with the transceiver taking turns transmitting and receiving.&lt;br /&gt;
&lt;br /&gt;
When transmitting, the PIC sends the serial format data to the endec, which encodes (or modulates) it bit by bit.  This encoded data is then outputted as electrical pulses to the transceiver.  The transceiver converts these electrical pulses to IR light pulses.  When receiving, the transceiver receives IR light pulses (data), which are outputted as electrical pulses. The endec decodes (or demodulates) these electrical pulses, with the data then being transmitted by the endec UART back to the receiving PIC. This modulation/demodulation method is performed in accordance with the IrDA standard.&lt;br /&gt;
&lt;br /&gt;
Both the PIC and the endec used in this example were DIP packages, making them easy to prototype and inspect.  The transceiver, however, was a surface mount chip with an uncommon pin configuration (0.95 mm pitch), requiring a different mounting approach.  We initially attempted to etch a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] for our circuit (see image).  However, due to the way this board is set up, this attempt only works with exact precision.  Unfortunately, due to the limited number of IR transceivers and copper-clad boards we had this approach led to a dead end.  Another possible solution to mount the IR transceiver was to use a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard].  These boards are more general and pre-fabricated for use with surface mount ICs (with a particular pitch or pin seperation).  Theoretically, both solutions will allow for connections to a solderless breadboard.  However, because none of the IR transceiver chips we could find came at the same pitch as the SchmartBoards, we could not use this approach.  Overall, since the IR transceiver chips did not come at standard pitches, we were unable to find a way to mount the IR chip.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
The circuit diagram below shows a complete half-duplex IR communication circuit.  This circuit can either be used together with an identical circuit to communicate, with only one PIC transmitting at a time, or with a remote control.  The software on the PIC can be configured to respond to a variety of commands sent by the remote.  The electrical characteristics of the power supply and discrete components are given below.  Some of the ranges for the IR circuitry are also given below in parentheses.  In the circuit, there are two interfaces: the serial interface and the IR interface.&lt;br /&gt;
&lt;br /&gt;
[[Image:Serial_ir_data_format.jpg|left|thumb|400px|Serial &amp;amp; IR Data Format]]&lt;br /&gt;
===Serial Interface===&lt;br /&gt;
The serial interface is located between the PIC and the endec and sends data sequentially one bit at a time. The transmit (TX) and receive (RX) pins on the endec need to be connected between both ICs with a common ground.  The data passing between the two components on these lines have the standard 8-N-1 serial data format. 8-N-1 is a serial configuration in which there are 8 data bits, no parity bits and 1 stop bit. Data bits contain the information to be transmitted. A parity bit is a binary digit used to ensure data accuracy, while a stop bit is used to indicate the end of a data string. &lt;br /&gt;
&lt;br /&gt;
There is also a 16XCLK signal going to the endec from the PIC used to control the baud rate of the endec; that signal is a square wave pulse train at a frequency of 16*(the baud rate) and is generated in software. The &amp;lt;span style=&amp;quot;text-decoration: overline&amp;quot;&amp;gt;RESET&amp;lt;/span&amp;gt; signal on the endec could be controlled with software but is simply held high since the endec need not be reset.&lt;br /&gt;
&lt;br /&gt;
===IR Interface===&lt;br /&gt;
The second interface — the IR interface — is located between the endec and the transceiver.  This interface is straightforward with the TXIR and RXIR pins of the endec connecting to the TXD and RXD pins of the transceiver, respectively, and also has a common ground.  The signals between these two components conform to the IrDA physical layer standard.  When a logic high or &#039;1&#039; is to be transmitted, a logic low will be sent to the transceiver.  When a logic low or &#039;0&#039; is to be transmitted, a logic high will be pulsed after 7-8 cycles of the 16XCLK signal for 3 cycles of the 16XCLK signal but no longer than 4 µs.&lt;br /&gt;
&lt;br /&gt;
===Optical Interface===&lt;br /&gt;
The optical interface refers to the actual IR energy being transmitted between two transceivers or a source and a receiver.  The optical signal is a modulated form of the signal between the Endec and the Transceiver at the Transceiver&#039;s carrier frequency, 38 kHz.  That means that when the Endec would transmit a pulse for 3 cycles at the 16XCLK frequency, the transceiver would start pulsing IR energy at 38 kHz until the pulse went low.  When the transceiver receive IR pulsed at 38 kHz, the duration of the IR pulses is the duration of the pulse sent to the Endec.&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_circuit.jpg|thumb|right|600px|Circuit Diagram]]&lt;br /&gt;
&lt;br /&gt;
===Electrical Characteristics===&lt;br /&gt;
&#039;&#039;Microcontroller ([http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V&lt;br /&gt;
*C&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; = 1µF&lt;br /&gt;
**V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; - Pin 11 &amp;amp; 32&lt;br /&gt;
**GND - Pin 12 &amp;amp; 31&lt;br /&gt;
**TX - Pin 25 (C6)&lt;br /&gt;
**RX - Pin 26 (C7)&lt;br /&gt;
**16XCLK - Pin 17 (C2/CCP1)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Encoder/Decoder ([http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf Microchip MCP2122-E/P])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V (1.8V-5.5V)&lt;br /&gt;
*C&amp;lt;sub&amp;gt;BYP&amp;lt;/sub&amp;gt; = 0.01µF&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Transceiver ([http://www.vishay.com/docs/82614/tfdu4300.pdf Vishay TFDU4300])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc1&amp;lt;/sub&amp;gt; = 5.0V (2.4V-5.5V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc2&amp;lt;/sub&amp;gt; = 5.0V (-0.3V-6.0V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;logic&amp;lt;/sub&amp;gt; = 5.0V (1.5V-5.5V)&lt;br /&gt;
*R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 47Ω&lt;br /&gt;
*C&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 0.1µF&lt;br /&gt;
&lt;br /&gt;
[[Image:copper_clad_board.jpg|right|thumb|400px|Copper-Clad Board with IR Transceiver]]		 &lt;br /&gt;
=== Surface Mount Prototyping ===	  &lt;br /&gt;
*Transceiver lead pitch = 0.95mm	 &lt;br /&gt;
*Multiple options for installation	 &lt;br /&gt;
**SchmartBoard	 &lt;br /&gt;
**Copper-clad board etching&lt;br /&gt;
**Microchip MCP212X Developer&#039;s Daughter Boards (suitable only for this specific IR application)&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===	 &lt;br /&gt;
*IR Communication is only Half-Duplex (only one transceiver transmitting at a time)&lt;br /&gt;
*Transmission Distance maximum is about 12 feet (about 3ft in low power mode)&lt;br /&gt;
*Communication Speed can only go up to 115.2 kpbs&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
Example code for a simple IR communication circuit w/o the use of a transceiver:&lt;br /&gt;
&lt;br /&gt;
 /*&lt;br /&gt;
   ircomm.c Jennifer Breger, Brian Lesperance, Dan Pinkawa 2008-02-05&lt;br /&gt;
   Using the PIC&#039;s built-in UART, a counter continually is sent to one IR encoder/decoder.  Then&lt;br /&gt;
   the first IR encoder/decoder feeds its TXIR to the RXIR of a second IR encoder/decoder.  The &lt;br /&gt;
   second IR encoder/decoder then transmits back to the PIC what it is receiving.  When the&lt;br /&gt;
   transceiver circuit is properly mounted and inserted into the circuit, this code can be adapted&lt;br /&gt;
   for half-duplex communication w/ another IR communications circuit.&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=20000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 char timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int i;&lt;br /&gt;
    char rx;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 32, 16); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(16);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       for(i=0;i&amp;lt;16;i++){      // Counts up from 0 to 15 and transmits to the first Encoder/Decoder.&lt;br /&gt;
          putc(i);             // Listens to the second Encoder/Decoder, which is simply the original&lt;br /&gt;
          rx = timed_getc();   // message from the PIC, and displays the value on the LEDs/Port D.&lt;br /&gt;
          output_d((int8) rx);&lt;br /&gt;
          delay_ms(1000);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= External Links and Further Reading =&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Transceiver Data Sheet]&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Encoder/Decoder Data Sheet]&lt;br /&gt;
*[http://www.schmartboard.com/ Schmartboard (Prototyping boards for SMT)]&lt;br /&gt;
&lt;br /&gt;
== Relevant Technical Articles ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.commsdesign.com/showArticle.jhtml?articleID=192200654 Infrared communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Serial_communications Serial communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Surface_mount Surface mount technology]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/UART UART]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
	<entry>
		<id>https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10091</id>
		<title>IR communication between PICs</title>
		<link rel="alternate" type="text/html" href="https://hades.mech.northwestern.edu//index.php?title=IR_communication_between_PICs&amp;diff=10091"/>
		<updated>2009-02-05T02:02:07Z</updated>

		<summary type="html">&lt;p&gt;Matt Watras: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note: This wiki page does not describe a successful implementation of communication between an IR transceiver and a PIC.&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Two PICs can easily communicate with one another using serial communication.  IR communication is a basic extension of this method which can be easily implemented with a microcontroller (PIC) through an IR Encoder/Decoder (endec) and an IR Transceiver.  The endec and transceiver used in this example support Serial IR (SIR) data rate, ranging from 9.6 kbps to 115.2 kbps.  The typical range of the transceiver is nominally from 2 inches to 2 feet and extends upwards of 12 feet.  The PIC, endec, and transceiver employed all support bidirectional use.  However, when a transceiver is transmitting it essentially blinds its receiver and therefore cannot attain true full-duplex communication; only half-duplex was used with the transceiver taking turns transmitting and receiving.&lt;br /&gt;
&lt;br /&gt;
When transmitting, the PIC sends the serial format data to the endec, which encodes (or modulates) it bit by bit.  This encoded data is then outputted as electrical pulses to the transceiver.  The transceiver converts these electrical pulses to IR light pulses.  When receiving, the transceiver receives IR light pulses (data), which are outputted as electrical pulses. The endec decodes (or demodulates) these electrical pulses, with the data then being transmitted by the endec UART back to the receiving PIC. This modulation/demodulation method is performed in accordance with the IrDA standard.&lt;br /&gt;
&lt;br /&gt;
Both the PIC and the endec used in this example were DIP packages, making them easy to prototype and inspect.  The transceiver, however, was a surface mount chip with an uncommon pin configuration (0.95 mm pitch), requiring a different mounting approach.  We initially attempted to etch a [http://www.radioshack.com/sm-2-sided-copper-clad-pc-board--pi-2102495.html copper-clad board] for our circuit (see image).  However, due to the way this board is set up, this attempt only works with exact precision.  Unfortunately, due to the limited number of IR transceivers and copper-clad boards we had this approach led to a dead end.  Another possible solution to mount the IR transceiver was to use a [http://www.schmartboard.com/index.asp?page=products_so&amp;amp;id=54 SchmartBoard].  These boards are more general and pre-fabricated for use with surface mount ICs (with a particular pitch or pin seperation).  Theoretically, both solutions will allow for connections to a solderless breadboard.  However, because none of the IR transceiver chips we could find came at the same pitch as the SchmartBoards, we could not use this approach.  Overall, since the IR transceiver chips did not come at standard pitches, we were unable to find a way to mount the IR chip.&lt;br /&gt;
&lt;br /&gt;
== Circuit ==&lt;br /&gt;
The circuit diagram below shows a complete half-duplex IR communication circuit.  This circuit can either be used together with an identical circuit to communicate, with only one PIC transmitting at a time, or with a remote control.  The software on the PIC can be configured to respond to a variety of commands sent by the remote.  The electrical characteristics of the power supply and discrete components are given below.  Some of the ranges for the IR circuitry are also given below in parentheses.  In the circuit, there are two interfaces: the serial interface and the IR interface.&lt;br /&gt;
&lt;br /&gt;
[[Image:Serial_ir_data_format.jpg|left|thumb|400px|Serial &amp;amp; IR Data Format]]&lt;br /&gt;
===Serial Interface===&lt;br /&gt;
The serial interface is located between the PIC and the endec and sends data sequentially one bit at a time. The transmit (TX) and receive (RX) pins on the endec need to be connected between both ICs with a common ground.  The data passing between the two components on these lines have the standard 8-N-1 serial data format. 8-N-1 is a serial configuration in which there are 8 data bits, no parity bits and 1 stop bit. Data bits contain the information to be transmitted. A parity bit is a binary digit used to ensure data accuracy, while a stop bit is used to indicate the end of a data string. &lt;br /&gt;
&lt;br /&gt;
There is also a 16XCLK signal going to the endec from the PIC used to control the baud rate of the endec; that signal is a square wave pulse train at a frequency of 16*(the baud rate) and is generated in software. The &amp;lt;span style=&amp;quot;text-decoration: overline&amp;quot;&amp;gt;RESET&amp;lt;/span&amp;gt; signal on the endec could be controlled with software but is simply held high since the endec need not be reset.&lt;br /&gt;
&lt;br /&gt;
===IR Interface===&lt;br /&gt;
The second interface — the IR interface — is located between the endec and the transceiver.  This interface is straightforward with the TXIR and RXIR pins of the endec connecting to the TXD and RXD pins of the transceiver, respectively, and also has a common ground.  The signals between these two components conform to the IrDA physical layer standard.  When a logic high or &#039;1&#039; is to be transmitted, a logic low will be sent to the transceiver.  When a logic low or &#039;0&#039; is to be transmitted, a logic high will be pulsed after 7-8 cycles of the 16XCLK signal for 3 cycles of the 16XCLK signal but no longer than 4 µs.&lt;br /&gt;
&lt;br /&gt;
===Optical Interface===&lt;br /&gt;
The optical interface refers to the actual IR energy being transmitted between two transceivers or a source and a receiver.  The optical signal is a modulated form of the signal between the Endec and the Transceiver at the Transceiver&#039;s carrier frequency, 38 kHz.  That means that when the Endec would transmit a pulse for 3 cycles at the 16XCLK frequency, the transceiver would start pulsing IR energy at 38 kHz until the pulse went low.  When the transceiver receive IR pulsed at 38 kHz, the duration of the IR pulses is the duration of the pulse sent to the Endec.&lt;br /&gt;
&lt;br /&gt;
[[Image:IR_circuit.jpg|thumb|right|600px|Circuit Diagram]]&lt;br /&gt;
&lt;br /&gt;
===Electrical Characteristics===&lt;br /&gt;
&#039;&#039;Microcontroller ([http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf Microchip PIC18F4520])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V&lt;br /&gt;
*C&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; = 1µF&lt;br /&gt;
**V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; - Pin 11 &amp;amp; 32&lt;br /&gt;
**GND - Pin 12 &amp;amp; 31&lt;br /&gt;
**TX - Pin 25 (C6)&lt;br /&gt;
**RX - Pin 26 (C7)&lt;br /&gt;
**16XCLK - Pin 17 (C2/CCP1)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Encoder/Decoder ([http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf Microchip MCP2122-E/P])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;DD&amp;lt;/sub&amp;gt; = 5.0V (1.8V-5.5V)&lt;br /&gt;
*C&amp;lt;sub&amp;gt;BYP&amp;lt;/sub&amp;gt; = 0.01µF&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;IR Transceiver ([http://www.vishay.com/docs/82614/tfdu4300.pdf Vishay TFDU4300])&#039;&#039;&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc1&amp;lt;/sub&amp;gt; = 5.0V (2.4V-5.5V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;cc2&amp;lt;/sub&amp;gt; = 5.0V (-0.3V-6.0V)&lt;br /&gt;
*V&amp;lt;sub&amp;gt;logic&amp;lt;/sub&amp;gt; = 5.0V (1.5V-5.5V)&lt;br /&gt;
*R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 47Ω&lt;br /&gt;
*C&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 0.1µF&lt;br /&gt;
&lt;br /&gt;
[[Image:copper_clad_board.jpg|right|thumb|400px|Copper-Clad Board with IR Transceiver]]		 &lt;br /&gt;
=== Surface Mount Prototyping ===	  &lt;br /&gt;
*Transceiver lead pitch = 0.95mm	 &lt;br /&gt;
*Multiple options for installation	 &lt;br /&gt;
**SchmartBoard	 &lt;br /&gt;
**Copper-clad board etching&lt;br /&gt;
**Microchip MCP212X Developer&#039;s Daughter Boards (suitable only for this specific IR application)&lt;br /&gt;
&lt;br /&gt;
=== Limitations ===	 &lt;br /&gt;
*IR Communication is only Half-Duplex (only one transceiver transmitting at a time)&lt;br /&gt;
*Transmission Distance maximum is about 12 feet (about 3ft in low power mode)&lt;br /&gt;
*Communication Speed can only go up to 115.2 kpbs&lt;br /&gt;
&lt;br /&gt;
== Code ==&lt;br /&gt;
&lt;br /&gt;
Example code for a simple IR communication circuit w/o the use of a transceiver:&lt;br /&gt;
&lt;br /&gt;
 /*&lt;br /&gt;
   ircomm.c Jennifer Breger, Brian Lesperance, Dan Pinkawa 2008-02-05&lt;br /&gt;
   Using the PIC&#039;s built-in UART, a counter continually is sent to one IR encoder/decoder.  Then&lt;br /&gt;
   the first IR encoder/decoder feeds its TXIR to the RXIR of a second IR encoder/decoder.  The &lt;br /&gt;
   second IR encoder/decoder then transmits back to the PIC what it is receiving.  When the&lt;br /&gt;
   transceiver circuit is properly mounted and inserted into the circuit, this code can be adapted&lt;br /&gt;
   for half-duplex communication w/ another IR communications circuit.&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
 #include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
 #fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
 #use delay (clock=20000000)&lt;br /&gt;
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                              // (up to 115,200 bps)&lt;br /&gt;
 &lt;br /&gt;
 // timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
 // character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
 // away.&lt;br /&gt;
 char timed_getc(void){&lt;br /&gt;
    long timeout;&lt;br /&gt;
    int timeout_error = FALSE;&lt;br /&gt;
    timeout = 0;&lt;br /&gt;
    while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
       delay_us(10);&lt;br /&gt;
    if (kbhit())&lt;br /&gt;
       return(getc());&lt;br /&gt;
    else {&lt;br /&gt;
       timeout_error = TRUE;&lt;br /&gt;
       return(0);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 // Main program&lt;br /&gt;
 void main(void){&lt;br /&gt;
    int i;&lt;br /&gt;
    char rx;&lt;br /&gt;
 &lt;br /&gt;
    setup_timer_2(T2_DIV_BY_1, 32, 16); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
    setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
    set_pwm1_duty(16);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
 &lt;br /&gt;
    while(TRUE){&lt;br /&gt;
       for(i=0;i&amp;lt;16;i++){      // Counts up from 0 to 15 and transmits to the first Encoder/Decoder.&lt;br /&gt;
          putc(i);             // Listens to the second Encoder/Decoder, which is simply the original&lt;br /&gt;
          rx = timed_getc();   // message from the PIC, and displays the value on the LEDs/Port D.&lt;br /&gt;
          output_d((int8) rx);&lt;br /&gt;
          delay_ms(1000);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Receive Code, Revised ==&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
  ircomm.c Jennifer Breger, Brian Lesperance, Dan Pinkawa 2008-02-05&lt;br /&gt;
  Using the PIC&#039;s built-in UART, a counter continually is sent to one IR encoder/decoder.  Then&lt;br /&gt;
  the first IR encoder/decoder feeds its TXIR to the RXIR of a second IR encoder/decoder.  The &lt;br /&gt;
  second IR encoder/decoder then transmits back to the PIC what it is receiving.  When the&lt;br /&gt;
  transceiver circuit is properly mounted and inserted into the circuit, this code can be adapted&lt;br /&gt;
  for half-duplex communication w/ another IR communications circuit.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;18f4520.h&amp;gt;&lt;br /&gt;
#fuses HS,NOLVP,NOWDT,NOPROTECT&lt;br /&gt;
#use delay (clock=40000000)&lt;br /&gt;
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=com_a) // Initializes the UART to 9600 bps &lt;br /&gt;
                                                             // (up to 115,200 bps)&lt;br /&gt;
&lt;br /&gt;
// timed_getc() checks whether data is ready to be read.  If it&#039;s not the function returns a null&lt;br /&gt;
// character.  If you simply use getc(), the PIC might get slowed up if the data isn&#039;t ready right&lt;br /&gt;
// away.&lt;br /&gt;
int timed_getc(void){&lt;br /&gt;
   long timeout;&lt;br /&gt;
   int timeout_error = FALSE;&lt;br /&gt;
   timeout = 0;&lt;br /&gt;
   while(!kbhit() &amp;amp;&amp;amp; (++timeout&amp;lt;50000))&lt;br /&gt;
      delay_us(10);&lt;br /&gt;
   if (kbhit())&lt;br /&gt;
      return(getc());&lt;br /&gt;
   else {&lt;br /&gt;
      timeout_error = TRUE;&lt;br /&gt;
      return(0);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Main program&lt;br /&gt;
void main(void){&lt;br /&gt;
   int rx;&lt;br /&gt;
&lt;br /&gt;
   setup_timer_2(T2_DIV_BY_1, 64, 8); // Provides a 151.3 kHz clock for the Encoder/Decoder, in   &lt;br /&gt;
   setup_ccp1(CCP_PWM);                // order for it to know the baud rate of the UART. Should be &lt;br /&gt;
   set_pwm1_duty(32);                  // closer to 16 * 9600 = 153.6 kHz but the error is tolerable&lt;br /&gt;
&lt;br /&gt;
   while(TRUE){&lt;br /&gt;
      rx = timed_getc();   // message from the PIC, and displays the value on the LEDs/Port D.&lt;br /&gt;
      output_d((int8) rx);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
= External Links and Further Reading =&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Transceiver Data Sheet]&lt;br /&gt;
*[http://ww1.microchip.com/downloads/en/DeviceDoc/21894c.pdf IR Encoder/Decoder Data Sheet]&lt;br /&gt;
*[http://www.schmartboard.com/ Schmartboard (Prototyping boards for SMT)]&lt;br /&gt;
&lt;br /&gt;
== Relevant Technical Articles ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.commsdesign.com/showArticle.jhtml?articleID=192200654 Infrared communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Serial_communications Serial communication]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Surface_mount Surface mount technology]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/UART UART]&lt;/div&gt;</summary>
		<author><name>Matt Watras</name></author>
	</entry>
</feed>