<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2771707043408054278</id><updated>2024-10-04T23:07:07.848-04:00</updated><title type='text'>meisjohn&#39;s Projects</title><subtitle type='html'>My projects, electronics and software, most likely...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://meisjohn.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://meisjohn.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>meisjohn</name><uri>http://www.blogger.com/profile/09338185434459110243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2771707043408054278.post-7482482241381710924</id><published>2011-02-03T01:19:00.001-05:00</published><updated>2011-02-03T01:28:25.139-05:00</updated><title type='text'>Let&#39;s Add Sensors, Part 2</title><content type='html'>In my last post, we worked through digital inputs using push-buttons, and we also started looking at interrupts.&amp;nbsp; This time we&#39;ll start looking at how to interface an analog sensor.&amp;nbsp; These sensors can be range-finders (I have a &lt;a href=&quot;http://www.roboticsconnection.com/multimedia/docs/Sharp_GP2D12_IR_Sensor_Specs.pdf&quot;&gt;Sharp GP2D12&lt;/a&gt;), potentiometers (adjustable resistors) and environmental sensors (temperature, humidity, force, accelerometer, gyros, et cetera.)&lt;br /&gt;
&lt;br /&gt;
Now that we know what we&#39;re dealing with, let&#39;s get down to business...&amp;nbsp; &lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
The analog pins are extremely easy to read, in fact, all you need is &lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;int sensorValue = analogRead(SENSOR_PIN);&lt;/pre&gt;No setting up of pins, no starting of any magic converters, just go and read the thing.  Not bad.&lt;br /&gt;
&lt;br /&gt;
Now that you know how to read your analog input, you need to make sense of it.  This is when you&#39;ll need to look at the &lt;a href=&quot;http://www.sparkfun.com/tutorials/223&quot;&gt;datasheet &lt;/a&gt;for your sensor.  You can look at the one for my sensor above.  In there, you&#39;ll probably find some sort of chart that maps the output voltage to whatever it is measuring (in this case, Volts-to-cm.)&amp;nbsp; Here&#39;s the one for my sensor:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/GP2D12_output_chart.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/GP2D12_output_chart.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Now, keeping in mind that the 10-bit A/D converter will give us 1024 possible results and I&#39;m not that completely concerned with precision (and I&#39;m lazy), we can pick some points on the graph. Another thing to consider is that the A/D converter doesn&#39;t return volts, it gives you a number from 0 to 1023 equaling 0 to 5 volts.  I eye-balled the chart above and came up with the following values:&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;table border=&quot;1&quot;&gt;&lt;thead align=&quot;center&quot;&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;Volts&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;A/D Value&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;Distance&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt; &lt;tbody align=&quot;center&quot;&gt;
&lt;tr&gt;&lt;td&gt;2.4&lt;/td&gt;&lt;td&gt;490&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2.0&lt;/td&gt;&lt;td&gt;408&lt;/td&gt;&lt;td&gt;13&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.6&lt;/td&gt;&lt;td&gt;327&lt;/td&gt;&lt;td&gt;17&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.4&lt;/td&gt;&lt;td&gt;286&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1.0&lt;/td&gt;&lt;td&gt;204&lt;/td&gt;&lt;td&gt;30&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.80&lt;/td&gt;&lt;td&gt;163&lt;/td&gt;&lt;td&gt;38&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.70&lt;/td&gt;&lt;td&gt;143&lt;/td&gt;&lt;td&gt;40&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.65&lt;/td&gt;&lt;td&gt;133&lt;/td&gt;&lt;td&gt;50&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.50&lt;/td&gt;&lt;td&gt;102&lt;/td&gt;&lt;td&gt;60&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.45&lt;/td&gt;&lt;td&gt;92&lt;/td&gt;&lt;td&gt;70&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;0.40&lt;/td&gt;&lt;td&gt;82&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;
Alternatively, you could calibrate this table to your exact sensor by following this tutorial and using a ruler and adjust the values accordingly.&amp;nbsp; I&#39;m not particularly concerned with precision at the moment, but I may come back to that option later. &lt;br /&gt;
&lt;br /&gt;
After we have our distance points, we&#39;ll use our handy geometry skills to make a slope between two known points using the following slope equations:&lt;br /&gt;
&lt;blockquote&gt;&lt;code&gt;y = m * x + c&lt;/code&gt;&lt;/blockquote&gt;&lt;blockquote&gt;where:&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp; y = value&lt;br /&gt;
&amp;nbsp;&amp;nbsp; x = distance&lt;br /&gt;
&amp;nbsp;&amp;nbsp; m = slope&lt;br /&gt;
&amp;nbsp;&amp;nbsp; c = constant adjustment&lt;/code&gt;&lt;/blockquote&gt;&amp;nbsp;and:&lt;br /&gt;
&lt;blockquote&gt;&lt;code&gt;m = (y1 - y2) / (x1 - x2)&lt;/code&gt;&lt;/blockquote&gt;&lt;blockquote&gt;where:&lt;br /&gt;
&lt;code&gt;&amp;nbsp;&amp;nbsp; x1, y1 = the first known point on our graph&lt;br /&gt;
&amp;nbsp;&amp;nbsp; x2, y2 = the second known point on our graph&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;
Another thing to keep in mind is sensor timing.&amp;nbsp; Using the timing chart from the datasheet we see that that the sensor will only be able to provide data so quickly, and there&#39;s a delay between the measurement and the availability of the data. Knowing this, we need to add an initial delay in the setup routine and a delay between every time we read the sensor data.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/GP2D12_timing_chart.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/GP2D12_timing_chart.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
If we stop our sketch with just a loop that continuously reads the data and logs it to Serial, it would give us a ridiculous amount of output.  So, we&#39;re going to combine this sketch with the last one and modify it to only output once when the button is pressed, sort of like a camera shutter.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s what we&#39;ve got going so far:&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;nbsp;
/*
 *  Analog Sensor Test (Sharp GP2D12)
 *  with button for logging enable.
 *
 */


