<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Principia Labs &#187; servo</title>
	<atom:link href="http://principialabs.com/tag/servo/feed/" rel="self" type="application/rss+xml" />
	<link>http://principialabs.com</link>
	<description>design, build, test, iterate.</description>
	<lastBuildDate>Sun, 28 Mar 2010 16:38:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Arduino-Python 4-Axis Servo Control</title>
		<link>http://principialabs.com/arduino-python-4-axis-servo-control/</link>
		<comments>http://principialabs.com/arduino-python-4-axis-servo-control/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 18:46:29 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[electronics]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[servo]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/?p=69</guid>
		<description><![CDATA[Although the Arduino platform is ideal for standalone applications, it really comes to life when interfaced with a PC. Connect Arduino to a personal computer and you instantly add a ton of versatility and processing power to your project. This tutorial will describe how to use Arduino to control a bank of four independent RC [...]]]></description>
			<content:encoded><![CDATA[<div class="video">
<embed src="http://blip.tv/play/wkew8g0C" type="application/x-shockwave-flash" width="380" height="310" allowscriptaccess="always" allowfullscreen="true"></embed>
</div>

<p>Although the <a href="http://arduino.cc/">Arduino</a> platform is ideal for standalone applications, it really comes to life when interfaced with a PC.  Connect Arduino to a personal computer and you instantly add a ton of versatility and processing power to your project.</p>

<p>This tutorial will describe how to use Arduino to control a bank of four independent RC servos with your PC (or Mac, or *nix Box), using a USB cable and a modular Arduino-Python software stack.</p>

<p>The following discussion builds upon concepts presented in two previous articles, &#8220;<a href="/arduino-serial-servo-control/">Arduino Serial Servo Control</a>&#8221; and &#8220;<a href="/joystick-control-of-a-servo/">Joystick Control of a Servo</a>.&#8221;  As always, comments, critiques, or suggestions for improving or adapting this code are welcome and appreciated.</p>

<h4>Project Outline</h4>

<p>The primary goal for this project was to create a software stack that allows simple and flexible control of multiple servos from any type of Python script.</p>

<p>The solution has two basic components: (1) an Arduino sketch that waits for serial input from a connected PC, then moves each servo to its commanded position, and; (2) a Python module on the PC that opens the serial connection and formats the data packets expected by the Arduino.</p>

<p>Any other Python program written to sit on <em>top</em> of these two layers need not worry about the messy details of serial communication, but rather can just say something like, &#8220;Move servo #2 to 90 degrees.&#8221;  Or, more precisely:</p>

<pre><code>servo.move(2,90)
</code></pre>

<p>Easy, right?  Let&#8217;s get started.</p>

<p><span id="more-51"></span></p>

<h2>Part I:  Smoke, Mirrors, and Hand-Waving</h2>

<p>If you just want to get things up and running quickly, start here.  These instructions will get your servos connected and obeying every whim of your PC in no time.</p>

<h4>Hardware Setup</h4>

<p>Hardware for this project consists of an Arduino module, four <a href="http://www.horizonhobby.com/Products/Default.aspx?ProdID=JSP20050">JR Sport ST47</a> standard servos, and a breadboard to create the circuit.</p>

<p>The servos each have three wires: Ground (brown), Power (red) and Control (yellow).  Each of the Control wires will connect to a different digital pin on the Arduino board (pins 2 through 5 in our setup), and <em>all</em> of the Power and Ground wires will need to connect somehow to the 5V and Gnd pins.</p>

<div style="text-align:center;"><a href='http://principialabs.com/wp-content/uploads/arduino-breadboard.jpg'><img src="http://principialabs.com/wp-content/uploads/arduino-breadboard.thumbnail.jpg" alt="" title="Breadboard: click to enlarge" /></a></div>

<p>The simplest way to accomplish this is to create a &#8220;bus&#8221; bar along one of the breadboard&#8217;s edges, as shown in the photo above. Simply route the Arduino&#8217;s 5V and Gnd to a convenient area on the breadboard, and connect all the servos.</p>

<h4>Required Software: The Lower Layers</h4>

<p>To get the effects seen in the video above, you&#8217;ll need at least the following two programs.  Although this code is designed to control four servos, it also works as-is with <em>fewer</em> servos, and &#8212; with a few modifications &#8212; as many as twelve (or 48 with the <a href="http://arduino.cc/en/Main/ArduinoBoardMega">Arduino Mega</a>!).</p>

<p><strong>Download the code:</strong></p>

<div style="padding-left:20px;">

<p><del><b>MultipleServos.pde</b>: This is the Arduino sketch.  Copy and paste this code into your Arduino software and upload it to the board.</del></p>

<p><a href='http://principialabs.com/wp-content/uploads/MultipleSerialServoControl.pde'><b> MultipleSerialServoControl.pde</b></a>: [Updated 12/23/09] This is the NEW Arduino sketch, which uses the Arduino <a href="http://arduino.cc/en/Reference/Servo">Servo library</a> to make alterations <i>much</i> simpler.  You can control up to 12 servos using this code (with modifications) and most Arduino boards, or <i>up to 48 servos</i> using an Arduino Mega!  (See the code comments for specific details.)  This code should also solve most of the servo &#8220;jitter&#8221; issues mentioned in the comments below.  Copy and paste this code into your Arduino software and upload it to the board.  (Requires <a href="http://www.arduino.cc/en/Main/Software">Arduino 0017</a> or greater.)</p>

<p><a href='http://principialabs.com/wp-content/uploads/servo.py'><b>servo.py</b></a>: This is the Python module which talks directly to the above Arduino sketch.  This script requires the <a href="http://sourceforge.net/projects/pyserial/">pyserial</a> module, available from Sourceforge. Save this script on your PC wherever you like, just be sure to name it &#8220;servo.py&#8221;.</p>

</div>

<div class="help">
<b>New to Python?</b> Welcome!  Python is a versatile and fun language to learn, and it&#8217;s used by just about everyone, from newbies to NASA!  Check out the <a href="http://wiki.python.org/moin/BeginnersGuide">Beginner&#8217;s Guide</a>  to get your bearings, or get the full skinny at <a href="http://python.org/">python.org</a>.
</div>

<p><strong>Customize the code:</strong></p>

<p>Depending on your computer system and Arduino hardware setup, you may need to make a few modifications to the code.</p>

<p><strong>Arduino:</strong> In the &#8220;MultipleSerialServoContro&#8221; sketch, take note of the following variables and make adjustments as necessary for your setup.  See &#8220;<a href="/arduino-serial-servo-control/">Arduino Serial Servo Control</a>&#8221; for more details regarding the <code>minPulse</code> and <code>maxPulse</code> variables.  (If you&#8217;ve got standard RC servos attached to pins 2-5, you probably won&#8217;t have to change anything.)</p>

<pre><code>// Common servo setup values
int minPulse = 600;   // minimum servo position, us (microseconds)
int maxPulse = 2400;  // maximum servo position, us

// Attach each Servo object to a digital pin
servo1.attach(2, minPulse, maxPulse);
servo2.attach(3, minPulse, maxPulse);
servo3.attach(4, minPulse, maxPulse);
servo4.attach(5, minPulse, maxPulse);
</code></pre>

<p><strong>Python:</strong>  In the &#8220;servo.py&#8221; script, you&#8217;ll most likely need to change the value of the <code>usbport</code> variable, which tells Python how to find your Arduino (On Windows, it&#8217;ll be something like &#8216;COM5&#8242;. On a Mac, &#8216;/dev/tty.usbserial-xxxxx&#8217;.  On Linux, &#8216;/dev/ttyUSB0&#8242;.).  Try running <code>ls /dev/tty*</code> from a Mac or Linux terminal for a list of available ports.  [ToDo: Modify the script to make this step unnecessary.]</p>

<p><strong>Test the code:</strong></p>

<p>Once your hardware is set up and the software is installed, you can test the system&#8217;s basic functionality from the <a href="http://programming-crash-course.com/the_python_interactive_interpreter">Python interactive interpreter</a>, like so:</p>

<pre><code>~/path/to/servo.py$ python
&gt;&gt;&gt; import servo
&gt;&gt;&gt; servo.move(2,150)
</code></pre>

<p>The <code>servo.move()</code> method takes two arguments, both integers.  The first is the servo number you wish to move, 1-4 (or whatever).  The second is the commanded angular position of the servo horn, from 0-180 degrees.  So, if you want to move Servo #3 fully clockwise (180 degrees), you&#8217;ll type <code>servo.move(3,180)</code>.  Cake, baby!</p>

<h4>Optional Software: From Totally Geek to Totally Chic</h4>

<p>The following scripts are designed to leverage the functionality of the <code>servo.move()</code> method for simple and readable code.  Make sure these files reside in the same directory as &#8220;servo.py&#8221;.</p>

<ul style="list-style-type: none; padding-left: 20px;">

<li><a href='http://principialabs.com/wp-content/uploads/servodance.py'><b>servodance.py</b></a>:  A cascading effect that feels like watching a quarter spiral down one of those funnel-shaped wishing wells.</li><br />

<li><a href='http://principialabs.com/wp-content/uploads/servorandom.py'><b>servorandom.py</b></a>: The final servo sequence seen in the video, with individual servos moving to random positions and then waving &#8220;goodbye&#8221; in unison.</li><br />

<li><a href='http://principialabs.com/wp-content/uploads/servomarch.py'><b>servomarch.py</b></a>:  This one&#8217;s not in the video, but it&#8217;s a fun script to test individual and simultaneous movement of multiple servos.  Just set the number of servos to march (default is 4), and send them off!</li><br />

<li><a href='http://principialabs.com/wp-content/uploads/multijoystick.py'><b>multijoystick.py</b></a>: Allows joystick control of four servos, with each joystick axis controlling a single servo.  This script is the most complex, so try getting the first three working, then graduate to this one &#8212; it&#8217;s easier to troubleshoot problems that way.  <br/>[Note: This script also requires installation of the <a href="http://www.pygame.org/">pygame</a> module.]</li>

</ul>

<p>With any luck, you should now have everything up and running just like in the video!</p>

<h4>NEW: Adding Servos</h4>

<p><p>[Updated 12/23/09] If you&#8217;re using the <a href='http://principialabs.com/wp-content/uploads/MultipleSerialServoControl.pde'>new Arduino sketch</a>, you can easily add servos to your project by making a few simple additions to the code.  The beauty of this system is that <code>servo.py</code> can remain unchanged, and all of the higher-level Python scripts just need simple alterations to include whatever number of servos you decide to add.  This segment will outline how to change the Arduino sketch; changes to the Python scripts will be up to you!</p>

<p>There are three places in the <code>MultipleSerialServoControl</code> sketch where you&#8217;ll need to make additions, if you want to control more than four servos.  Each section of the code contains the comment &#8220;TO ADD SERVOS:&#8221; followed by a suggestion on what to add.  </p>

<p>First, add a Servo object for each additional servo:</p>

<pre name="code" class="arduino:nocontrols">
// Create a Servo object for each servo
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
// TO ADD SERVOS:
//   Servo servo5;
//   etc...
</pre>

<p>Second, assign a digital pin to each additional servo:</p>

<pre name="code" class="arduino:nocontrols">
  // Attach each Servo object to a digital pin
  servo1.attach(2, minPulse, maxPulse);
  servo2.attach(3, minPulse, maxPulse);
  servo3.attach(4, minPulse, maxPulse);
  servo4.attach(5, minPulse, maxPulse);
  // TO ADD SERVOS:
  //   servo5.attach(YOUR_PIN, minPulse, maxPulse);
  //   etc...
</pre>

<p>Third, create a new switch case for each additional servo:</p>

<pre name="code" class="arduino:nocontrols">
      // Assign new position to appropriate servo
      switch (servo) {
        case 1:
          servo1.write(pos);    // move servo1 to 'pos'
          break;
        case 2:
          servo2.write(pos);
          break;
        case 3:
          servo3.write(pos);
          break;
        case 4:
          servo4.write(pos);
          break;
   // TO ADD SERVOS:
   //     case 5:
   //       servo5.write(pos);
   //       break;
   // etc...
      }
</pre>

<p>After making changes, be sure to click the &#8220;Verify&#8221; button on your Arduino software to make sure there are no errors, then upload it to the board.  Test your changes by calling the <code>servo.move()</code> method from the Python interpreter.  That&#8217;s it!</p>

<div style="border-top:1px solid #ddd;margin:40px 140px;">
</div>

<h2>Part II:  Getting Down to Brass Tacks</h2>

<p>Next, let’s take a look under the hood to see how it all works.  If you&#8217;re the type that just wants to get things working and damn the details, <strong>STOP HERE</strong>.  Otherwise, continue on, and I&#8217;ll do my best to explain how the code &#8220;do what it do.&#8221;</p>

<h4>The Problem Set</h4>

<p>Asynchronous serial communication is not perfect.  Sometimes there are errors,  dropped packets, confusion.  Sometimes the mail does <em>not</em> get through.  In both of the previous two serial/servo projects, the Arduino expected only one byte from the PC, and in both cases that byte represented a commanded servo position &#8212; and nothing more.  If a byte was missed or skipped, it wasn&#8217;t a big deal, another one was sure to come along, and it was impossible to misinterpret.</p>

<p>This project presents a couple of new challenges.  First, we are controlling more than one servo, so the Arduino needs more than one command element for each move.  As we&#8217;ve seen above, it needs to know (at least) <em>which</em> servo to move, and <em>how much</em> to move it.  Secondly, we have the problem of communication.  This time, we&#8217;re sending <em>two</em> command elements for each move (servo number &amp; position), and these elements are clearly <em>not</em> interchangable. That is, if we want to send <code>servo.move(4,90)</code>, we need to make sure that Arduino knows that the &#8217;4&#8242; means &#8220;Servo #4&#8243; and the &#8217;90&#8242; means &#8220;90 degrees.&#8221;</p>

<p>Tom Igoe&#8217;s article, &#8220;<a href="http://www.tigoe.net/pcomp/code/serial-communication/interpreting-serial-data-bytes">Interpreting Serial Data</a>,&#8221; contains an excellent discussion of some of the problems involved in serial communication, and lists several issues that need to be addressed in every project, namely:</p>

<blockquote>
  <ol>
  <li>How many bytes am I sending? Am I receiving the same number?</li>
  <li>Did I get the bytes in the right order?</li>
  <li>Are my bytes part of a larger variable?</li>
  <li>Is my data getting garbled in transit?</li>
  </ol>
</blockquote>

<p>The Arduino&#8217;s <code>Serial.read()</code> function reads one byte of data at a time from its <em>serial buffer</em>.  Think of the serial buffer as a mailbox.  It&#8217;s a small (128 bytes) area of memory where incoming serial messages are stashed until the Arduino is ready to read them.  Every character we send from the PC to Arduino is one byte.  So, while we could send the Arduino something very unambiguous like, &#8220;Yeah, hi, Arduino, it&#8217;s the Linux Box again.  What&#8217;s happening?  If you could go ahead and move Servo #4 to the 90-degree position, that would be great.  Thaaanks,&#8221; (163 bytes) it&#8217;s obviously better if we can come up with something a little more terse.</p>

<p>However, as we&#8217;ve seen, if we just send over the characters &#8217;4&#8242;, &#8217;9&#8242;, and &#8217;0&#8242; &#8212; remember, each character is a byte &#8212; the Arduino might get confused.  This problem is amplified when more commands start stacking up in the buffer.  Let&#8217;s say now we command <code>servo.move(2,180)</code> and <code>servo.move(3,120)</code>.  Now the buffer should hold {4,9,0,2,1,8,0,3,1,2,0}, except&#8211;OOPS!&#8211;one of the bytes got dropped along the way, so now it holds {4,9,0,2,1,8,3,1,2,0}.  &#8220;Wait, which servo did you want me to move?&#8221;  You can clearly see a problem developing.</p>

<h4>Solution: Data Packets and Start Bytes</h4>

<p>Luckily, part of the solution is handled in the way Arduino communicates.  Arduino uses <a href="http://en.wikipedia.org/wiki/ASCII">ASCII</a> encoding to represent alphanumeric characters.  Each character sent over the wire is converted to the binary equivalent of a decimal value from 0 to 255.  [See this <a href="http://www.arduino.cc/en/Reference/ASCIIchart">conversion chart</a> for specifics.]</p>

<p>So, for example, if we send over the character &#8216;A&#8217;, Arduino recognizes this as its decimal value, &#8217;65&#8242;.  We won&#8217;t get too deep into this concept except to say that the implementation is <em>great</em> for our application, because as long as the values we&#8217;re sending are less than 255, they&#8217;ll fit neatly into one byte.  Since the largest value we send is 180, we only have to send two bytes per command.</p>

<p>Now, if you&#8217;ve looked at the ASCII conversion chart, you&#8217;ll recognize that doing this every time you want to send a command would be a real pain.  Also, trying to teach Python this chart would take up a lot of unnecessary code.  Thankfully, this problem is already solved for us with Python&#8217;s <code>chr()</code> function.  Wrap any decimal value from 0-255 in <code>chr()</code>, and you get back its ASCII equivalent.  A few examples:</p>

<pre><code>~$ python
&gt;&gt;&gt; chr(65)
'A'
&gt;&gt;&gt; chr(110)
'n'
&gt;&gt;&gt; chr(13)
'r'
&gt;&gt;&gt; chr(9)
't'
</code></pre>

<p>You get the idea, but notice that ASCII doesn&#8217;t just represent letters and numbers, but also symbols and other &#8220;control&#8221; or &#8220;non-printing&#8221; characters like line-feeds, returns, and tabs.</p>

<p>So, now if we want to send <code>servo.move(4,90)</code>, we only need <em>two</em> bytes, the ASCII equivalents of &#8217;4&#8242; and &#8217;90&#8242;, represented in Python as <code>chr(4)</code> and <code>chr(90)</code>, and interpreted by the Arduino sketch as, once again, simply &#8217;4&#8242; and &#8217;90&#8242;.  Easy!  [Seriously, if your brain explodes at this point, or you're bleeding from the ears, it's understandable.  I don't like it any more than you do, but stick with me, it'll all work out neatly in the end.]</p>

<p><strong>Packets, Headers, and Payloads</strong></p>

<p>Okay, great, now instead of just digits in Arduino&#8217;s serial buffer, we have meaningful values.  Part of the problem is solved, but we still haven&#8217;t addressed the issue of dropped or missing bytes.  That is, how will the Arduino know that a &#8217;4&#8242; is &#8220;Servo #4&#8243; and not &#8220;4 degrees&#8221; when pulling values out of a crowded buffer like {4,90,2,180,3,0,1,110} ?</p>

<p>The answer is <a href="http://computer.howstuffworks.com/question525.htm">data packets</a>.  Very simply, instead of just sending a long string of numbers to Arduino, we&#8217;ll send a very specific ordered message, a <em>packet</em> of values, that is intended to be read and interpreted <strong>as a whole</strong> and <strong>in order</strong>, or else discarded completely.</p>

<p>Now, the structure of a packet can be as simple or as complex as we need it to be, as you might have noticed if you followed that last link.  But all we really need is some means of ensuring that Arduino doesn&#8217;t confuse one value for another.</p>

<p>Essentially, our Python script needs to tell Arduino three things:</p>

<ol>
<li>Here comes a new servo command.</li>
<li>Servo number to move.</li>
<li>Commanded servo position.</li>
</ol>

<p>We&#8217;ve already been sending the last two elements, the servo number and position.  Here, we&#8217;re adding a third element, which we&#8217;ll call the <em>header</em> or the <em>start byte</em>.  Our header, like the rest of the data in our packet, will be just one byte long, and contain no real information other than the conceptual message, &#8220;I am a header.&#8221;</p>

<p>The <em>order</em> of this message is important.  Every packet sent over the wire, or read from the serial buffer, will now have the following format:</p>

<pre><code>(Header, Servo Number, Servo Position)
</code></pre>

<p>or, more tersely:</p>

<pre><code>(startbyte, servo, angle)
</code></pre>

<p>What to use as a startbyte?  Well, we&#8217;re only using the values from 0-180 as either our Servo Number or Servo Postion.  Any value from 181 to 255 would be unique.  We&#8217;ll use &#8217;255&#8242; just to make it obvious.  So, every packet will now look something like one of the following:</p>

<pre><code>(255, 1, 90)
(255, 2, 180)
(255, 3, 0)
</code></pre>

<p>And the Arduino&#8217;s serial buffer would look something like:</p>

<pre><code>{255,1,90,255,2,180,255,3,0}
</code></pre>

<p>Now, instead of reading byte after byte and hoping for the best, Arduino will <em>wait</em> until a minimum of three bytes arrive in the buffer, and then read the first byte to determine whether or not it is, in fact, a header (255).  If it&#8217;s not, Arduino skips that value, and moves on to the next byte without touching the servos.  When it finally sees a header, Arduino continues reading the next two bytes, in order, and assigning them to the Servo Number and the Servo Position, respectively.  If either of <em>those</em> two values is &#8217;255&#8242;, Arduino assumes something is wrong, and skips everything until it reads a new header.</p>

<p><strong>Side Note:  Authoritarian Flow Control</strong></p>

<p>&#8220;Now just a minute!&#8221; you&#8217;re saying.  &#8220;If that is the case, then <em>some</em> of the commands Python sends to the Arduino will be totally ignored!&#8221;  And you&#8217;re right.  This method of serial flow control is definitely one-way, with no error-checking.  Other methods, such as &#8220;call-and-response&#8221; or &#8220;<a href="http://itp.nyu.edu/physcomp/Labs/Serial">handshaking</a>&#8221; are much better at ensuring accuracy, since there&#8217;s a back-and-forth arrangement that can call for data to be re-sent in the event of dropped packets.  But the two-way protocol this method requires is <em>much</em> slower.</p>

<p>We have to make an engineering decision.  In our application, which is more important, accuracy or quick response?  It depends on exactly how you are using the servos, but if you consider say, a joystick-controlled robot or RC vehicle application, then clearly an immediate response and quick visual feedback is preferable to perfect accuracy.  If you command &#8220;turn right&#8221; with a joystick, and your vehicle doesn&#8217;t respond appropriately, you&#8217;ll just instinctively add more right stick input.</p>

<p>Perfect accuracy is not required.</p>

<h4>Writing the Code</h4>

<p>Very briefly, let&#8217;s look at how the above concepts are implemented in both the Python and Arduino software.</p>

<p><strong>Python Implementation</strong></p>

<p>Whenever we call the <code>servo.move()</code> method, the Python script <code>servo.py</code> handles the serial communication details using the <code>pyserial</code> module, and formats the arguments into the data packet outlined above.  The bare-bones version looks like this:</p>

<pre name="code" class="python:nocontrols">
#!/usr/bin/env python

import serial
usbport = '/dev/ttyUSB0'
ser = serial.Serial(usbport, 9600, timeout=1)

def move(servo, angle):
    if (0 <= angle <= 180):
        ser.write(chr(255))
        ser.write(chr(servo))
        ser.write(chr(angle))
    else:
        pass
</pre>

<p><strong>Arduino Implementation</strong></p>

<p>Arduino opens its own serial connection, waits for at least three bytes to fill the buffer, then starts reading:</p>

<pre name="code" class="arduino:nocontrols">
/** MultipleSerialServoControl.pde (bare bones) **/

void setup() {
  // Open the serial connection, 9600 baud
  Serial.begin(9600);
} 

void loop() 
{ 
  // Wait for serial input (min 3 bytes in buffer)
  if (Serial.available() > 2) {
    // Read the first byte
    startbyte = Serial.read();
    // If it's really the startbyte (255) ...
    if (startbyte == 255) {
      // ... then get the next two bytes
      for (i=0;i<2;i++) {
        userInput[i] = Serial.read();
      }
      // First byte = servo to move?
      servo = userInput[0];
      // Second byte = which position?
      pos = userInput[1];
      // Packet error checking and recovery
      if (pos == 255) { servo = 255; }
</pre>

<p>If Arduino gets a complete packet with header, servo, and angle values, it assigns the new position to the appropriate servo.  If the value of <code>servo</code> is not between 1 and 4 (or whatever maximum number of servos you specify), the loop exits without assigning any new values.  That's it!  The Arduino Servo library really makes servo control easy and painless.</p>

<pre name="code" class="arduino:nocontrols:firstline[26]">
      // Assign new position to appropriate servo
      switch (servo) {
        case 1:
          servo1.write(pos);    // move servo1 to 'pos'
          break;
        case 2:
          servo2.write(pos);
          break;
        case 3:
          servo3.write(pos);
          break;
        case 4:
          servo4.write(pos);
          break;
    }
  }
</pre>

<h4>Whew! We're Done.</h4>

<p>Well, if you've made it this far, congratulations: you're totally insane.  I hope the above dissertation helps at least one person better grasp these concepts, since it took me across many web pages and into several late nights to find the answers.  Good luck!</p>

<h4>References</h4>

<ol>
<li>Tom Igoe, <em><a href="http://www.oreilly.com/catalog/9780596510510/">Making Things Talk: Practical Methods for Connecting Physical Objects</a></em></li>
<li>Tom Igoe, "<a href="http://www.tigoe.net/pcomp/serial.shtml">Serial Communication</a>"</li>
<li>Tom Igoe, "<a href="http://www.tigoe.net/pcomp/serialdata.shtml">Interpreting Serial Data</a>"</li>
<li>Society of Robots, "<a href="http://www.societyofrobots.com/actuators_servos.shtml">Actuators and Servos</a>"</li>
<li>ITP Physical Computing, "<a href="http://itp.nyu.edu/physcomp/Labs/Servo">Servo Lab</a>"</li>
<li>ITP Physical Computing, "<a href="http://itp.nyu.edu/physcomp/Labs/Serial">Serial Lab</a>"</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/arduino-python-4-axis-servo-control/feed/</wfw:commentRss>
		<slash:comments>92</slash:comments>
		</item>
		<item>
		<title>Joystick Control of a Servo</title>
		<link>http://principialabs.com/joystick-control-of-a-servo/</link>
		<comments>http://principialabs.com/joystick-control-of-a-servo/#comments</comments>
		<pubDate>Thu, 27 Dec 2007 18:46:11 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[electronics]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[servo]]></category>

		<guid isPermaLink="false">http://principialabs.com/joystick-control-of-a-servo/</guid>
		<description><![CDATA[UPDATE: Please read Arduino-Python 4-Axis Servo Control for the most current anddetailed information on using a USB joystick to control one or more RC servos. Inspired by Armadillo Aerospace and their laptop-controlled Pixel rocket, I decided to figure out how to use an Arduino module to achieve wireless remote control of a flight vehicle. Along [...]]]></description>
			<content:encoded><![CDATA[<div class="help" style="margin: 10px 6px 24px 6px; text-align: center;"><strong>UPDATE:</strong>  Please read <a href="http://principialabs.com/arduino-python-4-axis-servo-control/">Arduino-Python 4-Axis Servo Control</a> for the most current and<br />detailed information on using a USB joystick to control one or more RC servos.</div>

<div class="video">
<embed src="http://blip.tv/play/wkeilE8A" type="application/x-shockwave-flash" width="380" height="300" allowscriptaccess="always" allowfullscreen="true"></embed>
</div>

<p>Inspired by Armadillo Aerospace and their laptop-controlled <a href="http://media.armadilloaerospace.com/wallpapers/PixelFlightWallpaper1.jpg">Pixel rocket</a>, I decided to figure out how to use an Arduino module to achieve wireless remote control of a flight vehicle.</p>

<p>Along the path to development, an achievable intermediate goal would be something like a wireless RC rover with a video camera, monitored and controlled with a laptop and joystick on a WiFi network.</p>

<p>Step one in the process is simple joystick control of a servo over a USB connection.  This project builds upon the process documented in &#8220;<a href="/arduino-serial-servo-control">Arduino Serial Servo Control</a>.&#8221;  I welcome any comments or suggestions for improving or adapting this code.</p>

<p><span id="more-43"></span></p>

<p><strong>Hardware</strong></p>

<p>The hardware setup is very simple, and is described in detail in the serial-servo article.  The <a href="http://www.google.com/products?q=jr+sport+st47+standard+servo">JR Sport ST47 standard servo</a> is wired directly to Arduino&#8217;s 5V power and ground, and the servo&#8217;s control wire is connected to Digital pin #2.  The Arduino module is connected to a PC (running Linux in our case) with a USB cable, and a standard USB joystick is also connected.</p>

<p><strong>Software</strong></p>

<p>The simple two-layer software stack includes a Python script for interpreting inputs from the joystick, and the Arduino sketch to await serial inputs from the Python script and pulse the servo.</p>

<p>Let&#8217;s start with the Python script.  This code lives on the PC, and requires the <a href="http://pyserial.sourceforge.net/">pyserial</a> and <a href="http://www.pygame.org/">pygame</a> modules to be installed, along with (obviously) Python&#8217;s standard library.  The <code>pygame</code> module is primarily designed for graphics game creation, but it has a set of very straightforward methods for interpreting joysticks and other non-standard input devices.  The <code>pyserial</code> module simply allows us to open a serial connection to the Arduino over a USB port.</p>

<p>The primary purpose of the Python script is to read and report on joystick inputs.  A gaming joystick may have six different axes and a multitude of buttons.  This script will sense inputs from each axis, and (if enabled) print the values of the stick positions.</p>

<p>Each joystick axis reports a range of decimal values between -1.0 and 1.0, with zero being the center position.  This script converts those values (from the X-axis) into round numbers between zero and 180 and assigns that value as a servo position.  Since the servo can travel through 180 degrees, each servo position value increments the servo horn by one degree, with the center at 90 degrees.  The integers 0-180 are then converted to ASCII characters and sent over the serial connection to the Arduino.</p>

<pre name="code" class="python">
#!/usr/bin/env python
#
# joystick-servo.py
#
# created 19 December 2007
# copyleft 2007 Brian D. Wendt
# http://principialabs.com/
#
# code adapted from:
# http://svn.lee.org/swarm/trunk/mothernode/python/multijoy.py
#
# NOTE: This script requires the following Python modules:
#  pyserial - http://pyserial.sourceforge.net/
#  pygame   - http://www.pygame.org/
# Win32 users may also need:
#  pywin32  - http://sourceforge.net/projects/pywin32/
#

import serial
import pygame

# allow multiple joysticks
joy = []

# Arduino USB port address (try "COM5" on Win32)
usbport = "/dev/ttyUSB0"

# define usb serial connection to Arduino
ser = serial.Serial(usbport, 9600)

# handle joystick event
def handleJoyEvent(e):
    if e.type == pygame.JOYAXISMOTION:
        axis = "unknown"
        if (e.dict['axis'] == 0):
            axis = "X"

        if (e.dict['axis'] == 1):
            axis = "Y"

        if (e.dict['axis'] == 2):
            axis = "Throttle"

        if (e.dict['axis'] == 3):
            axis = "Z"

        if (axis != "unknown"):
            str = "Axis: %s; Value: %f" % (axis, e.dict['value'])
            # uncomment to debug
            #output(str, e.dict['joy'])

            # Arduino joystick-servo hack
            if (axis == "X"):
                pos = e.dict['value']
                # convert joystick position to servo increment, 0-180
                move = round(pos * 90, 0)
                if (move < 0):
                    servo = int(90 - abs(move))
                else:
                    servo = int(move + 90)
                # convert position to ASCII character
                servoPosition = chr(servo)
                # and send to Arduino over serial connection
                ser.write(servoPosition)
                # uncomment to debug
                #print servo, servoPosition

    elif e.type == pygame.JOYBUTTONDOWN:
        str = "Button: %d" % (e.dict['button'])
        # uncomment to debug
        #output(str, e.dict['joy'])
        # Button 0 (trigger) to quit
        if (e.dict['button'] == 0):
            print "Bye!\n"
            ser.close()
            quit()
    else:
        pass

# print the joystick position
def output(line, stick):
    print "Joystick: %d; %s" % (stick, line)

# wait for joystick input
def joystickControl():
    while True:
        e = pygame.event.wait()
        if (e.type == pygame.JOYAXISMOTION or e.type == pygame.JOYBUTTONDOWN):
            handleJoyEvent(e)

# main method
def main():
    # initialize pygame
    pygame.joystick.init()
    pygame.display.init()
    if not pygame.joystick.get_count():
        print "\nPlease connect a joystick and run again.\n"
        quit()
    print "\n%d joystick(s) detected." % pygame.joystick.get_count()
    for i in range(pygame.joystick.get_count()):
        myjoy = pygame.joystick.Joystick(i)
        myjoy.init()
        joy.append(myjoy)
        print "Joystick %d: " % (i) + joy[i].get_name()
    print "Depress trigger (button 0) to quit.\n"

    # run joystick listener loop
    joystickControl()

# allow use as a module or standalone script
if __name__ == "__main__":
    main()
</pre>

<p>Now for the Arduino sketch.  This code merely waits for serial input from the PC, does a little math on the decimal values of the transmitted ASCII characters, then pulses the servo to the corresponding position.  If no new serial input is received from the PC (i.e., the joystick is not moved), then the Arduino will maintain the last known position of the servo horn with an identical pulsewidth every 20ms.  As always, the minPulse and maxPulse values should be tweaked to work with your particular servo model.</p>

<pre name="code" class="arduino">
/*
 * JoystickSerialServo
 * --------------
 * Servo control with a PC and Joystick
 *
 * Created 19 December 2007
 * copyleft 2007 Brian D. Wendt
 * http://principialabs.com/
 *
 * Adapted from code by Tom Igoe
 * http://itp.nyu.edu/physcomp/Labs/Servo
 */

/** Adjust these values for your servo and setup, if necessary **/
int servoPin     =  2;    // control pin for servo motor
int minPulse     =  600;  // minimum servo position
int maxPulse     =  2400; // maximum servo position
int refreshTime  =  20;   // time (ms) between pulses (50Hz)

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position
int pulseWidth;          // servo pulse width
int servoPosition;       // commanded servo position, 0-180 degrees
int pulseRange;          // max pulse - min pulse
long lastPulse   = 0;    // recorded time (ms) of the last pulse


void setup() {
  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
  pulseRange  = maxPulse - minPulse;
  centerServo = maxPulse - ((pulseRange)/2);
  pulseWidth  = centerServo;   // Give the servo a starting point (or it floats)
  Serial.begin(9600);
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
    // read the incoming byte:
    servoPosition = Serial.read();

    // compute pulseWidth from servoPosition
    pulseWidth = minPulse + (servoPosition * (pulseRange/180));

    // stop servo pulse at min and max
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
    if (pulseWidth < minPulse) { pulseWidth = minPulse; }

    // debug
    //Serial.println(servoPosition);
  }

  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servoPin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servoPin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}
</pre>

<p>This may not be the most elegant solution to the joystick servo control problem, but it does serve as a nice "Hello Servo" project, to let you see what's going on at the lower levels of input and output.</p>

<p>The next step in the process is to remove the USB cable to the Arduino, and control the servo by sending serial data over a WiFi or <a href="http://en.wikipedia.org/wiki/ZigBee">ZigBee</a> network.  Also, for a real remote robotics project, the code will need to be modified so that each joystick axis controls a separate servo, e.g. pitch, roll, yaw, and throttle.  Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/joystick-control-of-a-servo/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Arduino Serial Servo Control</title>
		<link>http://principialabs.com/arduino-serial-servo-control/</link>
		<comments>http://principialabs.com/arduino-serial-servo-control/#comments</comments>
		<pubDate>Sun, 09 Dec 2007 18:33:24 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[electronics]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[serial]]></category>
		<category><![CDATA[servo]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/arduino-serial-servo-control-2/</guid>
		<description><![CDATA[One of the cool features of the Arduino platform is its ability to talk to other electronic devices using standard protocols. The big draw of physical computing, in my opinion, is the power it gives you to affect a limitless range of real-world objects with your PC, rather than just boring old monitors and printers. [...]]]></description>
			<content:encoded><![CDATA[<div class="video">
<embed src="http://blip.tv/play/wkeg4hMA" type="application/x-shockwave-flash" width="380" height="300" allowscriptaccess="always" allowfullscreen="true"></embed>
</div>

<p>One of the cool features of the Arduino platform is its ability to talk to other electronic devices using standard protocols.  The big draw of physical computing, in my opinion, is the power it gives you to affect a limitless range of real-world objects with your PC, rather than just boring old monitors and printers.</p>

<p>This short tutorial will demonstrate one way to use Arduino to control a servo motor with a PC, using a USB cable and the Arduino&#8217;s serial library.  It will in no way attempt to be an introduction to asynchronous serial communication, since such topics are <a href="http://www.tigoe.net/pcomp/serial.shtml">better addressed elsewhere</a>.</p>

<p>RC servos are comprised of a DC motor mechanically linked to a potentiometer. <a href="http://principialabs.com/arduino-pulse-width-modulation">Pulse-width modulation</a> (PWM) signals sent to the servo are translated into position commands by electronics inside the servo. When the servo is commanded to rotate, the DC motor is powered until the potentiometer reaches the value corresponding to the commanded position.</p>

<p><span id="more-41"></span></p>

<p>A standard RC servo has three wires: Ground (black or brown), Power (red) and Control (orange, yellow or white) and will move based on pulses sent over the control wire.  The control pulses set the angle of the servo horn. The servo expects a pulse every 20 ms in order to gain correct information about the angle. The pulse width maps directly to the servo angle.  Most servos will rotate 180&deg;, and expect pulse widths between 1-2 ms or so.</p>

<div style="text-align: center;">
<img src="/files/servo-pwm.jpg" alt="Servo Control with PWM" /><br /><small>Image credit: <a href="http://www.societyofrobots.com/actuators_servos.shtml#control" alt="">Society of Robots</a></small>
</div>

<p>This project uses a <a href="http://www.horizonhobby.com/Products/Default.aspx?ProdID=JSP20050">JR Sport ST47 Standard servo</a>, which accepts an input voltage between 4.8 and 6 volts &#8212; perfect for the Arduino&#8217;s 5V output pin.  Connect the servo&#8217;s brown and red wires to the Arduino&#8217;s Gnd and 5V POWER pins, respectively (colored orange in the diagram below), and connect the servo&#8217;s orange control wire to the Arduino&#8217;s digital pin #2 (on the green row in the diagram).</p>

<div style="text-align: center;">
<img src="/files/arduino_board.png" alt="Arduino Diagram" /><br /><small>Image credit: <a href="http://www.arduino.cc/en/Guide/Board" alt="">Arduino.cc</a></small>
</div>

<p>Using the Arduino IDE, upload the following code to the board, which will allow you to control the position of the servo over a serial connection.  Pay particular attention to the variables <code>minPulse</code> and <code>maxPulse</code>, as these define the min and max pulse widths for your servo.  As mentioned earlier, most servos expect a pulse width between 1-2 ms, however, a range of 0.5 ms to 2.5 ms (500-2500&mu;s) may be required, depending on your servo.  Experiment as necessary.</p>

<pre name="code" class="arduino">
/*
 * NewSerialServo
 * --------------
 * Servo control from the Serial port
 *
 * Alteration of the control interface to use < and > keys
 * to slew the servo horn left and right.  Works best with
 * the Linux/Mac terminal "screen" program.
 *
 * Created 10 December 2007
 * copyleft 2007 Brian D. Wendt
 * http://principialabs.com/
 *
 * Adapted from code by Tom Igoe
 * http://itp.nyu.edu/physcomp/Labs/Servo
 */

/** Adjust these values for your servo and setup, if necessary **/
int servoPin     =  2;    // control pin for servo motor
int minPulse     =  600;  // minimum servo position
int maxPulse     =  2400; // maximum servo position
int turnRate     =  100;  // servo turn rate increment (larger value, faster rate)
int refreshTime  =  20;   // time (ms) between pulses (50Hz)

/** The Arduino will calculate these values for you **/
int centerServo;         // center servo position
int pulseWidth;          // servo pulse width
int moveServo;           // raw user input
long lastPulse   = 0;    // recorded time (ms) of the last pulse


void setup() {
  pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
  centerServo = maxPulse - ((maxPulse - minPulse)/2);
  pulseWidth = centerServo;   // Give the servo a starting point (or it floats)
  Serial.begin(9600);
  Serial.println("      Arduino Serial Servo Control");
  Serial.println("Press < or > to move, spacebar to center");
  Serial.println();
}

void loop() {
  // wait for serial input
  if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo = Serial.read();

    // ASCII '<' is 44, ASCII '>' is 46 (comma and period, really)
    if (moveServo == 44) { pulseWidth = pulseWidth - turnRate; }
    if (moveServo == 46) { pulseWidth = pulseWidth + turnRate; }
    if (moveServo == 32) { pulseWidth = centerServo; }

    // stop servo pulse at min and max
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
    if (pulseWidth < minPulse) { pulseWidth = minPulse; }

    // print pulseWidth back to the Serial Monitor (uncomment to debug)
    // Serial.print("Pulse Width: ");
    // Serial.print(pulseWidth);
    // Serial.println("us");   // microseconds
  }

  // pulse the servo every 20 ms (refreshTime) with current pulseWidth
  // this will hold the servo's position if unchanged, or move it if changed
  if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servoPin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servoPin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}

</pre>

<p>Once you&#8217;ve got the code uploaded, you&#8217;re ready to go!  You can send and receive serial data using the Arudino IDE&#8217;s Serial Monitor, or you can use a Linux terminal (as in the video) with the <code>screen</code> command, like so:</p>

<pre>
screen /dev/ttyUSB0 9600
</pre>

<p>The first element of the <code>screen</code> command specifies the USB port, and the second the serial baud rate (9600).  You may need to run <code>ls /dev/tty*</code> to find the correct USB port on your machine.</p>

<p>The theory behind this project can be extended to include a graphical user interface on the PC to control the servo motor, and maybe even the addition of an Ethernet connection for networked control.</p>

<p><strong>Update:</strong>  (10 Dec 2007)  <em>I wasn&#8217;t happy with the &#8220;Enter Servo Position (0-9):&#8221; interface shown in the video, so I revamped the code to allow left/right movements using the &lt; and > keys.  This new sketch is the one that is currently displayed here.  <a href="http://todbot.com/blog/spookyarduino/">Tod E. Kurt</a> already has a good implementation of the 0-9 angular-position concept if you prefer it.</em></p>

<div class="new"><b>New:</b> <em>Check out the <a href="/arduino-python-4-axis-servo-control/">Arduino-Python 4-Axis Servo Control</a> tutorial</em></div>

<p><strong>References</strong></p>

<ol>
<li>Wikipedia, &#8220;<a href="http://en.wikipedia.org/wiki/Servomechanism">Servomechanism</a>&#8220;</li>
<li>Society of Robots, &#8220;<a href="http://www.societyofrobots.com/actuators_servos.shtml">Actuators and Servos</a>&#8220;</li>
<li>ITP Physical Computing, &#8220;<a href="http://itp.nyu.edu/physcomp/Labs/Servo">Servo Lab</a>&#8220;</li>
<li>ITP Physical Computing, &#8220;<a href="http://itp.nyu.edu/physcomp/Labs/Serial">Serial Lab</a>&#8220;</li>
<li>Tom Igoe, &#8220;<a href="http://www.tigoe.net/pcomp/serial.shtml">Serial Communication</a>&#8220;</li>
<li>Tom Igoe, &#8220;<a href="http://www.tigoe.net/pcomp/serialdata.shtml">More on Serial Communication</a>&#8220;</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/arduino-serial-servo-control/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
