<?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; tutorial</title>
	<atom:link href="http://principialabs.com/tag/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>http://principialabs.com</link>
	<description>design, build, test, iterate.</description>
	<lastBuildDate>Sat, 13 Feb 2010 17:51:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Beginning SSH on Ubuntu</title>
		<link>http://principialabs.com/beginning-ssh-on-ubuntu/</link>
		<comments>http://principialabs.com/beginning-ssh-on-ubuntu/#comments</comments>
		<pubDate>Fri, 30 May 2008 01:49:02 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://principialabs.com/?p=102</guid>
		<description><![CDATA[So let&#8217;s say you have a private LAN running in your secret underground lab.  Maybe you&#8217;ve got a Linux box hardwired to a WiFi router, and maybe a Mac or Linux laptop floating around somewhere, and you need a quick way to transfer files or execute shell commands remotely.

What you need is SSH, the [...]]]></description>
			<content:encoded><![CDATA[<p>So let&#8217;s say you have a private <acronym title="Local Area Network">LAN</acronym> running in your secret underground lab.  Maybe you&#8217;ve got a Linux box hardwired to a WiFi router, and maybe a Mac or Linux laptop floating around somewhere, and you need a quick way to transfer files or execute shell commands remotely.</p>

<p>What you need is <a href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a>, the Secure Shell.  SSH is a powerful tool which allows secure remote login over insecure networks. It provides an encrypted terminal session with strong authentication of both the server and client using public-key cryptography.  This tutorial will cover the basics of SSH&#8217;s most useful features:</p>

<ul>
<li>Logging into a remote computer over a secure connection.</li>
<li>Transferring files and directories between computers over a secure connection.</li>
<li>Enabling public-key authentication.</li>
<li>Passwordless authentication for use with scripts and cron jobs.</li>
</ul>

<p>The following assumptions are made about the reader:</p>

<ul>
<li>You know what a terminal/command line/shell is and how to start a session.</li>
<li>You have at least a basic familiarity with Linux/Mac command-line syntax.</li>
<li>You&#8217;re on a private LAN with access to at least two Linux/Mac computers (or, you have a user account on a remote server that accepts SSH connections).</li>
</ul>

<p>As always, comments, corrections, and suggestions for improvement are appreciated.</p>

<h3>Installing OpenSSH</h3>

<p>The Ubuntu (and MacOS X) flavor of SSH is called <a href="http://www.openssh.org/">OpenSSH</a>, a free, open-source implementation of the <code>ssh</code> protocol.  It consists of two basic components, an <code>openssh-client</code> and an <code>openssh-server</code>.  SSH clients communicate with SSH servers over encrypted network connections.</p>

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

<p>The <code>openssh-client</code> software should already be installed by default on Ubuntu.  If you want to be able to accept SSH connections as well as request them, you&#8217;ll need the server software as well.  The easiest way to ensure you have both is simply to run:</p>

<pre><code>sudo apt-get install openssh-client openssh-server
</code></pre>

<h3>Using SSH to Log into a Remote Computer</h3>

<p>Once OpenSSH is installed, you can login to a remote SSH server by using the <code>ssh</code> command:</p>

<pre><code>ssh remoteuser@remotebox
</code></pre>

<p>where <code>remoteuser</code> is the username of the remote account you&#8217;re trying to access, and <code>remotebox</code> is the remote server&#8217;s hostname or IP address.</p>

<p>For example, if you know that your Kubuntu desktop box (now running <code>openssh-server</code>) has a user account named <code>joebanks</code> and that the IP address of that computer on your private LAN is <code>192.168.0.12</code>, you could login remotely to that account from your Linux/Mac laptop by typing:</p>

<pre><code>ssh joebanks@192.168.0.12
</code></pre>

<div class="help">
If you&#8217;re unsure of a computer&#8217;s local IP address, try running <code>ifconfig</code> on that machine.  This will display the status of the active network interfaces, and the local IP address of that device will be listed after <code>inet addr</code>.  It will most likely be in the form of <code>192.168.0.xx</code>.
</div>

<p>Or, if you&#8217;ve got a web hosting account that allows shell access (e.g., <a href="http://dreamhost.com/">DreamHost</a>) with a domain name like <code>cooldomain.com</code>, your syntax might look like:</p>

<pre><code>ssh joebanks@cooldomain.com
</code></pre>

<p>Now, the first time an SSH client encounters a new remote server, it will report that it&#8217;s never seen the machine before, by printing the following message:</p>

<pre><code>The authenticity of host 'remotebox (192.168.0.12)' can't be established.
RSA key fingerprint is 53:b4:ad:c8:51:17:99:4b:c9:08:ac:c1:b6:05:71:9b.
Are you sure you want to continue connecting (yes/no)?
</code></pre>

<p>This is just an extra security measure to ensure that you&#8217;re actually connecting to the machine you think you are.  If you type <code>yes</code> (the most common response), you&#8217;ll see the following:</p>

<pre><code>Warning: Permanently added 'remotebox' (RSA) to the list of known hosts.
</code></pre>

<p>Subsequent login attempts to this machine will omit the warning message.  You&#8217;ll then be asked for the <code>remoteuser</code>&#8217;s password:</p>

<pre><code>remoteuser@remotebox's password:
</code></pre>

<p>And after correctly entering it, like magic, you&#8217;ll be logged into the remote machine, and instead of your local machine&#8217;s command prompt, you&#8217;ll see the following:</p>

<pre><code>remoteuser@remotebox:~$
</code></pre>

<p>And, voila!  You can execute commands on the remote machine just as you would on your local box.  To close the connection to the remote server, type <code>exit</code>, or use <code>Ctrl-D</code>.</p>

<h3>Copying Files</h3>

<p>To transfer files and directories from your local machine to the remote server and vice-versa, you&#8217;ll use SSH&#8217;s &#8220;secure copy&#8221; command, or <code>scp</code>.  To copy a single file from your local machine to the server, use the following syntax:</p>

<pre><code>scp file.txt remoteuser@remotebox:/directory
</code></pre>

<p>where <code>file.txt</code> is the name of a file in the current directory of your local machine, <code>remoteuser@remotebox</code> is the username and hostname or IP address of the server (just like in the above <code>ssh</code> examples, and <code>/directory</code> is the directory path on the server where you want your file copied.</p>

<p>For example, if you want to copy the local <code>file.txt</code> to the <code>/home/joebanks/docs</code> directory on the server you logged into above, you&#8217;ll run the following command from a <em>local terminal session:</em></p>

<pre><code>scp file.txt joebanks@192.168.0.12:/home/joebanks/docs
</code></pre>

<div class="help">
By &#8220;local terminal session,&#8221; I mean that you DO NOT first <code>ssh</code> in to the remote computer and <i>then</i> run the <code>scp</code> command.  Secure copy opens the <code>ssh</code> tunnel on its own.  Since secure copy uses the <code>ssh</code> protocol for a secure connection, whenever you run the <code>scp</code> command, you&#8217;ll be prompted for a password (or passphrase) if the <code>ssh</code> connection requires it.
</div>

<p>You can be as verbose as you want with the local and remote filenames and directories, even changing the filename in the process, like so:</p>

<pre><code>scp ~/docs/oldfile.txt joebanks@192.168.0.12:/home/joebanks/docs/newfile.txt
</code></pre>

<p>To copy a file from the server to your local machine, use the following syntax:</p>

<pre><code>scp remoteuser@remotebox:file.txt /local/directory
</code></pre>

<p>where <code>remoteuser@remotebox</code> is the username and hostname or IP address of the server, <code>file.txt</code> is a file in the /home/remoteuser directory, and <code>/local/directory</code> is the local directory path into which the file will be copied.</p>

<p>Again, you can be as verbose as necessary, for example:</p>

<pre><code>scp joebanks@192.168.0.12:~/docs/newfile.txt /home/joe/downloads
</code></pre>

<h3>Copying Directories</h3>

<p>To copy an entire directory (and all of its contents) from the local machine to the remote server, use the recursive <code>-r</code> switch, like so:</p>

<pre><code>scp -r /local/directory remoteuser@remotebox:/remote/directory
</code></pre>

<p>where <code>/local/directory</code> is the path to the local directory you want copied, and <code>/remote/directory</code> is the remote directory <em>into which</em> you want the directory to be copied.</p>

<p>To copy an entire directory (and all of its contents) from the remote server to the local machine, use the following:</p>

<pre><code>scp -r remoteuser@remotebox:/remote/directory /local/directory
</code></pre>

<p>where <code>/remote/directory</code> is the path to the remote directory you want copied, and <code>/local/directory</code> is the local directory <em>into which</em> you want the directory to be copied.</p>

<h3>Stop Typing the Stupid IP Address All Day, Will You?</h3>

<p>By now you&#8217;re no doubt getting sick of typing <code>joebanks@192.168.0.12</code> or whatever. It sure would be nice to type something shorter. Let&#8217;s fix that.</p>

<p>OpenSSH uses a client configuration file, located at <code>~/.ssh/config</code>, to simplify some of the tedious typing associated with logging into remote machines.  To edit (or create) that file, we&#8217;ll use the nano text editor, but you can use vi, emacs, kate or whatever:</p>

<pre><code>nano ~/.ssh/config
</code></pre>

<p>The simplest configuration file might look something like this:</p>

<pre>
Host volcano
  HostName 192.168.0.12
</pre>

<p>This associates the Host <code>volcano</code> with the HostName (or IP address) <code>192.168.0.12</code>, so now to login you&#8217;ll only need to type:</p>

<pre><code>ssh joebanks@volcano
</code></pre>

<p>That&#8217;s cool, but let&#8217;s get a little more lazy, shall we?  How about this:</p>

<pre>
Host BigWoo
  HostName 192.168.0.12
  User joebanks
</pre>

<p>Now all we need to type is:</p>

<pre><code>ssh BigWoo
</code></pre>

<p>Far out!  You can add as much configuration data as you need to this Host, and as many different Hosts as you like.  And this shorthand will also work with all the <code>scp</code> examples:</p>

<pre><code>scp file.txt BigWoo:
</code></pre>

<p>To learn more visit the <a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh_config">OpenSSH docs</a>, or run <code>man ssh_config</code>.</p>

<h3>Public-Key Authentication</h3>

<p>To increase the security of your SSH session, or to set up passwordless authentication, you can enable SSH&#8217;s built-in <a href="http://en.wikipedia.org/wiki/Public-key_cryptography">public-key cryptography</a>.  Then, instead of entering the <code>remoteuser</code>&#8217;s password on each login attempt, SSH will initiate a challenge-and-response protocol which attempts to match an encrypted public key (stored on the server) with a protected private key (stored on the local machine).  This completely eliminates the need to send sensitive information (like a password) over the network, encrypted or not.</p>

<p>To generate a public/private key pair on your local machine, open a terminal and type:</p>

<pre><code>ssh-keygen -t dsa
</code></pre>

<p>You&#8217;ll see the following message:</p>

<pre><code>Generating public/private dsa key pair.
Enter file in which to save the key (~/.ssh/id_dsa):
</code></pre>

<p>Hit <code>Enter</code>.  This selects the default location.  Next you&#8217;ll see:</p>

<pre><code>Enter passphrase (empty for no passphrase):
</code></pre>

<p>Enter a secure passphrase, ideally something unique and unguessable.  Unlike a password, a passphrase is usually a phrase or complete sentence, with spaces and punctuation if you like.  The longer and more obscure the phrase, the stronger it is.</p>

<div class="help">
<b>Note:</b> It is also acceptable to just hit <code>Enter</code> at this point, thereby selecting <i>no passphrase.</i>  This can be appropriate in some instances (see below), but you should be aware that it is <i>not</i> as secure.  While <code>ssh</code> will still use an encrypted public/private keypair  (which is almost certainly more secure than typing the remote user&#8217;s password like you&#8217;ve been doing), anyone gaining access to your local account will thereby also gain unfettered access to any remote hosts which recognize your public key.
</div>

<p>After typing a passphrase and hitting <code>Enter</code>, you&#8217;ll see:</p>

<pre><code>Enter same passphrase again:
</code></pre>

<p>Enter the same passphrase again.  And finally:</p>

<pre><code>Your identification has been saved in ~/.ssh/id_dsa.
Your public key has been saved in ~/.ssh/id_dsa.pub.
The key fingerprint is:
42:ac:8a:81:31:81:e5:7b:d2:01:42:2d:64:32:0f:dd localuser@localbox
</code></pre>

<p>Now copy your public key, which is stored in the local file <code>~/.ssh/id_dsa.pub</code> to the remote machine, by running the following command from a <em>local terminal session:</em></p>

<pre><code>ssh-copy-id -i ~/.ssh/id_dsa.pub remoteuser@remotebox
</code></pre>

<p>You&#8217;ll be prompted for the <code>remoteuser</code>&#8217;s password one last time, and then you&#8217;ll see the message:</p>

<pre><code>Now try logging into the machine, with "ssh 'remoteuser@remotebox'", and check in:

  .ssh/authorized_keys

to make sure we haven't added extra keys that you weren't expecting.
</code></pre>

<div class="help">
<b>MacOSX Users:</b>  If the <code>ssh-copy-id</code> method doesn&#8217;t work with your version of OpenSSH, try the following command:
<p>
<code>cat ~/.ssh/id_dsa.pub | ssh remoteuser@remotebox 'cat >> .ssh/authorized_keys'</code>
</p>
Or, if the <code>~/.ssh</code> directory doesn&#8217;t yet exist on the remote machine, you can create the directory <i>and</i> copy the public key all in one swell foop, like so:
<p>
<code>cat ~/.ssh/id_dsa.pub | ssh remoteuser@remotebox 'mkdir .ssh; cat >> .ssh/authorized_keys'</code>
</p>
</div>

<p>Once the <code>~/.ssh/authorized_keys</code> file on the remote machine contains your public key, you&#8217;ll be prompted for your passphrase at each login attempt, rather than the <code>remoteuser</code>&#8217;s system password, like so:</p>

<pre><code>Enter passphrase for key '~/.ssh/id_dsa':
</code></pre>

<p>Finally, it&#8217;s a good idea to change the permissions of the <code>~/.ssh</code> directory and the <code>~/.ssh/id_dsa</code> file on your local machine, to disable any outside access to your private key.</p>

<pre><code>chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_dsa
</code></pre>

<h3>Passwordless Authentication for Automated Tasks</h3>

<p>You can use <code>ssh</code> and <code>scp</code> in shell scripts and cron jobs to automate repetitive tasks, such as remote backups of critical files.  To do so, however, you&#8217;ll need to implement some sort of passwordless authentication scheme, so that scripts can run without human intervention.</p>

<p>Two methods are presented below, the first is the easiest to implement (and possibly the most prevalent), while the second is the most secure.</p>

<h4>Method 1:  Sans Passphrase</h4>

<p>If you want your scripts to have access to the <code>ssh</code> command without requiring a password or passphrase, simply go through the steps outlined above for enabling public-key authentication, but instead of entering a passphrase when prompted, simply press <code>Enter</code>.</p>

<p>The <code>ssh-keygen</code> program will generate a public/private key pair for you that will allow password- and passphrase-less access to any remote server which has your public key stored in its <code>authorized_keys</code> file.</p>

<p><strong>Is this secure?</strong>  Well, no.  And yes.  It&#8217;s probably more secure than typing in the <code>remoteuser</code>&#8217;s password and sending it over the network.  Sure it&#8217;s encrypted, but it could still be intercepted.</p>

<p>Public-key authentication sends no password or passphrase data over the network.  The &#8220;challenge&#8221; sent by the server is encrypted with your public key, and can only be decrypted with your private key, which only you have.</p>

<p>However, as mentioned above, if someone gains access to your local computer, they&#8217;ll also have access to every remote server with your public key.</p>

<p>So, you&#8217;ll need to decide the level of security required.  In my opinion, if you&#8217;re only communicating with machines on a private LAN, under your control, behind a router&#8217;s firewall, then this method is adequate.  Others may disagree.</p>

<h4>Method 2: Using ssh-agent and keychain</h4>

<p>The &#8220;proper&#8221; and secure way to achieve passwordless authentication is by using the <code>ssh-agent</code> and <code>keychain</code> daemons to store your passphrase between terminal sessions, so you don&#8217;t need to type it every time.</p>

<p>Setup of this method is beyond the scope of this article, but the following tutorials will walk you through the entire process, as well as the theory behind it:</p>

<ul>
<li><a href="http://www.ibm.com/developerworks/library/l-keyc.html">OpenSSH key management, Part 1</a></li>
<li><a href="http://www.ibm.com/developerworks/library/l-keyc2/">OpenSSH key management, Part 2</a></li>
</ul>

<h3>Go Forth and SSHify!</h3>

<p>I hope this tutorial serves as a gentle introduction to the Secure Shell.  For further reading and advanced topics, check out the references listed below, and browse the <a href="http://www.openssh.org/manual.html">OpenSSH Documentation</a>.  Thanks for reading.</p>

<h3>References</h3>

<ol>
<li><a href="http://www.suso.org/docs/shell/ssh.sdf">SSH Tutorial for Linux</a></li>
<li><a href="https://help.ubuntu.com/community/SSHHowto">SSH: Ubuntu Community Documentation</a></li>
<li><a href="http://www.kuro5hin.org/story/2001/10/21/134817/35">Secure Communications with OpenSSH</a></li>
<li><a href="http://kimmo.suominen.com/docs/ssh/">Getting Started with SSH</a></li>
<li><a href="http://kb.iu.edu/data/agye.html">Indiana University Knowledge Base: SCP</a></li>
<li><a href="http://www.hypexr.org/linux_scp_help.php">Example Syntax for Secure Copy</a></li>
<li><a href="http://tiswww.case.edu/php/chet/bash/bashref.html">Bash Reference Manual</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/beginning-ssh-on-ubuntu/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<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 &#8216;4&#8242; means &#8220;Servo #4&#8243; and the &#8216;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 &#8216;4&#8242;, &#8216;9&#8242;, and &#8216;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, &#8216;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 &#8216;4&#8242; and &#8216;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 &#8216;4&#8242; and &#8216;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 &#8216;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 &#8216;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 &#8216;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>81</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 [...]]]></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>
		<item>
		<title>Arduino Pulse Width Modulation</title>
		<link>http://principialabs.com/arduino-pulse-width-modulation/</link>
		<comments>http://principialabs.com/arduino-pulse-width-modulation/#comments</comments>
		<pubDate>Sat, 08 Dec 2007 18:31:10 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[electronics]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[pwm]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/arduino-pulse-width-modulation/</guid>
		<description><![CDATA[



The digital pins on the Arduino board can be set (with code) to output either HIGH (5V) or LOW (0V) &#8212; essentially ON or OFF.  This is great for applications like blinking LEDs or activating relays.

But what if we wanted an output voltage somewhere in between 0V and 5V?  This might be useful [...]]]></description>
			<content:encoded><![CDATA[<div class="video">
<embed src="http://blip.tv/play/wkegzGEA" type="application/x-shockwave-flash" width="380" height="300" allowscriptaccess="always" allowfullscreen="true"></embed>
</div>

<p>The digital pins on the Arduino board can be set (with code) to output either HIGH (5V) or LOW (0V) &#8212; essentially ON or OFF.  This is great for applications like blinking LEDs or activating relays.</p>

<p>But what if we wanted an output voltage somewhere <em>in between</em> 0V and 5V?  This might be useful in applications like controlling the speed of a DC motor, or &#8220;dimming&#8221; an LED.</p>

<p>Well, the digital pins cannot directly produce an analog voltage; as we&#8217;ve said, they&#8217;re either HIGH or LOW.  But it turns out we can <em>simulate</em> these &#8220;in-between&#8221; voltages using a technique called Pulse Width Modulation, or PWM.</p>

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

<p>First off, <em>don&#8217;t panic</em>.  PWM sounds complicated, but as we&#8217;ll see, the concept is very simple, and the implementation is even easier, especially on the Arduino.</p>

<p>Let&#8217;s say we want to make an LED shine with half of its normal intensity when supplied with 5 volts.  Since we can&#8217;t use the Arduino&#8217;s digital pins to <em>directly</em> supply 2.5V, we&#8217;ll &#8220;pulse&#8221; the output pin on and off &#8212; really fast.  You may have noticed this effect when you played with the Arduino&#8217;s &#8220;Blink&#8221; sketch.  If you blink an LED fast enough &#8212; that is, if the delay between blinks is <em>short enough</em> &#8212; the LED will appear to be lit continuously, but just a little bit dimmer than it was originally.</p>

<p>It&#8217;s easy to visualize this concept using the graphs below.  When you plot voltage over time, you can see that the pin is pulsing between HIGH and LOW at regular intervals.  Since this on-off pulsing is happening so quickly, the connected LED will &#8220;see&#8221; the result as a 50% reduction in the normal voltage (in this example), and will glow at roughly half its normal intensity.</p>

<div style="text-align: center;"><img src="/files/pwm-graph1.gif" alt="PWM graph" /><br /><small>Image credit: <a href="http://www.tigoe.net/pcomp/analogout.shtml" alt="">Tom Igoe</a></small></div>

<p>We can vary the output voltage percentage (the &#8220;effective voltage&#8221;) by regulating &#8212; or &#8220;modulating&#8221; &#8212; the width of the pulse.  For example, if we make the HIGH pulse 25% as &#8220;wide&#8221; (in time) as the LOW pulse, the LED will appear to glow with 25% intensity.</p>

<div style="text-align: center;"><img src="/files/pwm-graph2.gif" alt="PWM graph" /><br /><small>Image credit: <a href="http://www.tigoe.net/pcomp/analogout.shtml" alt="">Tom Igoe</a></small></div>

<p>&#8220;Okay, great,&#8221; you&#8217;re saying, &#8220;But how do I do this on the Arduino?&#8221;  Well, there are a couple of ways.  First, you could write a sketch that blinks the LED between HIGH and LOW really fast, as we discussed above.  However, this approach requires the full attention of the Arduino all the time; that is, if you want the Arduino to do anything else, you&#8217;ll be interrupting the pulse loop.</p>

<p>Luckily, the Arduino designers have already solved this problem for us with three dedicated pins and the <code>analogWrite()</code> command.</p>

<p>Notice on the Arduino board there are three digital pins (9-11) which are labeled PWM.  Devices (like LEDs) connected to these pins can employ continuous pulse width modulation using only the <code>analogWrite()</code> command like so:</p>

<pre name="code" class="arduino">
/*
 * A simple PWM example
 */

int pin         =  11;     // LED connected to PWM pin 11
int pulsewidth  =  127;    // Any value between 0 and 255

void setup() {
  // None required for analogWrite!
}

void loop() {
  analogWrite(pin, pulsewidth);
}
</pre>

<p>The example above should cause the connected LED to glow at about 50% intensity (255/2 = 127ish).  Play around with the value of the <code>pulsewidth</code> variable and note the changes in LED brightness.</p>

<p>Now, let&#8217;s take this concept one step further.  What if we <em>varied</em> the effective voltage to the LED over time?  If we could devise a way to &#8220;fade&#8221; the <code>pulsewidth</code> from zero to 255 and back again, then the LED would pulsate, as in the video above.  Here&#8217;s the code for that, using three LEDs this time, connected to pins 9-11:</p>

<pre name="code" class="arduino">
/*
 * Pulsating LEDs with Pulse Width Modulation
 */

int green   = 11;            // Digital pin 11 - Green LED
int red     = 10;            // Digital pin 10 - Red LED
int blue    = 9;             // Digital pin 9  - Blue LED
int time    = 5;             // define delay element
int pulsewidth;              // define pulsewidth (0-255)

void setup() {
  // None required for analogWrite!
}

void loop() {
  // slowly fade the LEDs to full brightness
  for (pulsewidth=0; pulsewidth <= 255; pulsewidth++){
    analogWrite(green, pulsewidth);
    analogWrite(red, pulsewidth);
    analogWrite(blue, pulsewidth);
    delay(time);
  }
  // slowly dim the LEDs
  for (pulsewidth=255; pulsewidth >= 0; pulsewidth--){
    analogWrite(green, pulsewidth);
    analogWrite(red, pulsewidth);
    analogWrite(blue, pulsewidth);
    delay(time);
  }
}
</pre>

<p>Cool, huh?</p>

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

<ol>
<li>Tom Igoe, &#8220;<a href="http://www.tigoe.net/pcomp/analogout.shtml">Analog Output</a>&#8220;</li>
<li>Sebastian Tomczak, &#8220;<a href="http://little-scale.blogspot.com/2007/09/pwm-and-you-quick-primer.html">PWM and You: A Quick Primer</a>&#8220;</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/arduino-pulse-width-modulation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Installing Skype 2.0 on Kubuntu Gutsy 64</title>
		<link>http://principialabs.com/installing-skype-20-on-kubuntu-gutsy-64/</link>
		<comments>http://principialabs.com/installing-skype-20-on-kubuntu-gutsy-64/#comments</comments>
		<pubDate>Thu, 15 Nov 2007 19:37:48 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[skype]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://principialabs.com/installing-skype-20-on-kubuntu-gutsy-64/</guid>
		<description><![CDATA[
Skype is a free text/audio/video chat and softphone client for PCs.  Version 2.0 for Linux finally includes support for webcam video.  It&#8217;s still in beta, and it&#8217;s designed for a 32-bit OS, so AMD64 users have to do a little creative tweaking to get it to work.

Thanks to this tutorial on the Ubuntu [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.skype.com/intl/en/newtoskype/" alt="" style="border: none;"><img style="float: left; padding-right: 14px;" src="/images/skype_logo.png" alt="" /></a>
Skype is a free text/audio/video chat and <a href="http://en.wikipedia.org/wiki/Softphone">softphone</a> client for PCs.  <a href="http://www.skype.com/intl/en/download/skype/linux/beta/">Version 2.0 for Linux</a> finally includes support for webcam video.  It&#8217;s still in beta, and it&#8217;s designed for a 32-bit OS, so AMD64 users have to do a little creative tweaking to get it to work.</p>

<p>Thanks to <a href="http://ubuntuforums.org/showthread.php?t=432295">this tutorial</a> on the Ubuntu Forums, getting the latest Skype up and running is a snap.  Just paste the following code into a terminal.  This snippet works on 64-bit Gusty (7.10), Feisty (7.04), and Edgy (6.10) installations.</p>

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

<pre>
cd; sudo apt-get install ia32-libs lib32asound2; cd ~/Desktop; wget -N boundlesssupremacy.com/Cappy/getlibs/getlibs-all.deb; wget -N -O skype-install.deb http://www.skype.com/go/getskype-linux-beta-ubuntu; sudo dpkg -i getlibs-all.deb; sudo dpkg -i --force-all skype-install.deb; sudo getlibs /usr/bin/skype; cd ~
</pre>

<p><strong>Webcam Configuration</strong></p>

<p>I have the Logitech QuickCam Pro 9000 webcam.  Kopete was recognizing and using the camera right out of the box.  Skype, however, wouldn&#8217;t show the webcam image in its configuration page.  I thought I already <em>had</em> the necessary <code>uvc</code> driver installed, but apparently Skype didn&#8217;t agree.  So, I tried <a href="https://help.ubuntu.com/community/InstallingLogitechQuickcamPro5000OnEdgy">this procedure from the Ubuntu documentation</a>.</p>

<p>Install the prerequisites (Subversion and Video4Linux):</p>

<pre>
sudo apt-get install subversion libpt-plugins-v4l2 v4l2ucp libsdl1.2-dev
</pre>

<p>Get the latest build of the uvc driver using Subversion:</p>

<pre>
svn checkout svn://svn.berlios.de/linux-uvc/linux-uvc/trunk
</pre>

<p>Compile and install:</p>

<pre>
cd trunk
</pre>

<pre>
make
</pre>

<pre>
make install
</pre>

<p>Then I restarted the computer.  It worked, but I&#8217;m still not sure why.</p>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/installing-skype-20-on-kubuntu-gutsy-64/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Liquid-Fuel Rocket Engine</title>
		<link>http://principialabs.com/building-a-liquid-fuel-rocket-engine/</link>
		<comments>http://principialabs.com/building-a-liquid-fuel-rocket-engine/#comments</comments>
		<pubDate>Tue, 16 Oct 2007 20:06:19 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[rocketry]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/building-a-liquid-fuel-rocket-engine/</guid>
		<description><![CDATA[Building a liquid-propellant rocket engine is pretty much the pinnacle of amateur engineering projects.

The 1967 book How to Design, Build and Test Small Liquid-Fuel Rocket Engines can be read online, or you can download the entire file in zip format.

From the introduction:


  The purpose of this publication is to provide the serious amateur builder [...]]]></description>
			<content:encoded><![CDATA[<p>Building a liquid-propellant rocket engine is pretty much the pinnacle of amateur engineering projects.</p>

<p>The 1967 book <a href="http://www.risacher.org/rocket/">How to Design, Build and Test Small Liquid-Fuel Rocket Engines</a> can be read online, or you can download the entire file in <a href="/pdf/rocket.zip">zip</a> format.</p>

<p>From the introduction:</p>

<blockquote>
  <p>The purpose of this publication is to provide the serious amateur builder with design information, fabrication procedures, test equipment requirements, and safe operating procedures for small liquid-fuel rocket engines.</p>
</blockquote>

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

<p>Also, don&#8217;t forget the bible:</p>

<p><a href="http://www.amazon.com/gp/product/0471326429/"><img src="/images/rpe.jpg" alt="Rocket Propulsion Elements" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/building-a-liquid-fuel-rocket-engine/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rocket Stability and Performance</title>
		<link>http://principialabs.com/rocket-stability-and-performance/</link>
		<comments>http://principialabs.com/rocket-stability-and-performance/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 19:29:19 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[rocketry]]></category>
		<category><![CDATA[electronics]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/rocket-stability-and-performance/</guid>
		<description><![CDATA[The Rocket-Mounted Video Camera project is nearing completion.  Prior to the flight test phase, however, prudence demands that we run a few simulations to ensure that the rocket will have a safe and stable flight.

Initial Evaluation

Before beginning construction, we made a few ballpark calculations using (a free trial version of) RockSim, a Windows-based model [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="/rocket-mounted-digital-video-camera">Rocket-Mounted Video Camera</a> project is nearing completion.  Prior to the flight test phase, however, prudence demands that we run a few simulations to ensure that the rocket will have a safe and stable flight.</p>

<p><strong>Initial Evaluation</strong></p>

<p>Before beginning construction, we made a few ballpark calculations using (a free trial version of) <a href="http://www.apogeerockets.com/rocksim.asp">RockSim</a>, a Windows-based model rocket design tool, to verify that the addition of the camera wouldn&#8217;t adversely affect the model&#8217;s flight characteristics.  To increase performance, we also swapped the specified D12 engine for a higher-impulse E9.</p>

<p>The images below show the results of this evaluation.  You can see from the flight profile graph on the left that the predicted maximum altitude with the E9 motor is nearly 1000 feet.  The stability diagram on the right shows the center of gravity (CG) position with the E9 engine, but without the addition of the video camera in the nose.</p>

<div style="text-align: center;">
<a href="/images/flight_profile_E9-8.jpg" >
<img src="/images/flight_profile_E9-8_sm.jpg" alt="Flight Profile" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/rocksim_2d.jpg" >
<img src="/images/rocksim_2d_sm.jpg" alt="CP/CG Analysis" title="Click to enlarge"
style="border: none;" /></a>
</div>

<p>Although the CG was a little further aft than is desirable, we determined that the addition of the video camera and battery pack to the nose of the rocket would only improve stability, and that the E9 motor would help compensate for the loss of performance that the camera&#8217;s weight would create.  Based on this preliminary analysis, we decided to go ahead with rocket construction, using an Estes E9-8 engine, the video PCB and a 2AAA battery pack.</p>

<p>Now that the build is complete and the camera is installed, we need to revisit these calculations with the actual mass measurements, to assure that we have an accurate picture of the flight profile before the first test flight.</p>

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

<p><strong>Rocket Stability</strong></p>

<p>Like the feathers of an arrow, the fins of a model rocket keep it flying straight and true.  Air moving over the fins creates a lift force which helps to straighten out the rocket&#8217;s flight path when small perturbations like wind gusts or engine thrust asymmetry attempt to push it off course.  The position of two imaginary points on the rocket body, the Center of Gravity (CG) and the Center of Pressure (CP), determine how stable the rocket flight will be.</p>

<p>As with any flight vehicle, forces on a rocket will cause it to pivot about its CG.  The CG of the rocket is best determined when the model is prepped and ready to fly: that is, after the engine, recovery system and heat-resistant wadding are installed.</p>

<p>In the preliminary analysis, we used RockSim to estimate the CG position on the rocket&#8217;s fuselage based on the average masses of engines, parachutes, and modeling clay (in the nosecone, to move the CG forward).  Now that the actual build is complete, we can determine the true flight CG by prepping the rocket for flight as described above, and balancing it.</p>

<p>Using this method, we determined that the CG of our model is 286mm from the aft end of the tailcone.  This includes the installed E9-8 engine, the parachute and wadding, the video camera and 2AAA battery pack, along with some modeling clay in the very tip of the nosecone.  The clay is necessary because the Canadian Arrow kit is undesirably tail-heavy by design.</p>

<p>Now, for a stable rocket flight, the CG needs to be at least one <em>caliber</em> (the diameter of the fuselage) forward of the CP.  We know that the CG position can change depending on how we load the rocket (i.e., where we put the weight).  The Center of Pressure, however, is dependent only on the design of the rocket.  The rocket&#8217;s length and the shape, size and position of the fins determine the location of the CP.  The CP can be determined longhand using the <a href="http://my.execpc.com/~culp/rockets/Barrowman.html">Barrowman Equations</a>, or automagically by using a program like RockSim or <a href="http://www.spacecad.com/">SpaceCAD</a>.</p>

<p>Since we didn&#8217;t alter the design of the rocket aerodynamically, the CP we found using RockSim in our preliminary analysis will still be correct.  In our case, the CP is 208mm from the aft end of the tailcone.  The fuselage diameter is 66mm, and the difference between CP and CG is 78mm &#8212; about 1.18 calibers stability.  This isn&#8217;t ideal, but it is better than the marginal 0.95 that we came up with originally.</p>

<p>With these calculations we can be reasonably assured that our rocket won&#8217;t go spiralling off into oblivion on its first flight.</p>

<p>For more detailed information on this topic, consult the <a href="http://exploration.grc.nasa.gov/education/rocket/rktstab.html">Rocket Stability</a> page from NASA&#8217;s &#8220;Beginner&#8217;s Guide to Rockets.&#8221;</p>

<p><strong>Rocket Performance</strong></p>

<p>The performance of our rocket &#8212; acceleration, velocity, altitude &#8212; depends on the vehicle&#8217;s weight, aerodynamic drag, and the engine&#8217;s thrust and burn time.  Because the biggest engine Estes makes is the E9, we figured we&#8217;d throw that sucker in and be good to go.  The preliminary analysis showed no problems.  But during the course of the build, our rocket got a little &#8230; uh &#8230; heavy.</p>

<p>The <a href="/pdf/estes_engine_chart.pdf">Estes Engine Chart</a> (PDF 20K) recommends 283 grams as the maximum total liftoff weight for a model rocket using the E9-8 engine.  Well, our little prima donna weighed in this afternoon at a hefty 363 grams.  My first concern was that this fatty wouldn&#8217;t even get off the pad with an E9, but that turned out not to be the case.</p>

<p>The same chart lists maximum liftoff weights for the E9-6 and E9-4 at 340g and 425g respectively.  All three E-impulse engines have the same propellant weight, the same total impulse, the same max thrust, and the same thrust duration.  So why the difference in max recommended liftoff mass?</p>

<p>The answer, of course, is the ejection delay.  Heavier rocket, shorter ejection delay.  Why?  Well, since the thrust curve of all three engines are identical, the boost phase for a given rocket riding all three engines should be identical.  But it&#8217;s all about the coast phase.  The time from engine burnout to apogee is (obviously) less for a heavier rocket than for a lighter one.  So, my theory was that with the long-delay engines &#8212; the E9-8 and E9-6 &#8212; the ejection charge would occur way after apogee, with the vehicle velocity steadily increasing as it plummeted back to earth.</p>

<p>I needed to run some simulations.</p>

<p>Since it had been more than 30 days since I first downloaded RockSim, the trial period had expired and I was locked out of the software.  Damn!  But, not to worry, there is always <a href="http://webalt.markworld.com/webalt.html">Markworld!</a></p>

<p>Mark Sullivan has created a simple and effective HTML rocket altitude predictor that can be used for performance calculations.  Just fill in some data fields about your rocket and engine type, and voila!</p>

<p>I ran three simulations, one for each E-impulse engine type, to determine max altitude, velocity and the point of parachute deployment.  The results are as follows:</p>

<p><strong>Estes E9-4</strong></p>

<p><img src="/images/E9-4.gif" alt="E9-4" title="E9-4" />
<br />
The E9-4 graph is characteristic of the perfect model rocket flight: a quick boost to apogee, velocity goes to zero, and the recovery system is deployed shortly afterward.  (The three dots on the blue altitude curve mark engine burnout, apogee and ejection.) Maximum altitude is significantly lower than originally predicted &#8212; 136 meters (448 ft) &#8212; due to the increased mass of the finished rocket.  The airframe glides at a constant velocity under the canopy to a soft touchdown rougly 29 seconds after liftoff at a gentle 6.2 m/s.  Chute deployment occurs at a velocity of 3.15 m/s, creating a shock on the airframe of 1 g.  Nice flight.</p>

<p><strong>Estes E9-6</strong></p>

<p><img src="/images/E9-6.gif" alt="E9-6" title="E9-6" />
<br />
Notice that the boost profile and max altitude of the E9-6 are <em>identical</em> to that of the E9-4, since the thrust profile is the same.  What differs is the time and velocity of the chute deployment.  In this case, ejection occurs at 21.04 m/s, creating a shock of 10.38 g.  That&#8217;s a big difference, and we&#8217;re endangering our rocket by creating unnecessary stress on the shock cord and recovery system.</p>

<p><strong>Estes E9-8</strong></p>

<p><img src="/images/E9-8.gif" alt="E9-8" title="E9-8" />
<br />
We&#8217;ve got three of these engines sitting in the package and ready to fire.  They&#8217;ll boost the rocket to apogee just as well as the other two E-impulse, but recovery stress borders on unacceptable.  Descent velocity climbs to a whopping 33.25 m/s, creating a shock of <strong>27.50 g!</strong>  We might try these engines just for fun, but it&#8217;s clear that there is a significant danger of losing the vehicle.</p>

<p>So, we know now that our rocket is safe and ready to fly, and that the E-impulse engines should be sufficient to huck this hefty beast off the launchpad.  But our choice of an 8-second ejection delay is unacceptable for the first flight test.  We&#8217;ll pick up a pack of E9-4s before we head out to the range.</p>

<p>For more detailed information on model rocket performance, visit NASA&#8217;s <a href="http://exploration.grc.nasa.gov/education/rocket/rktengperf.html">Rocket Engine Performance</a> page.</p>

<p>Next: <a href="/cato-catastrophic-engine-failure">Launch Day Videos</a></p>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/rocket-stability-and-performance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rocket-Mounted Digital Video Camera</title>
		<link>http://principialabs.com/rocket-mounted-digital-video-camera/</link>
		<comments>http://principialabs.com/rocket-mounted-digital-video-camera/#comments</comments>
		<pubDate>Thu, 11 Oct 2007 21:42:07 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[electronics]]></category>
		<category><![CDATA[rocketry]]></category>
		<category><![CDATA[projects]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/rocket-mounted-digital-video-camera/</guid>
		<description><![CDATA[The idea comes from MAKE Magazine, Vol. 7: Hack a $30, &#8220;single-use&#8221;  camcorder and fly it on a model rocket.  The project involves disassembly of the plastic camera housing, soldering a stripped USB cable onto the camera&#8217;s circuit board, hacking the board&#8217;s embedded software to make it reusable, then mounting it in the [...]]]></description>
			<content:encoded><![CDATA[<p>The idea comes from <a href="http://www.makezine.com/07/camerarocket/">MAKE Magazine, Vol. 7</a>: Hack a $30, &#8220;single-use&#8221;  camcorder and fly it on a model rocket.  The project involves disassembly of the plastic camera housing, soldering a stripped USB cable onto the camera&#8217;s circuit board, hacking the board&#8217;s embedded software to make it reusable, then mounting it in the nosecone of an Estes rocket kit.  With persistence, the project can be completed in a long weekend, and the results are spectacular.</p>

<p><b>The CVS &#8220;Single-Use&#8221; Camcorder</b></p>

<div style="float: right; padding-left: 10px;">
<a href="/images/cvs_front.jpg" >
<img src="/images/cvs_front_sm.jpg" alt="Camera Front" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/cvs_back.jpg" >
<img src="/images/cvs_back_sm.jpg" alt="Camera Rear" title="Click to enlarge"
style="border: none;" /></a>
</div>

<p>The <a href="http://www.puredigitalinc.com/products/otucvideo.html">Pure Digital One-Time Use Video Camcorder</a>
is marketed by CVS and Rite-Aid pharmacies as an inexpensive and user-friendly device for capturing family memories,
vacation outings and the like.  With only three buttons, it is simple enough for anyone to use.  A 1.5-inch color LCD serves as a viewfinder, and allows you to watch a playback of the most recent clip.  The camera&#8217;s <a href="http://en.wikipedia.org/wiki/Firmware">firmware</a> and data are stored on a Samsung 128MB non-volatile <a href="http://en.wikipedia.org/wiki/Flash_memory">flash memory</a> chip which holds roughly 20 minutes of digital video.</p>

<p>The palm-sized camera costs less than thirty bucks, but there&#8217;s a
catch.  When your 20 minutes are up, you take the camera back to CVS, where they charge you a $13 processing fee to download the video data and burn it onto a DVD for you.  The camera&#8217;s memory is then cleared, but you don&#8217;t get to keep it; it gets sent back to the manufacturer for repackaging and resale.  Well, with a little tinkering and some steady-handed soldering, we&#8217;ll make our own camera interface, turning this product into a compact, reliable and &#8212; best of all &#8212; reusable digital video platform.</p>

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

<p><b>Camera Hacking 101</b></p>

<div style="float: right; padding-left: 10px;">
<a href="/images/interface.jpg" >
<img src="/images/interface_sm.jpg" alt="CVS Interface" title="Click to enlarge"
style="border: none;" /></a>
</div>

<p><p>Peeling off the sticker on the top end of the camera reveals its secret: a proprietary, card-edge connector that only fits the
plug behind the counter at CVS.  Luckily, it uses standard USB protocol to communicate, so interfacing with the camera is simply a
matter of soldering a cable onto the correct contacts on the circuit board.</p></p>

<p>To disassemble the camcorder, first remove the battery cover from the rear of the case, then unlock the gray battery holder inside and remove it.  Unpeeling the four corners of the sticker on the back of the case reveals four tiny Phillips-head screws.  Remove them and snap off the back of the case to expose the printed circuit board (PCB).</p>

<p>Looking at the PCB, you&#8217;ll notice two more tiny black Phillips-head screws near the lower left and right edges of the board.  Remove these to release the PCB from its standoff mounts.  There is a small, four-pin connector on the lower left (underside) corner of the PCB that connects the circuit board to the batteries.  Pull the board straight up from this corner, and it will come free of the case.</p>

<div style="text-align: center;">
<a href="/images/pcb_rear.jpg" >
<img src="/images/pcb_rear_sm.jpg" alt="PCB Rear" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/pcb_front.jpg" >
<img src="/images/pcb_front_sm.jpg" alt="PCB Front" title="Click to enlarge"
style="border: none;" /></a>
</div>

<p>Now the tricky part:  We&#8217;ll solder a USB cable to the PCB&#8217;s card-edge contacts so we can connect the camcorder to a PC. </p>

<p><b>Rigging the USB Interface</b></p>

<p><p>Find yourself an old USB cable (maybe from an unused USB mouse or other device you won&#8217;t miss) and snip off the far end of the cord.  Strip the insulation to reveal four smaller wires (and possibly some metal mesh <a href="http://en.wikipedia.org/wiki/Electromagnetic_shielding">RF shielding</a>), colored red, black, green and white.  </p></p>

<p>If you can get your hands on a <a href="http://www.testequipmentdepot.com/weller/images/wes51.jpg">decent soldering iron</a> with a fine-pointed tip, the following procedure will be much easier.  The contacts on the PCB are very close together, and any solder that accidentally flows between contacts will foul the connection &#8212; or worse.  You can see from the photos that an iron that&#8217;s too large (as mine was) can quickly make a mess of the job.  Also, using needle-nose pliers or (preferably) a small <a href="http://www.sparkfun.com/commerce/advanced_search_result.php?keywords=hemostat">hemostat</a> to hold the wires to the PCB while soldering will make things go much more smoothly.</p>

<div style="text-align: center;">
<a href="/images/bad_solder.jpg" >
<img src="/images/bad_solder_sm.jpg" alt="Bad Solder" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/video_pcb.jpg" >
<img src="/images/video_pcb_sm.jpg" alt="USB Connected" title="Click to enlarge"
style="border: none;" /></a>
</div>

<p>Notice that there are ten gold contacts on the PCB&#8217;s edge connector.  With the connector facing you and the camera lens pointing at you, label the connectors 1-10 from left to right.  Now, solder the wires to the circuit board&#8217;s edge connector in this order: red, black, green and white, to contacts 6 through 9 respectively.  (If the computer indicates a problem later, try swapping the green and white wires.)  Take your time.</p>

<p><b>Connecting the Camcorder to a PC</b></p>

<p><p>The forums at <a href="http://camerahacks.10.forumer.com/index.php?c=5">CameraHacking.com</a> are the primary resource for the most current information on hacking the Pure Digital cameras.  These bright folks have <i>legally</i> reverse-engineered the hardware and software in both still and video camera models, allowing them to be reused for a variety of applications.  [For more detailed information on how all this was done, visit <a href="http://www.maushammer.com/systems/cvscamcorder/">John Maushammer's website</a>.]</p></p>

<p>As you might imagine, Pure Digital updates the firmware and security software in each new model of camera, and your workaround solution may vary slightly from this description, depending on your camera&#8217;s model number and firmware version.  The following applies to Model 220, firmware version 33.04.</p>

<p>The camera&#8217;s model number can be found on the FCC sticker on the bottom of the camera case exterior.  To discover your firmware version, re-connect the camcorder PCB to the battery pack and verify that the camera is turned off.  Hold down the &#8220;Record&#8221; and &#8220;Delete&#8221; buttons, then press the power button to turn the camera on.  This should bring up the camera&#8217;s Configuration Screen which looks something like:</p>

<pre>
FW-VERSION: 33.04
CAMERA ID: GD5060******
PCB VER: B1
</pre>

<p>If you haven&#8217;t already, shoot a few minutes of test footage.  Make sure everything still works, and that you can save and play back a short video clip on the camera.  Now plug the camera into your PC&#8217;s USB port.  Windows should recognize the camera as a &#8220;Saturn&#8221;, and ask to install a driver.  This message indicates that you have connected the USB wires correctly.  Click &#8220;Cancel&#8221;, since you have no driver yet. (See CameraHacking.com for MacOS and Linux support.)</p>

<p><div style="float:right;padding:10px 0 0 10px;">
    <a href="/images/Saturn_Ops.jpg" >
    <img src="/images/Saturn_Ops_sm.jpg" alt="Saturn Ops Software" title="Click to enlarge"
    style="border: none;" /></a>
    </div>
We will manage our Saturn camera using a small graphical client called &#8220;Ops&#8221; (see screenshot, right).  [In Roman mythology, Ops was the wife of Saturn.]  The Ops software can be used to download videos stored on the camera&#8217;s flash chip and save them to your PC.  You can also use Ops to alter the camera&#8217;s firmware or increase the video resolution.  The entire Saturn file tree is accessible using Ops. </p>

<p><br />
<br />
<p>To convince Windows to interface with Saturn, we&#8217;ll need to download a hardware driver (just like any other device) and we&#8217;ll need Ops.  You can scour CameraHacking.com to find these items, or you can simply use Ryan David&#8217;s <a href="http://ryandavid773.googlepages.com/ocs">One-Click Setup</a>.  This will install the most current driver and the Ops client automatically.  Be sure and get the latest version from the download page.
</p></p>

<p>Once all the software and drivers are installed, we&#8217;ll connect the camera to the PC with the USB cable and fire up the Ops client.  Complete instructions for using Ops are available in the FAQ section of CameraHacking.com, but the basic procdeure is: Open Camera -> Unlock -> Download All Movies -> Close Camcorder.  That&#8217;s it!  [If you have problems unlocking your camera, you may want to check out
<a href="http://freelowell.com/downloads/camcorderpage/Camerahacking.html">this site</a>.]</p>

<p><b>Playing the Videos</b></p>

<p><p>Videos from the Saturn camera are saved as .AVI files and are encoded using the open-source <a href="http://www.xvidmovies.com/info/">XviD codec</a>, which, like DivX, is an imlementation of the MPEG-4 standard.  In order to play these clips on a Windows PC, we&#8217;ll need to <a href="http://www.xvidmovies.com/codec/">download</a> this codec.  Once we&#8217;ve installed the XviD codec, we will be able to play XviD videos using Windows Media Player or any other XviD-enabled player. </p></p>

<p><b>Building the Rocket</b></p>

<p><p>The model rocket we&#8217;ll use to fly the camcorder is the <a href="http://www.estesrockets.com/products.php?number=2188">Estes X-Prize Canadian Arrow</a>.  The design is essentially a stretched version of the classic WWII German V-2 rocket, but our main concern is to find a kit with a nosecone diameter large enough to accommodate the video PCB.  The Estes Fat Boy kit, while quite a bit shorter, would also serve our purposes.  Since we are going to modify the kit slightly from it&#8217;s original configuration, we&#8217;ll use <a href="http://www.apogeerockets.com/rocksim.asp">Rocksim</a> design and simulation software to ensure our modifications won&#8217;t affect the flight characteristics of the rocket.</p></p>

<p>Next: <a href="/rocket-stability-and-performance">Rocket Stability and Performance</a></p>

<div style="text-align: center;">
<a href="/images/rocksim_3d.jpg" >
<img src="/images/rocksim_3d_sm.jpg" alt="Rocksim" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/v2_build.jpg" >
<img src="/images/v2_build_sm.jpg" alt="Building the Kit" title="Click to enlarge"
style="border: none;" /></a>
</div>

<div style="text-align: center;">
<a href="/images/the_eye.jpg" >
<img src="/images/the_eye_sm.jpg" alt="Lens Cutout" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/standoffs_top.jpg" >
<img src="/images/standoffs_top_sm.jpg" alt="Standoffs - Top View" title="Click to enlarge"
style="border: none;" /></a>
</div>

<div style="text-align: center;">
<a href="/images/mounted_cam.jpg" >
<img src="/images/mounted_cam_sm.jpg" alt="Mounted Camera" title="Click to enlarge"
style="border: none;" /></a>
<a href="/images/progress2.jpg" >
<img src="/images/progress2_sm.jpg" alt="Making Progress" title="Click to enlarge"
style="border: none;" /></a>
</div>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/rocket-mounted-digital-video-camera/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rocket Propulsion Tutorial</title>
		<link>http://principialabs.com/rocket-propulsion-tutorial/</link>
		<comments>http://principialabs.com/rocket-propulsion-tutorial/#comments</comments>
		<pubDate>Sat, 02 Jun 2007 19:41:51 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[rocketry]]></category>
		<category><![CDATA[propulsion]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://principialabs.com/rocket-propulsion-tutorial/</guid>
		<description><![CDATA[
Image credit: SpaceX
The 
Cambridge Dictionary of Space Technology defines a rocket as a propulsive
device using a mixture of propellants which,
upon ignition, provide a reaction force to propel a vehicle such
as a missile, aircraft or spacecraft.

Typically, two separate chemical propellants are used, a fuel

(such as liquid hydrogen or kerosene), and an oxidizer (such as liquid
oxygen or [...]]]></description>
			<content:encoded><![CDATA[<p>
<div style="float: right; margin: 0 0 4px 7px;text-align:right; font-size: 11px; line-height:12px;"><img src="/images/merlin1c.jpg" alt="SpaceX Rocket Engine Test"  /><br />Image credit: SpaceX</div>
The <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0521660777/qid=1116976133/sr=8-1/ref=sr_8_xs_ap_i1_xgl14/102-6373179-6821754?v=glance&#038;s=books&#038;n=507846">
Cambridge Dictionary of Space Technology</a> defines a <i>rocket</i> as a propulsive
device using a mixture of propellants which,
upon ignition, provide a reaction force to propel a vehicle such
as a missile, aircraft or spacecraft.</p>

<p>Typically, two separate chemical propellants are used, a <i>fuel</i>

(such as liquid hydrogen or kerosene), and an <i>oxidizer</i> (such as liquid
oxygen or nitrous oxide), which provides the oxygen to sustain a burning reaction.
Rockets differ from similar propulsion systems such as gas turbine engines (jets) in that
they carry both their fuel and oxidizer on board, thereby needing no intake oxygen to
operate.  Also, the performance possible with rockets make them ideal for vehicles
such as spacecraft, which need to achieve large changes in momentum and high final velocities.</p>

<p>A rocket operates according to Newton&#8217;s third
<a href="http://en.wikipedia.org/wiki/Newton%27s_laws_of_motion">law of motion</a>,
which states, generally, that for every action there is an equal and opposite reaction.
In a chemical rocket, the fuel and oxidizer are combined in a combustion chamber,
where they are exposed to a source of ignition, causing a violent chemical reaction
which produces hot, rapidly expanding gases.  These gases are accelerated through
a throat and nozzle, where they are ejected at very high velocity, thereby imparting
a change of momentum to the vehicle.</p>

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

<p>For the purposes of this discussion, there are three major types of chemical
rockets: solid propellant, liquid propellant, and hybrid propellant.</p>

<p>A <i>solid propellant</i> rocket, commonly called a &#8220;rocket motor,&#8221; is likely
a <i>composite</i> propellant, with both the fuel and oxidizer pre-mixed
together with a firm, rubber-like putty called the <i>binder</i>.  This mixture is
then formed into the shape of the engine
casing itself, and contains an empty space or <i>port</i> down the center of the putty
which serves as the combustion chamber.
The Solid Rocket Boosters (SRBs) on the Space Shuttle are the most notable of this
type of system, using aluminum powder as a fuel and
<a href="http://en.wikipedia.org/wiki/Ammonium_perchlorate">ammonium perchlorate</a>
(NH4ClO4) as an oxidizer.</p>

<table style="text-align: center; line-height: 120%; background-color: #eee !important;" width="350"><tr><td>
<img src="/images/rockettypes.jpg" alt="Liquid and Solid Rockets" width="350" border="0" />
</td></tr>
<tr><td style="text-align:center;"><b>Liquid- and
Solid-Propellant Rockets.</b><br />Note the different combustion chambers and the significant<br />increase in complexity required for a liquid system.</td></tr>
<tr><td height="10px"></td></tr>
<tr><td style="text-align:center;"><img src="/images/hybrid.jpg" alt="Hypertek Hybrids" border="0" /></td></tr>
<tr><td style="text-align:center;"><b>Hybrid Rocket</b> with molded plexiglass fuel module (left)<br /> and N20 oxidizer canister (blue, right). <br />
(Image credit <a href="http://www.hypertekhybrids.com/">Hypertek</a>.)</p></td></tr>
</table>

<p>A <i>liquid propellant</i> rocket, commonly called a &#8220;rocket engine,&#8221; keeps its
fuel and oxidizer in separate fuel tanks, then, through a series of pumps, valves
and injectors, combines the propellants in a combustion chamber.  Liquid systems
tend to have better fuel efficiencies (in terms of
<a href="http://en.wikipedia.org/wiki/Impulse">impulse</a> per unit weight) than solids,
but are considerably more complex and thus more prone to failure.  The Space Shuttle
Main Engines (SSMEs) are the most recognizable implementation of a liquid propellant
system.</p>

<p><i>Hybrid propellant</i> rockets typically utilize a solid fuel and a liquid
or gaseous oxidizer.  Fuel in a hybrid can be almost anything combustible, but the
most common is rubber or, specifically,
<a href="http://en.wikipedia.org/wiki/HTPB">Hydroxyl-terminated Polybutadiene</a>
(HTPB).  While rubber may seem a strange choice for use as a rocket fuel, it is
interesting to note that the <a href="http://www.nasa.gov/returntoflight/system/system_SRB.html">binder</a>
used in the shuttle&#8217;s SRBs is, in fact, a polybutadiene.  Hybrid oxidizers are similar
in nature to liquid systems, although N20 (nitrous oxide) is commonly
chosen for its ease of handling and storage.  Hybrids are seen as being more versatile
than solids due to their ability to throttle, stop and restart, and safer than
liquids since the propellants are, separately, totally inert.  Currently, however, little
experimentation has been done with large-scale hybrids.
</p>

<p>Most commercial hobby rockets use some form of solid propellant, either black powder
or a HTPB-Ammonium Perchlorate composite. A few companies are now producing high-power hybrid
motors for the hobby market which are considerably less expensive per flight than composites of comparable
performance, but require a complex system of ground support equipment (GSE). The
most well-known commercial application of a large hybrid motor is
Scaled Composites&#8217; suborbital rocket glider,
<a href="http://www.scaled.com/projects/tierone/index.htm">SpaceShipOne</a>.</p>

<h2>Rocket Performance</h2>

<p>When designing or selecting a rocket propulsion system for an aerospace vehicle,
various performance parameters must be addressed.  These include such concerns as
final velocity desired, maximum acceleration, maximum altitude, payload and vehicle mass, and fuel mass
budget and volume constraints, to name a few. In order to understand and compare
the performance characteristics of different systems, the following principles
must be discussed.</p>

<h3><i>Force</i></h3>

<p>In physics, a <i>force</i> acting on a body is that which causes the body to
accelerate; that is, to change its <a href="http://en.wikipedia.org/wiki/Velocity">velocity</a>. The concept
first appeared in Newton&#8217;s second law of motion of


<a href="http://en.wikipedia.org/wiki/Classical_mechanics">classical mechanics</a>,
and is usually expressed by the equation:</p>

<p><dl style="font-family: Times; font-size: 17px; color: black;">
<dd><b>F</b> = <b><i>m</i></b> <b>a</b></dd></p>

<p></dl>
<p>where</p></p>

<dl style="color: #333;">

<dd><b>F</b> is the <a href="http://en.wikipedia.org/wiki/Force"><i>Force</i></a>, measured in
<a href="http://en.wikipedia.org/wiki/Newton">newtons</a> (N),</dd>
<dd><b><i>m</i></b> is the <a href="http://en.wikipedia.org/wiki/Mass"><i>Mass</i></a>, measured in kilograms (kg),
and</dd><dd><b>a</b> is the <a href="http://en.wikipedia.org/wiki/Acceleration"><i>Acceleration</i></a>,
measured in metres per second squared (m/s<sup><small>2</small></sup>).</dd></dl>

<p style="text-align: right;">
[Review <a href="http://en.wikipedia.org/wiki/SI#Units">SI Units of Weights and Measures</a>.]</p>

<h3><i>Thrust</i></h3>

<p>Thrust is the force that propels a rocket. The diagram to the right
shows a rocket&#8217;s <i>combustion chamber</i> with an opening, the <i>throat</i> and


<i>nozzle</i>, through which the expanding gases can escape.</p>

<div style="float:right; padding: 0 0 7px 7px"><img src="/images/ctn.gif" alt="" />
<br />(Diagram credit <a href="http://www.braeunig.us/">Robert A. Braeunig</a>.)</div>

<p>The thrust force is a product of the <i>exhaust velocity</i> (V<sub>e</sub>)
and the <i>mass flow rate</i> (<i>q</i>) of the ejected propellant,
plus the difference between the <i>atmospheric pressure</i> (P<sub>a</sub>) and the pressure
of the exhaust gases (P<sub>e</sub>). <i>Exhaust pressure</i> (P<sub>e</sub>) is affected
by the <i>expansion ratio</i> of the rocket nozzle, defined by dividing the area
of the nozzle&#8217;s exit (A<sub>e</sub>) by the area of the throat (A<sub>t</sub>).</p>

<p>Thrust is therefore expressed by the equation:</p>

<dl style="font-family: Times; font-size: 17px; color: black;">
<dd><b>F = <i>q</i>  V<sub>e</sub> + (P<sub>e</sub> &#8211; P<sub>a</sub>)  A<sub>e</sub></b></dd>

</dl>

<p>A nozzle is said to be optimized for its operating
environment when P<sub>e</sub> = P<sub>a</sub>.
Assuming an optimized expansion ratio, the thrust equation can be reduced to its
simplest form:</p>

<dl style="font-family: Times; font-size: 17px; color: black;">
<dd><b>F = <i>q</i>  V<sub>e</sub></b></dd>

</dl>

<p>where</p>

<dl style="color: #333;">
<dd><b>F</b> is the <i>Thrust</i> force, measured in newtons (N),</dd>
<dd><b><i>q</i></b> is the <i>Mass Flow Rate</i> of the ejected propellant, (kg/s),
and</dd><dd><b>V<sub>e</sub></b> is the hot gas <i>Exhaust Velocity</i>

relative to the moving vehicle, (m/s).</dd></dl>

<p>This looks very similar to the <i>Force</i> equation above (F = ma), and upon
closer inspection it becomes clear that <i>Thrust</i> is simply the acceleration of a
given mass of propellant out the back end of the vehicle which, in turn, pushes it
forward.</p>

<h3><i>The Thrust Curve</i></h3>

<p>As a rocket motor fires, its instantaneous thrust can be measured and recorded over the
duration of the burn.  This data can then be plotted on a graph with <i>thrust</i> (in
newtons or pounds) on the vertical scale and <i>time</i> (in seconds) on the horizontal
scale.  This graph is commonly referred to as a &#8220;thrust curve&#8221;, and is used as a
visual means of comparing two different rocket motors. (See Fig. 1)</p>

<div style="text-align: center;">
<img src="/images/l600attrs.gif" alt="" /><br />
Typical thrust curve.
(Credit <a href="http://www.thrustcurve.org">ThrustCurve.org</a>.)</div>

<p>You can see from the graph that the thrust spikes sharply at the beginning of the burn, and
then gradually begins to taper off.  This spike is the point of <i>maximum thrust</i>, and it
occurs in this example at about 0.3 seconds into the burn.</p>

<h3><i>Total Impulse</i></h3>

<p>The area under the thrust curve is called the <i>total impulse</i>.  It is the product of
the thrust force integrated over the burn time, and is expressed by the equation:</p>

<dl style="color: #333;">

<dd>

<img src="/images/impulse.png" alt="" />

<p>     or</p>

</dd>

<dd><b>I</b> = <b>F</b> <i>t</i>
     (assuming constant thrust)</dd>

</dl>

<p>where</p>

<dl style="color: #333;">
<dd><b>I</b> is the <i>Total Impulse</i>, measured in newton-seconds (Ns),</dd>
<dd><b>F</b> is the total <i>Thrust</i>, in newtons (N),
and</dd><dd><b><i>t</i></b> is the burn <i>Time</i>, in seconds (s).</dd></dl>

<p>Total impulse is the best means of comparing one rocket motor to another.
It is proportional to the total energy released by <i>all</i> the propellant in a propulsion system.
More total impulse means more velocity and altitude for vehicles of equal mass,
or more payload for flights of similar altitude.  </p>

<p>You&#8217;ll also see in Figure 1 the line of <i>average thrust</i> (F<sub>avg</sub>).
This number is useful in making approximations of burnout velocity and maximum altitude
of a given vehicle, and is also used in the designation of motor types (see next section).
Since no rocket motor has constant thrust throughout its burn time,
average thrust is computed by dividing total impulse by burn time (F<sub>avg</sub> = I / t).</p>

<h3><i>Specific Impulse</i></h3>

<p>Propellant efficiency of a rocket propulsion system is measured by <i>specific impulse</i> (I<sub>sp</sub>).
Put simply, specific impulse is the total impulse obtainable per unit weight of
propellant.  This means that the higher the I<sub>sp</sub>, the less fuel mass required
for a desired total impulse.  Specific impulse is expressed by the equation:</p>

<dl style="font-family: Times; font-size: 17px; color: black;">
<dd><b>I<sub>sp</sub> =   I / m<sub>p</sub> g</b></dd>

</dl>

<p>where</p>

<dl style="color: #333;"><dd><b>I<sub>sp</sub></b> is the <i>Specific Impulse</i>, measured in seconds (s),</dd>
<dd><b>I</b> is the <i>Total Impulse</i>, in newton-seconds (Ns), </dd>

<dd><b>m<sub>p</sub></b> is the <i>Propellant Mass</i>, (kg), and</dd>
<dd><b>g</b> is the acceleration of <i>Gravity</i> at the surface of the earth,
(roughly 9.81 m/s<sup><small>2</small></sup>).</dd></dl>

<p>The next section will describe how these terms are used in the designation and
classification of commercial hobby rocket motors.</p>

<h2>Rocket Motor Designation</h2>

<p>Rocket motor manufacturers designate each of their motors with standardized letter
and number codes which approximate total impulse and average thrust.  This allows
motors built by different manufacturers, possibly having different propellant types
and weights, to be classified by their total impulse.</p>

<p>Each motor will have a code similar to the following:</p>

<dl>
<dd style="font-size: 19px;">       C6-7</dd>

</dl>

<p>The first letter of the code indicates the <b>Total Impulse</b> category.  In this case,
the letter &#8220;C&#8221; indicates that this motor has a total impulse between 5.01 and 10.00 Ns.
Each successive letter indicates <i>twice</i> the impulse of the previous category (e.g., a &#8220;D&#8221;
motor has an upper limit of 20.00 Ns.)</p>

<p>The next number indicates the <b>Average Thrust</b> of the motor throughout its burn time. In
our example, the number &#8220;6&#8243; indicates that the average thrust of this motor is roughly 6 N.
[Note: Motors of equal impulse will often have different average thrust values.  Assuming equal
total impulse (e.g. two "C" motors), a greater average thrust value will produce greater
acceleration over a shorter burn time.  This is helpful for getting heavy rockets off the
pad and flying quickly.]</p>

<p>The number following the dash (-) is not always present, as it represents the
<b>Delay</b>, in seconds, between motor burnout and the recovery system ejection charge. Here, the
number &#8220;7&#8243; indicates a seven-second delay between motor burnout and chute deployment.
Longer delays allow a longer coast phase between burnout and apogee. [Note: Many
high-power motors ("G" impulse and higher) will have no built-in delay, allowing
the user to tailor the delay length to vehicle mass and predicted coast time,
either with a modular delay charge or a flight computer.  A motor with a -0 designation
is intended for use as a first stage motor on vehicles with multiple stages.]</p>

<p>The following table lists standardized impulse categories by their alphabetic designator.  Specific
information on each motor type, including thrust curves, can be found at the
<a href="http://nar.org/SandT/NARenglist.shtml">NAR Certified Motors</a> page.</p>

<div style="text-align: center;"><table style="border: 1px solid #ddd;"  cellspacing="0" cellpadding="4" align="center">

<tr style="background: #ddf;"><td align="center"><b>Total Impulse (Ns)</b></td><td align="center"><b>Engine Type</b></td></tr>
<tr><td align="center">1.26 &#8211; 2.50</td><td align="center">A</td></tr>

<tr style="background: #eee;"><td align="center">2.51 &#8211; 5.00</td><td align="center">B</td></tr>
<tr><td align="center">5.01 &#8211; 10.00</td><td align="center">C</td></tr>
<tr style="background: #eee;"><td align="center">10.01 &#8211; 20.00</td><td align="center">D</td></tr>
<tr><td align="center">20.01 &#8211; 40.00</td><td align="center">E</td></tr>

<tr style="background: #eee;"><td align="center">40.01 &#8211; 80.00</td><td align="center">F</td></tr>
<tr><td align="center">80.01 &#8211; 160.00</td><td align="center">G</td></tr>

<tr style="background: #eee;"><td align="center">160.01 &#8211; 320.00</td><td align="center">H</td></tr>
<tr><td align="center">320.01 &#8211; 640.00</td><td align="center">I</td></tr>
<tr style="background: #eee;"><td align="center">640.01 &#8211; 1280.00</td><td align="center">J</td></tr>
<tr><td align="center">1280.01 &#8211; 2560.00</td><td align="center">K</td></tr>

<tr style="background: #eee;"><td align="center">2560.01 &#8211; 5120.00</td><td align="center">L</td></tr>
<tr><td align="center">5120.01 &#8211; 10,240.00</td><td align="center">M</td></tr>

<tr style="background: #eee;"><td align="center">10,240.01 &#8211; 20,480.00</td><td align="center">N</td></tr>
</table></div>

<p><p></p>
<h2>Model Rocket Flight Profile</h2></p>

<p><img src="/images/rktflight.gif" alt="" /><br />
Diagram credit <a href="http://www.grc.nasa.gov/WWW/K-12/airplane/index.html">
NASA Glenn Research Center</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://principialabs.com/rocket-propulsion-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