// This identifies the interrupt number for our chipset:
//   0 = digial pin 2
//   1 = digital pin 3
#define INTERRUPT_NUM 1 

// set up the button pin to match the interrupt number.
#define BUTTON_PIN 3 
// set up the a pin drive the button
#define DRIVER_PIN 4 

// identify the current LED state this is volatile because 
// the toggleLed routine which changes the value will be
// called from an interrupt. This is important because 
// we&#39;ll be using this variable in our loop routine.
volatile int button_state = HIGH; 

// our sensor has a maximum time between the measurement and
// the data being ready to read.  This is just an initial 
// delay that is only added on the start of the program.
#define SENSOR_INIT_DELAY 5

// our sensor has a delay between read-times of 48ms, meaning
// new data is only available every 48 ms.
#define SENSOR_DELAY 48

// select the analog pin we&#39;re going to use
#define SENSOR_PIN A0

struct ValueToDist {
  int value;
  int dist;
};

// We need to identify values to feed to our algorithm
// and since we know that the sensor is only ranged from
// 0 - 2.5V, we can ignore half the data points, additionally
// we&#39;re going to give a relatively small sample set (compared
// to the 1024 possible values)
ValueToDist valueDistTable[] =
 { {490, 10},
   {408, 13},
   {327, 17},
   {286, 20},
   {204, 30},
   {163, 38},
   {143, 40},
   {133, 50},
   {102, 60},
   {92,  70},
   {82,  80} };

int getDistance( int value )
{
  ValueToDist left;
  ValueToDist right;
  float slope;
  float c;
  
  int result = -1;
  
  // Test for the value being out of bounds
  if (value &amp;gt; valueDistTable[0].value || 
      value &amp;lt; valueDistTable[11].value )
  {
    Serial.println(&quot;value out of bounds&quot;);
    result = -1;
  }
  // test for the value at the closer edge of valid values
  else if ( value == valueDistTable[0].value )
  {
    result = valueDistTable[0].dist;
  }
  // test for the value at the further edge of valid values
  else if ( value == valueDistTable[11].value)
  {
    result = valueDistTable[11].dist;
  }
  // handle all other points in between
  else
  {
    // loop through the table, except the last one
    for (int i = 0; i &amp;lt; 11; i++ )
    {
      // if the value is between the current and next point
      if ( value &amp;lt;= valueDistTable[i].value &amp;amp;&amp;amp; 
           value &amp;gt; valueDistTable[i+1].value )
      {

         Serial.print(&quot;found value range, upper =&quot;);
         Serial.print(valueDistTable[i].value);
         Serial.print(&quot; lower =&quot;);
         Serial.println(valueDistTable[i+1].value );

         // using a simple slope algorithm to find
         // the value on the line between two known
         // points
         //   value=slope * dist + c
         left=valueDistTable[i];
         right=valueDistTable[i+1];

         // calculate the slope from the known points
         slope = ( (left.value - right.value) / (left.dist - right.dist));
         // get the slope constant using one of the known points
         c = left.value-slope*left.dist;

         // get the results from the algorithm
         result=int((value - c) / slope);

         // break out of the loop, because we&#39;ve found what we&#39;re looking for
         break;
      }
    }
  }  
  
  return result;
}

void toggleLed()
{
  // read in the current state of the button
  button_state=digitalRead(BUTTON_PIN);
}

void setup()
{
  // add the driver pin
  pinMode(DRIVER_PIN, OUTPUT);
  // set the driver pin to LOW
  digitalWrite(DRIVER_PIN, LOW);
  
  // add the driver pin
  pinMode(BUTTON_PIN, INPUT);
  // enable the pull-up register
  digitalWrite(BUTTON_PIN, HIGH);
  
  // Identify the routine and conditions for our interrupt. An interrupt
  // can have only one routine attached, and that routine takes no inputs
  // and returns no output.  The specified routine will be called in 
  // the midst of the normal loop processing, so any variables that are
  // changed should probably be marked as volatile, if they are real-time
  // critical.  For our purposes, it&#39;s not necessary, but it may be 
  // significant if we have more robust processing of data changed in an 
  // interrupt routine.
  attachInterrupt(INTERRUPT_NUM, toggleLed, CHANGE); 
 
  // start serial port at 9600 bps:
  Serial.begin(9600);

  delay(SENSOR_INIT_DELAY);
}

void loop()
{
  // As noted above, the sensor can only translate data so
  // quickly, so each time through loop, we need to delay 
  // the read of the next sensor value
  delay(SENSOR_DELAY);                  

  // only calculate the distance if the button is pressed
  if (LOW == button_state)
  {
    // read the value from the sensor:
    int sensorValue = analogRead(SENSOR_PIN);
    int dist = getDistance(sensorValue);

    // if the button is being pressed, send the data to the
    // serial interface.
    Serial.print(&quot;sensor val = &quot;);
    Serial.print(sensorValue);
    Serial.print(&quot;  distance = &quot; );
    Serial.println(dist);
    
    // reset the button state so that we only get one reading
 // per button press
    button_state=HIGH;
  }
}
&lt;/pre&gt;&lt;br /&gt;
Here&#39;s the fritzing diagram of our setup:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/GP2D12_sketch.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/GP2D12_sketch.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
and here&#39;s the &lt;a href=&quot;http://meisjohns-projects.googlecode.com/svn/trunk/arduino_sketches/analog_GP2D12/analog_GP2D12.pde&quot;&gt;link for the code&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://meisjohn.blogspot.com/feeds/7482482241381710924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://meisjohn.blogspot.com/2011/02/lets-add-sensors-part-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/7482482241381710924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/7482482241381710924'/><link rel='alternate' type='text/html' href='http://meisjohn.blogspot.com/2011/02/lets-add-sensors-part-2.html' title='Let&#39;s Add Sensors, Part 2'/><author><name>meisjohn</name><uri>http://www.blogger.com/profile/09338185434459110243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2771707043408054278.post-5553608460462430874</id><published>2011-01-26T00:00:00.000-05:00</published><updated>2011-01-26T00:00:00.099-05:00</updated><title type='text'>Let&#39;s Add Sensors, Part 1</title><content type='html'>Now that we can &lt;i&gt;act&lt;/i&gt; on the physical realm, let&#39;s add sensors to &lt;i&gt;observe&lt;/i&gt; it.&amp;nbsp; There&#39;s &lt;a href=&quot;http://www.sparkfun.com/categories/23&quot;&gt;all&lt;/a&gt; &lt;a href=&quot;http://www.parallax.com/Store/Sensors/tabid/86/Default.aspx&quot;&gt;sorts&lt;/a&gt; of &lt;a href=&quot;http://www.robotshop.ca/sensors.html&quot;&gt;sensors&lt;/a&gt; &lt;a href=&quot;http://www.acroname.com/robotics/parts/c_Sensors.html&quot;&gt;out&lt;/a&gt; &lt;a href=&quot;http://www.trossenrobotics.com/c/robot-sensors.aspx&quot;&gt;there&lt;/a&gt;, but there three basic interfaces to those sensors, digital, analog or via some sort of higher-level communications protocol (i2c, serial, parallel, et cetera).&lt;br /&gt;
&lt;br /&gt;
I&#39;ve got some of each of these, so we&#39;ll go through and try them each out one-by-one. Let&#39;s pick the digital inputs first.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;To demonstrate this interface, I&#39;m going to use a &lt;a href=&quot;http://www.sparkfun.com/products/97&quot;&gt;push-button switch&lt;/a&gt;.&amp;nbsp; These things are everywhere.&amp;nbsp; Most of mine were harvested from an old VCR.&amp;nbsp; This is the simplest sensor for use with your arduino, because, well, the output is either 1 or 0. (We will ignore &lt;a href=&quot;http://en.wikipedia.org/wiki/Debounce#Contact_bounce&quot;&gt;debounce &lt;/a&gt;for now.)&lt;br /&gt;
&lt;br /&gt;
Since you can read the input simply by reading in the pin, the easiest thing to do would be to put this logic into your &lt;code&gt;loop()&lt;/code&gt; routine and do it repetitively.&amp;nbsp; Alternatively, you could set up an interrupt.&amp;nbsp; Interrupts are special creatures that allow a routine (commonly referred to as an Interrupt Service Routine, ISR for short) to get called when a pin&#39;s state changes.&amp;nbsp; By migrating your &quot;on change&quot; code into the ISR, you&#39;re doing less work on every loop.&lt;br /&gt;
&lt;br /&gt;
I&#39;m deciding to go the interrupt path, because it allows me to demonstrate more things at once, and well, it sounds like more fun.&amp;nbsp; My sketch will have a button that turns off our LED from the previous examples.&amp;nbsp; The button will trigger the &lt;code&gt;toggleLed()&lt;/code&gt; ISR.&amp;nbsp; Also, for the sake of simplifying the electronics, the pin adjacent to the &lt;code&gt;BUTTON_PIN&lt;/code&gt;  (I&#39;m calling it &lt;code&gt;DRIVE_PIN&lt;/code&gt;) will be used to identify the button state and the button will be between the two pins.&amp;nbsp; When the button is pressed, the &lt;code&gt;BUTTON_PIN&lt;/code&gt; will observe a low state (based on the state of the &lt;code&gt;DRIVE_PIN&lt;/code&gt;) and vice-versa.&amp;nbsp; To ensure that the &lt;code&gt;BUTTON_PIN&lt;/code&gt; state is high by default, we are using internal pull-up resistors in the chip.&amp;nbsp; The schematic for this set-up is below:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjToehZajYsW9bCG68tg-xl6VyJ8WkV_LS3Ju3EbS7an3g8dZPgcZwO52qZ7897Umm98AQCL04VMfx-Aogsec4aIo3-oEGh1tqdQEIDNrG1d8I2vxOAoKGOF0_MH9sJdeOc8KlT9Q0xm5_/s1600/diagram1.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;319&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjToehZajYsW9bCG68tg-xl6VyJ8WkV_LS3Ju3EbS7an3g8dZPgcZwO52qZ7897Umm98AQCL04VMfx-Aogsec4aIo3-oEGh1tqdQEIDNrG1d8I2vxOAoKGOF0_MH9sJdeOc8KlT9Q0xm5_/s320/diagram1.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;/*
   * Push Button Test
   *
   */
   
  #define LED_PIN 13         
  #define INTERRUPT_NUM 1         // This identifies the interrupt number for
                                  // our chipset:
                                  //   0 = digial pin 2
                                  //   1 = digital pin 3
                                
  #define BUTTON_PIN 3            // set up the button pin to match the interrupt
                                  // number.
  #define DRIVER_PIN 4            // set up the a pin drive the button

  volatile int led_state = HIGH;  // identify the current LED state
                                  // this is volatile because the toggleLed
                                  // routine which changes the value will be
                                  // called from an interrupt. 

  void toggleLed()
  {
    // read in the current state of the button
    // and enable the LED state based on the button state
    led_state=digitalRead(BUTTON_PIN);
    
    // write the new state out to the LED pin
    digitalWrite(LED_PIN, led_state);
  }


  void setup()
  {
    // set up the same LED as we have been
    pinMode(LED_PIN, OUTPUT);
    
    // add the driver pin
    pinMode(DRIVER_PIN, OUTPUT);
    // set the driver pin to LOW
    digitalWrite(DRIVER_PIN, LOW);
    
    // add the driver pin
    pinMode(BUTTON_PIN, INPUT);
    // enable the pull-up register
    digitalWrite(BUTTON_PIN, HIGH);
    
    // Identify the routine and conditions for our interrupt. An interrupt
    // can have only one routine attached, and that routine takes no inputs
    // and returns no output.  The specified routine will be called in 
    // the midst of the normal loop processing, so any variables that are
    // changed should probably be marked as volatile, if they are real-time
    // critical.  For our purposes, it&#39;s not necessary, but it may be 
    // significant if we have more robust processing of data changed in an 
    // interrupt routine.
    attachInterrupt(INTERRUPT_NUM, toggleLed, CHANGE); 
  }

  void loop()
  {
    // nothing to do here, since it&#39;s all taken care of in the interrupt
  }

&lt;/pre&gt;&lt;br /&gt;
Now, we can control the state of the LED manually by pressing a button.&amp;nbsp; This isn&#39;t earth shattering or particularly complex, but it does demonstrate a couple of principles (ISRs, Digital write, digital read, internal pull-up resistors.)&amp;nbsp; Another interesting note is that you don&#39;t need to actually read the interrupt pin in the ISR, it could be used to trigger something completely different, like reading different pins&#39; values, or enabling some additional behavior, or even waking up the arduino (think back to the sleep mode we entered in the last post).&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Looking forward, and applying what we&#39;ve learned...&lt;/h3&gt;Eventually, I&#39;m thinking that I&#39;ll use these buttons to detect when my little bot has bumped into something.&amp;nbsp; Because the arduino only has 2 interrupt pins, I&#39;m going to need to be creative when doing this. I&#39;ve got an assortment of ICs, so I think I&#39;m going to &quot;XOR&quot; their states together to drive the ISR pin, so that I can have the ISR trigger when any of their states change.  I will also connect them to digital pins, so that in the ISR, we can read all the inputs.&amp;nbsp; I plan to use the &lt;a href=&quot;http://pdf1.alldatasheet.com/datasheet-pdf/view/51094/FAIRCHILD/DM74LS86N.html&quot;&gt;74LS86N&lt;/a&gt; Quad 2-input XOR gate from my goody-bag.</content><link rel='replies' type='application/atom+xml' href='http://meisjohn.blogspot.com/feeds/5553608460462430874/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://meisjohn.blogspot.com/2011/01/lets-add-sensors-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/5553608460462430874'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/5553608460462430874'/><link rel='alternate' type='text/html' href='http://meisjohn.blogspot.com/2011/01/lets-add-sensors-part-1.html' title='Let&#39;s Add Sensors, Part 1'/><author><name>meisjohn</name><uri>http://www.blogger.com/profile/09338185434459110243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjToehZajYsW9bCG68tg-xl6VyJ8WkV_LS3Ju3EbS7an3g8dZPgcZwO52qZ7897Umm98AQCL04VMfx-Aogsec4aIo3-oEGh1tqdQEIDNrG1d8I2vxOAoKGOF0_MH9sJdeOc8KlT9Q0xm5_/s72-c/diagram1.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2771707043408054278.post-8688584390704506746</id><published>2011-01-22T04:24:00.000-05:00</published><updated>2011-01-22T04:24:59.221-05:00</updated><title type='text'>Up Next: Servo and Serial</title><content type='html'>Okay, we&#39;ve got the computer and the arduino board working together.  Let&#39;s start doing something interesting, like driving a Servo.&amp;nbsp; Again, I did a little research on the Arduino website, and started with one of the sample sketches.&lt;br /&gt;
&lt;br /&gt;
This has me thinking back to college where I spent many hours getting a Motorola HC12 to drive a servo.&amp;nbsp; You had to enable the right pins, configure your PWM channels to make sure your duty cycles matched the servo specifications, break out the old monster of an oscilloscope to figure out what you&#39;re actually sending, when it doesn&#39;t work-- all in assembly code.&lt;br /&gt;
&lt;br /&gt;
So, how do you do it with Arduino?&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;nbsp;
#define SERVO_PIN 11

Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 

void setup () 
{
  myservo.attach(SERVO_PIN);  // attaches the servo pin to the servo object 

}

void loop ()
{
  myservo.write(45); // go to the first quarter position
  delay(1000);
  myservo.write(90); // go to the middle point
  delay(1000);
  myservo.write(135); // go to the last quarter position
  delay(1000);
}

&lt;/pre&gt;Are you kidding me?&amp;nbsp; It almost makes me want to cry when I think how much time I spent debugging a similar procedure just a few years ago.&lt;br /&gt;
&lt;br /&gt;
Okay, now I&#39;ve got software affecting the physical realm.&amp;nbsp; This is where robotics starts to get really exciting.&amp;nbsp; (I said &lt;i&gt;starts&lt;/i&gt;...)&amp;nbsp; So, what to do next?&lt;br /&gt;
&lt;br /&gt;
Let&#39;s throw that blinky LED back in and have the servo move a little smoother through it&#39;s full range of motion.  I&#39;m going to set the LED the same way as the previous post, call a new routine to toggle it, and a couple of loops for the servo.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;nbsp;
for(pos = 0; pos &amp;lt; 180; pos += 5)  // goes from 0 degrees to 180 degrees 
{                                  // in steps of 5 degrees
  myservo.write(pos);              // tell servo to go to position in variable &#39;pos&#39; 
  delay(50);                       // waits 50ms for the servo to reach the position 
  toggleLed();
} 

for(pos = 180; pos&amp;gt;=0; pos-=5)     // goes from 180 degrees to 0 degrees 
{                                
  myservo.write(pos);              // tell servo to go to position in variable &#39;pos&#39; 
  delay(50);                       // waits 50ms for the servo to reach the position 
  toggleLed();
} 
&amp;nbsp;
&lt;/pre&gt;&lt;br /&gt;
Nice, now we&#39;ve got some smooth motion, and some blinking action too.  Okay, now we&#39;ve got this going back and forth fairly smoothly, ad infinitum.  Let&#39;s see if we can take some control over the situation here... let&#39;s take advantage of the Serial connection.&lt;br /&gt;
&lt;br /&gt;
The Serial interface is nearly as simple as the Servo one.  You can read and write to your computer over the USB cable, so when you open the Serial Monitor in the Arduino Environment, you can read what it has to say, and tell it to do things.  So, let&#39;s make an interface to tell the servo to move somewhere.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: cpp&quot;&gt;&amp;nbsp;
char buffer[9];      // a buffer to store data coming back from the serial interface
char buffer_pos = 0; // the current position into the buffer

void setup() 
{ 
  // start serial port at 9600 bps:
  Serial.begin(9600);

  ...
} 

void loop() 
{ 
  int read_val;  // variable to store the integer from the Serial.read() method
                 // this is the ASCII value of what is typed in at the Serial
                 // Monitor window
  
  // if we&#39;ve got something ready from the serial interface
  if ( Serial.available() &amp;gt; 0 )  
  {
    // read in the data, up to the max size of the buffer.
    while( -1 != (read_val = Serial.read() ) &amp;amp;&amp;amp; buffer_pos &amp;lt; 8)
    {
      // put the value in the buffer, and increment the position
      buffer[buffer_pos++] = read_val;  
    }
    buffer[buffer_pos] = &#39;\0&#39;;       // terminate the string.
    Serial.print(&quot;Read in value: &quot;); // add some feedback to the Serial Monitor
    Serial.println(buffer);          //   so we know the command was received
    pos = atoi(buffer);              // turn the input data into an integer value
    pos = (pos &amp;lt; 170 ? pos : 170);   // clamp the input values at reasonable 
    pos = (pos &amp;gt; 0 ? pos : 0);       //  values for your servo.  Mine is finicky ~ 180
    Serial.print(&quot;Moving to &quot;);      // Tell Serial Monitor where we&#39;re actually going
    Serial.print(pos);
    myservo.write(pos);              // And go there.
    toggleLed();
    delay(1000); 
    buffer_pos = 0;                  // Clean up after ourselves.
    memset(buffer,0,9);
  }
}

&lt;/pre&gt;&lt;br /&gt;
Nice, now we have manual control over the servo, and we&#39;re able to see where it is going, and where it has been, all this using only a few pins on the Arduino.&lt;br /&gt;
&lt;br /&gt;
Okay, now that we can make it go, let&#39;s figure out how to make it stop.  Arduino doesn&#39;t have a &quot;stop&quot; command that I&#39;ve been able to find yet, but avr does have power controls.  Let&#39;s just tell it to go to sleep and reduce as much power as it can.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;nbsp;

#include &amp;lt;avr/sleep.h&amp;gt;

void loop()
{
  ...

    if (pos == -1)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // If we&#39;ve received the &quot;all done&quot; command&amp;nbsp;
    {
      set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set the sleep mode
      sleep_enable();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // enable sleeping
      sleep_mode();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // then activate the sleep mode
    }

  ...
}&lt;/pre&gt;&lt;br /&gt;
Okay, now we can conserve our power when we&#39;ve completed our task.&lt;br /&gt;
&lt;br /&gt;
Let&#39;s put everything we&#39;ve learned here together.&lt;br /&gt;
&lt;br /&gt;
A link for the source code is &lt;a href=&quot;http://code.google.com/p/meisjohns-projects/source/browse/trunk/arduino_sketches/servo_sweep_with_led/servo_sweep_with_led.pde&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;nbsp;
/* Serial Servo Control
 *
 * Derived from:
 *   Sweep by BARRAGAN &amp;lt;http://barraganstudio.com&amp;gt;
 */

#include &amp;lt;Servo.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt; //atoi
#include &amp;lt;avr/sleep.h&amp;gt;

#define LED_PIN 13
#define SERVO_PIN 11

Servo myservo;       // create servo object to control a servo 
                     // a maximum of eight servo objects can be created 

int pos = 0;         // variable to store the servo position 
char led_state = 0;  // variable to store the state of the LED
char buffer[9];      // buffer for storing the inputs from the Serial
                     //   interface
char buffer_pos = 0; // current writing position for the buffer


void toggleLed()
{
  // If the LED is on
  if (led_state) 
  { 
    // then turn it off.
    digitalWrite(LED_PIN,LOW);
  }
  else
  {
    // otherwise, turn it on
    digitalWrite(LED_PIN,HIGH);
  }
  
  // toggle the LED state variable
  led_state=!led_state;
}

void setup() 
{ 
  // start serial port at 9600 bps:
  Serial.begin(9600);

  pinMode(LED_PIN, OUTPUT);  // enable the LED pin
  myservo.attach(SERVO_PIN); // attaches the servo pin to the servo object 

} 
 
 
void loop() 
{ 
  int read_val;  // variable to store the integer from the Serial.read() method
                 // this is the ASCII value of what is typed in at the Serial
                 // Monitor window
                 
  // if we&#39;ve got something ready from the serial interface
  if ( Serial.available() &amp;gt; 0 )
  {
    // read in the data, up to the max size of the buffer.
    while( -1 != (read_val = Serial.read() ) &amp;amp;&amp;amp; buffer_pos &amp;lt; 8)
    {
      // put the value in the buffer, and increment the position
      buffer[buffer_pos++] = read_val;
    }
    buffer[buffer_pos] = &#39;\0&#39;;       // terminate the string.
    Serial.print(&quot;Read in value: &quot;); // add some feedback to the Serial Monitor
    Serial.println(buffer);          //   so we know the command was received
    pos = atoi(buffer);              // turn the input data into an integer value
    if (pos == -1)                   // If we&#39;ve received the &quot;all done&quot; command
    {
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // set the sleep mode
      sleep_enable();                // enable sleeping
      sleep_mode();                  // then activate the sleep mode
    }
    pos = (pos &amp;lt; 170 ? pos : 170);   // clamp the input values at reasonable 
    pos = (pos &amp;gt; 0 ? pos : 0);       //  values for your servo.  Mine is finicky ~ 180
    Serial.print(&quot;Moving to &quot;);      // Tell Serial Monitor where we&#39;re actually going
    Serial.print(pos);
    myservo.write(pos);              // And go there
    toggleLed();
    delay(10000); 
    buffer_pos = 0;                  // And clean up after ourselves.
    memset(buffer,0,9);
  }
  else
  {
    
    Serial.println(&quot;Moving 0 to 180&quot;);
    for(pos = 0; pos &amp;lt; 180; pos += 5)  // goes from 0 degrees to 180 degrees 
    {                                  // in steps of 5 degrees
      myservo.write(pos);              // tell servo to go to position in variable &#39;pos&#39; 
      delay(50);                       // waits 50ms for the servo to reach the position 
      toggleLed();
    } 
    Serial.println(&quot;Moving 180 to 0&quot;);
    for(pos = 180; pos&amp;gt;=0; pos-=5)     // goes from 180 degrees to 0 degrees 
    {                                
      myservo.write(pos);              // tell servo to go to position in variable &#39;pos&#39; 
      delay(50);                       // waits 50ms for the servo to reach the position 
      toggleLed();
    } 
  }
} 
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://meisjohn.blogspot.com/feeds/8688584390704506746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://meisjohn.blogspot.com/2011/01/up-next-servo-and-serial.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/8688584390704506746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/8688584390704506746'/><link rel='alternate' type='text/html' href='http://meisjohn.blogspot.com/2011/01/up-next-servo-and-serial.html' title='Up Next: Servo and Serial'/><author><name>meisjohn</name><uri>http://www.blogger.com/profile/09338185434459110243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2771707043408054278.post-7207214741525140735</id><published>2011-01-22T00:29:00.003-05:00</published><updated>2011-01-22T10:52:20.978-05:00</updated><title type='text'>Connecting to Arduino &amp; My First Sketch</title><content type='html'>I just received my first &lt;a href=&quot;http://www.arduino.cc/&quot;&gt;Arduino&lt;/a&gt; board (the &lt;a href=&quot;http://arduino.cc/en/Main/ArduinoBoardUno&quot;&gt;Uno&lt;/a&gt;) as part of my spoils from the &lt;a href=&quot;http://www.sparkfun.com/news/531&quot;&gt;SparkFun Electronics free day&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
My goal?&amp;nbsp; Toy around, clearly.&amp;nbsp; But seriously, I&#39;d like to build some sort of autonomous robot eventually.&amp;nbsp; I&#39;d love to get my kids involved at some level, but they&#39;re still very young.&amp;nbsp; We&#39;ll see how that works out eventually.&lt;br /&gt;
&lt;br /&gt;
First things first, though... let&#39;s get a blinky app going.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
I&#39;m currently using the arduino environment to get started.&amp;nbsp; I may switch to the Eclipse AVR plugin, but that&#39;s for another day.&lt;br /&gt;
&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;Here&#39;s my first sketch:&lt;/div&gt;&lt;pre class=&quot;brush:cpp&quot;&gt;&amp;nbsp;
/*
&amp;nbsp;* First Arduino sketch - Blinky
&amp;nbsp;*
&amp;nbsp;*/
&amp;nbsp;
&amp;nbsp;
#define LED_PIN 13

void turnOnLedShort(char pin);
void turnOnLedLong(char pin);


void setup() {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp; pinMode(LED_PIN, OUTPUT);&amp;nbsp;&amp;nbsp;&amp;nbsp; 
}

void loop() {
&amp;nbsp; // Morse Code &quot;SOS&quot;

&amp;nbsp; // S
&amp;nbsp; turnOnLedShort(LED_PIN);
&amp;nbsp; turnOnLedShort(LED_PIN);
&amp;nbsp; turnOnLedShort(LED_PIN);&amp;nbsp; 

&amp;nbsp; // O
&amp;nbsp; turnOnLedLong(LED_PIN);
&amp;nbsp; turnOnLedLong(LED_PIN);
&amp;nbsp; turnOnLedLong(LED_PIN);&amp;nbsp; 

&amp;nbsp; // S
&amp;nbsp; turnOnLedShort(LED_PIN);
&amp;nbsp; turnOnLedShort(LED_PIN);
&amp;nbsp; turnOnLedShort(LED_PIN);&amp;nbsp; 
&amp;nbsp; 
&amp;nbsp; delay(1000);
}


void turnOnLedShort(char pin)
{
&amp;nbsp; digitalWrite(pin, HIGH); 
&amp;nbsp; delay(500);
&amp;nbsp; digitalWrite(pin, LOW);
&amp;nbsp; delay(500);
}

void turnOnLedLong(char pin)
{
&amp;nbsp; digitalWrite(pin, HIGH); 
&amp;nbsp; delay(1000);
&amp;nbsp; digitalWrite(pin, LOW);
&amp;nbsp; delay(500);
}
&lt;/pre&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;Once the program was written, I needed to connect to the Arduino board.&amp;nbsp; Plugged it into my USB port and got this in my dmesg output:&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre class=&quot;brush:plain&quot;&gt;&amp;nbsp;
usb 6-1: new full speed USB device using ohci_hcd and address 2
usb 6-1: New USB device found, idVendor=2341, idProduct=0001 
usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=220
usb 6-1: Product: Arduino Uno
usb 6-1: Manufacturer: Arduino (www.arduino.cc)
usb 6-1: SerialNumber: 012345689ABCDEF
usb 6-1: configuration #1 chosen from 1 choice
cdc_acm 6-1:1.0: ttyACM0: USB ACM device
usbcore: registered new interface driver cdc_acm
cdc_acm: v0.26:USB Abstract Control Model driver for USB modems and ISDN adapters
&lt;/pre&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;Nice, it connected...&amp;nbsp; The out of the box blinking test program was working fine, so the Uno had power, and it was functional.&amp;nbsp; Let&#39;s upload my program!&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;First, you&#39;ve got to configure your arduino envionment.&amp;nbsp; To do that, change your Arduino preferences file (~/.arduino/preferences.txt).&amp;nbsp; Change the line:&lt;/div&gt;&lt;pre class=&quot;brush:plain&quot;&gt;serial.port=COM1&lt;/pre&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;to:&lt;/div&gt;&lt;pre class=&quot;brush:plain&quot;&gt;serial.port=/dev/ttyACM0&lt;/pre&gt;&lt;br /&gt;
Open the Arduino envionment, compile my sketch, and click upload... Here we go!&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush:plain&quot;&gt;&amp;nbsp;
processing.app.SerialNotFoundException: Serial port &#39;/dev/ttyACM0&#39; not found.&amp;nbsp; Did you select the right one from the Tools &amp;gt; Serial Port menu?
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.Serial.&amp;lt;init&amp;gt;(Serial.java:153)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.Serial.&amp;lt;init&amp;gt;(Serial.java:76)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.debug.Uploader.flushSerialBuffer(Uploader.java:75)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.debug.AvrdudeUploader.uploadViaBootloader(AvrdudeUploader.java:93)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.debug.AvrdudeUploader.uploadUsingPreferences(AvrdudeUploader.java:56)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.Sketch.upload(Sketch.java:1603)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.Sketch.exportApplet(Sketch.java:1568)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.Sketch.exportApplet(Sketch.java:1524)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at processing.app.Editor$DefaultExportHandler.run(Editor.java:2293)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; at java.lang.Thread.run(Unknown Source)
&lt;/pre&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
Fail. Okay, Google can help me, and so I sought after an answer.&amp;nbsp; After a little while, it was apparent that the permissions for the device were wrong.&amp;nbsp; I could have just switched to root, and chmod it, but that&#39;d be a temporary solution.&amp;nbsp; I decided to write a udev rule for arduino instead.&amp;nbsp; Here&#39;s what I came up with for /lib/udev/rules.d/90-arduino.rules (Your path may be different.&amp;nbsp; I&#39;m running Slackware Linux.)&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre class=&quot;brush:plain&quot;&gt;&amp;nbsp;
KERNEL==&quot;ttyACM*&quot;, ATTRS{product}==&quot;Arduino*&quot;, SYMLINK+=&quot;arduino%n&quot;, MODE=&quot;0666&quot;
&lt;/pre&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: inherit;&quot;&gt;Restarted udev, and plugged the Uno back in, clicked the &quot;Upload&quot; button again.&amp;nbsp; &quot;Done uploading.&quot; in the status bar.&amp;nbsp; Success!&amp;nbsp; My little arduino board is now blinking - - - __ __ __ - - -.&amp;nbsp; &lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://meisjohn.blogspot.com/feeds/7207214741525140735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://meisjohn.blogspot.com/2011/01/connecting-to-arduino-my-first-sketch.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/7207214741525140735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2771707043408054278/posts/default/7207214741525140735'/><link rel='alternate' type='text/html' href='http://meisjohn.blogspot.com/2011/01/connecting-to-arduino-my-first-sketch.html' title='Connecting to Arduino &amp; My First Sketch'/><author><name>meisjohn</name><uri>http://www.blogger.com/profile/09338185434459110243</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>