<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    
    <title>Code V.igoro.us - Arduino</title>
    <link>http://code.v.igoro.us/</link>
    <description>Dustin J. Mitchell</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.6 - http://www.s9y.org/</generator>
    <pubDate>Sun, 18 Apr 2010 04:39:57 GMT</pubDate>

    <image>
        <url>http://code.v.igoro.us/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Code V.igoro.us - Arduino - Dustin J. Mitchell</title>
        <link>http://code.v.igoro.us/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>LCD Display and TMP102 sensor</title>
    <link>http://code.v.igoro.us/archives/55-LCD-Display-and-TMP102-sensor.html</link>
            <category>Arduino</category>
    
    <comments>http://code.v.igoro.us/archives/55-LCD-Display-and-TMP102-sensor.html#comments</comments>
    <wfw:comment>http://code.v.igoro.us/wfwcomment.php?cid=55</wfw:comment>

    <slash:comments>4</slash:comments>
    <wfw:commentRss>http://code.v.igoro.us/rss.php?version=2.0&amp;type=comments&amp;cid=55</wfw:commentRss>
    

    <author>nospam@example.com (Dustin J. Mitchell)</author>
    <content:encoded>
    &lt;p&gt;It is &lt;i&gt;incredibly&lt;/i&gt; easy to throw things together with an Arduino.  It&#039;s common to see criticism of the device when it&#039;s used in in projects that don&#039;t require even a fraction of its power, and that might be justified.  As a flexible platform for test-driving complex modules, though, the Arduino hits the mark perfectly on flexibility and usability.&lt;/p&gt;

&lt;p&gt;I don&#039;t have a particular project in mind for my Arduino, but since I don&#039;t have a multimeter or an oscilloscope, I want to use it as a test harness for various basic components as I experiment with them.  To this end, I bought a cute &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.sparkfun.com/commerce/product_info.php?products_id=9054&#039;]);&quot;  href=&quot;http://www.sparkfun.com/commerce/product_info.php?products_id=9054&quot;&gt;16x2 character amber LCD display&lt;/a&gt;.  With thoughts of building a fermentation-temperature monitor and learning about the I&lt;sup&gt;2&lt;/sup&gt;C bus, I also bought a relatively cheap &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.sparkfun.com/commerce/product_info.php?products_id=9418&#039;]);&quot;  href=&quot;http://www.sparkfun.com/commerce/product_info.php?products_id=9418&quot;&gt;TMP102 and breakout board&lt;/a&gt;.  With a little bit of reading, I was able to stitch them together quickly and easily.
 &lt;h2&gt;LCD Display&lt;/h2&gt;&lt;/p&gt;

&lt;p&gt;The display I purchased is command-driven via a 4-bit parallel port.  It&#039;s a ST7066, compatible with HD44780.  There are two datasheets available -- one for the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.sparkfun.com/datasheets/LCD/st7066.pdf&#039;]);&quot;  href=&quot;http://www.sparkfun.com/datasheets/LCD/st7066.pdf&quot;&gt;ST7066&lt;/a&gt;, and one for the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.sparkfun.com/datasheets/LCD/ADM1602K-NSA-FBS-3.3v.pdf&#039;]);&quot;  href=&quot;http://www.sparkfun.com/datasheets/LCD/ADM1602K-NSA-FBS-3.3v.pdf&quot;&gt;assembled board&lt;/a&gt;.  The latter adequately described the pinout through unattributed copying from the former, but was otherwise useless.  &quot;Qiu&quot;, &quot;Chen&quot;, and &quot;Ye&quot;, all three of whom helpfully signed the cover page, should be ashamed.  Anyway, here&#039;s a brief description of the pins and some more details I culled from the ST7066 datasheet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;V&lt;sub&gt;ss&lt;/sub&gt; (ground) and V&lt;sub&gt;dd&lt;/sub&gt; (positive supply): these are rated up to 7V, so running from the Arduino&#039;s 5V supply is great.&lt;/li&gt;
&lt;li&gt;V&lt;sub&gt;0&lt;/sub&gt; sets the LCD contrast.  Short on jumpers, I initially assumed I could leave this unconnected to get &quot;reasonable&quot; contrast.  Not so!  I tried setting up a few voltage dividers to get the right contrast, without any luck.  Plan to add a 10k pot between ground and the positive supply, and tie the wiper to this pin.&lt;/li&gt;
&lt;li&gt;RS (register select) selects whether an operation is to configuration registers (0) or RAM (1)&lt;/li&gt;
&lt;li&gt;R/W (read/write) selects whether an operation reads or writes to the device&lt;/li&gt;
&lt;li&gt;DB0-DB7 is the data bus&lt;/li&gt;
&lt;li&gt;E (enable), strobed to move a byte across the data bus&lt;/li&gt;
&lt;li&gt;LED+/LED- supply power to the LED backlight, and can be wired directly to the 5V supply.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Arduino has a lot of digital pins, but all the same it&#039;s handy to save a few pins.  The display supports reading character and font data, but that&#039;s not much use: the Arduino can remember whatever it needs to.  So we won&#039;t need the R/W pin, and can tie it to ground (read) instead.&lt;/p&gt;

&lt;p&gt;The display can operate in two data lengths (controlled by the DL configuration bit).  In the default mode, only 4 bits (DB4-DB7) on the parallel bus are used.  The display starts in 8-bit mode, but fortunately the DL bit comes in at pin DB4, so it&#039;s relatively easy to reset the data length with only 4 pins connected.  Note that there&#039;s an odd sequencing required here, where you need to set 8-bit mode three times &lt;i&gt;before&lt;/i&gt; setting 4-bit mode.  Don&#039;t worry, though: the Arduino &lt;i&gt;LiquidCrystal&lt;/i&gt; library takes care of that for you.&lt;/p&gt;

&lt;p&gt;So aside from pins tied to V+ or GND, we only need 6 digital I/O pins.  It&#039;s best to avoid the pins that have other functions on the Arduino: 0 and 1 are RS-232 I/O, and 13 is the onboard LED.  I used pins 2-5 for the data bus, pin 12 for E, and pin 13 for RS, since that was at the top of the LiquidCrystal example.  V&lt;sub&gt;ss&lt;/sub&gt;, LED-, and R/W go to GND; V&lt;sub&gt;dd&lt;/sub&gt; and LED+ go to the 5V supply; and V&lt;sub&gt;0&lt;/sub&gt; is wired as described above.&lt;/p&gt;

&lt;p&gt;From there on out, it&#039;s a straightforward application of the &lt;i&gt;LiquidCrystal&lt;/i&gt; library:&lt;/p&gt;

&lt;pre&gt;
#include &amp;lt;LiquidCrystal.h&amp;gt;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

void setup() {    
    lcd.begin(16, 2); 
}

void loop() {
    lcd.setCursor(0, 0);
    lcd.print(&quot;Hello, World&quot;);
}
&lt;/pre&gt;

&lt;p&gt;Note that the display itself is capable of a number of interesting things not supported by the library.  It has an 80-byte character memory, and can scroll that through the display without rewriting the entire screen every time.  It can also accept 8 custom 5x11 glyphs, making rudimentary animation possible.&lt;/p&gt;

&lt;h2&gt;TMP102&lt;/h2&gt;

&lt;p&gt;The TMP102 is ridiculously tiny - smaller than the SMD resistors that Sparkfun has placed around it on the breakout board.  It senses temperature internally, which means it&#039;s basically monitoring the temperature of its leads.&lt;/p&gt;

&lt;p&gt;The device speaks I&lt;sup&gt;2&lt;/sup&gt;C (also known as the two-wire interface or SMBus), which makes it pretty easy to connect to the Arduino.  The MCU speaks I&lt;sup&gt;2&lt;/sup&gt;C via hardware, so the corresponding Arduino library doesn&#039;t even need to bit-bang the data.  On the Duemilanove, it uses analog-in pin 4 for SDA and analog-in pin 5 for SCL.  You&#039;ll also need to hook up V+ to the &lt;b&gt;3.3V pin&lt;/b&gt; on the Arduino (the device is only specified for 3.6V) and GND to the TMP102&#039;s GND.  Finally, the TMP102&#039;s ADD0 pin can cleverly select one of four addresses for the device by tying it to one of these four pins.  I tied it to GND, giving address 0b1001000.  ALARM is an output pin, so you can leave it unconnected.&lt;/p&gt;

&lt;p&gt;The TMP102 is a very nice low-power device that&#039;s designed to handle several common tasks without any interaction from the MCU - it can trigger an interrupt when the temperature strays from a configured boundaries, poll temperature on a relatively slow schedule, or even poll on command.  I didn&#039;t use any of that, relying on the device to simply sample the temperature on its own schedule.&lt;/p&gt;

&lt;p&gt;The TMP102 has four registers, but we&#039;ll only use one -- temperature (0b01).  Like many devices, this one multiplexes addresses and data over the same bus.  To read a register, you first select the register by writing it to the device, then read the 16-bit value, again with the MSB first.  Once a register is selected, it can be read multiple times.&lt;/p&gt;

&lt;p&gt;The device&#039;s temperature register contains a two&#039;s-complement 12-bit value, left-aligned, where 0x7FF is 128&amp;deg;C; equivalently, a change of one unit in the 12-bit value is equivalent to 0.0625&amp;deg;C.&lt;/p&gt;

&lt;h2&gt;Putting it Together&lt;/h2&gt;

&lt;p&gt;The obvious combination of these tools is to display the ambient temperature on the LCD screen.  Here&#039;s the program to do so:&lt;/p&gt;

&lt;pre&gt;
#include &amp;lt;Wire.h&amp;gt;
#include &amp;lt;LiquidCrystal.h&amp;gt;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 

#define TEMP_REG 0b00000000
int tmp102 = 0b1001000;  // with ADD0 tied to ground

void setPR(int reg) {
  Wire.beginTransmission(tmp102);
  Wire.send(reg);
  Wire.endTransmission();
}

int getReg() {
  unsigned char lo, hi;

  Wire.requestFrom(tmp102, 2);
  hi = Wire.receive();
  lo = Wire.receive();
  return (hi &lt;&lt; 8) + lo;
}

void setup()   {    
  lcd.begin(16, 2);
  Wire.begin();
  setPR(TEMP_REG);
}

void show_temp() {
  int temp_reg = getReg();
  lcd.setCursor(0, 0);
  show_bin(temp_reg);

  temp_reg &gt;&gt;= 4;

  float temp_C = temp_reg * 0.0625;
  float temp_F = (temp_C * 9 / 5) + 32;

  lcd.setCursor(0, 0);
  lcd.print(temp_C);
  lcd.print(&quot;\xdf&quot;&quot;C  &quot;);
  lcd.setCursor(0, 1);
  lcd.print(temp_F);
  lcd.print(&quot;\xdf&quot;&quot;F  &quot;);
}

void loop() {
  show_temp();
}
&lt;/pre&gt;

&lt;p&gt;The &lt;tt&gt;setup&lt;/tt&gt; function sets up the LCD, then uses &lt;tt&gt;setPR&lt;/tt&gt; to point the TMP102 at the temperature register.  Subsequent reads will then return the 12-bit encoded temperature.  The &lt;tt&gt;loop&lt;/tt&gt; function reads the temperature register, decodes it, and displays the result in both Celsius and Fahrenheit.&lt;/p&gt;

&lt;p&gt;Note that this is horrendously inefficient: the TMP102 only measures temperature every 26ms or so, during which &lt;tt&gt;loop&lt;/tt&gt; will probably run a half-dozen times, feeding the same time strings to the LCD each run.  It would be much better to put the TMP102 in one-shot mode, and measure the temperature at a much lower frequency - say once a second - with a correspondingly low update frequency for the display.  I&#039;ll leave that as an exercise for the reader.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 18 Apr 2010 02:22:01 +0000</pubDate>
    <guid isPermaLink="false">http://code.v.igoro.us/archives/55-guid.html</guid>
    
</item>
<item>
    <title>Charlieplexing: watch your voltage levels!</title>
    <link>http://code.v.igoro.us/archives/35-Charlieplexing-watch-your-voltage-levels!.html</link>
            <category>Arduino</category>
    
    <comments>http://code.v.igoro.us/archives/35-Charlieplexing-watch-your-voltage-levels!.html#comments</comments>
    <wfw:comment>http://code.v.igoro.us/wfwcomment.php?cid=35</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://code.v.igoro.us/rss.php?version=2.0&amp;type=comments&amp;cid=35</wfw:commentRss>
    

    <author>nospam@example.com (Dustin J. Mitchell)</author>
    <content:encoded>
    &lt;p&gt;&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Charlieplexing&#039;]);&quot;  href=&quot;http://en.wikipedia.org/wiki/Charlieplexing&quot;&gt;Charlieplexing&lt;/a&gt; is a technique to allow &lt;i&gt;n&lt;/i&gt; tristate digital output pins to control &lt;i&gt;n(n-1)&lt;/i&gt; LEDs, by exploiting the high-impedence state of the output pins and the reverse-bias tolerance of LEDs.&lt;/p&gt;

&lt;p&gt;I put together a circuit to test this out, similar to the 6-LED diagram in the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Charlieplexing#Expanding:_tri-state_logic&#039;]);&quot;  href=&quot;http://en.wikipedia.org/wiki/Charlieplexing#Expanding:_tri-state_logic&quot;&gt;Wikipedia entry&lt;/a&gt;.  I added three 220Ω resistors, though.  This ASCII art sums it up nicely:&lt;/p&gt;

&lt;pre&gt;
      +---&gt;|---+          +---&gt;|---+          +---&gt;|---+    
      |  LED1  |          |  LED3  |          |  LED5  |
 &lt;----|        |-/\/\-+---|        |-/\/\-+---|        |-/\/\-+--&gt;
      |  LED2  |      |   |  LED4  |      |   |  LED6  |      |   
      +---|&lt;---+      R   b---|&lt;---+      G   +---|&lt;---+      B   
&lt;/pre&gt;

&lt;p&gt;where R, G, and B are the three connections to the Arduino, and the arrows on the left and right side are joined by a jumper.  I put together some simple Arduino-level code to drive this layout in a simple counter sequence, and fired it up.&lt;/p&gt;

&lt;p&gt;One thing I will say about the Arduino: &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/diveintomark.org/archives/2010/01/29/tinkerers-sunset&#039;]);&quot;  href=&quot;http://diveintomark.org/archives/2010/01/29/tinkerers-sunset&quot;&gt;tinkering&lt;/a&gt; pays off.  After the usual forgotten-semicolon cleanup, LEDs started blinking immediately.  This is good, because I don&#039;t have much of an Arduino-debugging toolbox at this point!&lt;/p&gt;

&lt;p&gt;Anyway, there&#039;s a problem.  When an LED is fully illuminated, two other LEDs glow at about 50% brightness.  For example, when LED1 is on, LED4 and LED6 glow too.  It&#039;s not hard to see why: to turn LED1 on, the arduino drives R low and B high.  The path through LED1 is intended, but LED4 and LED6 are also forward-biased in series, albeit with more resistance inline and the voltage-drop from two LEDs.  Can this be prevented?&lt;/p&gt;

&lt;p&gt;Let&#039;s work out the math here, using the resistance &lt;i&gt;r&lt;/i&gt; as the only parameter I can change.  The LEDs I&#039;m using (&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.sparkfun.com/commerce/product_info.php?products_id=9592&#039;]);&quot;  href=&quot;http://www.sparkfun.com/commerce/product_info.php?products_id=9592&quot;&gt;5mm Green LEDs from CHINA YOUNG SUN&lt;/a&gt;) don&#039;t have a lot of performance data, but do list a forward voltage drop of 1.8-2.2V, so let&#039;s use 2V.  My Arduino is running from the USB power at 5V.  The resistor to the left of R defines the current through that leg for the remaining &lt;i&gt;5-2 = 3V&lt;/i&gt;, so &lt;i&gt;I&lt;sub&gt;1&lt;/sub&gt;&lt;/i&gt; is &lt;i&gt;3/r&lt;/i&gt;.  On the leg containing LED4 and LED6 a total of 1V remains across two resistors, so &lt;i&gt;I&lt;sub&gt;4&lt;/sub&gt;&lt;/i&gt; and &lt;i&gt;I&lt;sub&gt;6&lt;/sub&gt;&lt;/i&gt; are both &lt;i&gt;1/2r&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;The LED datasheet lists a maximum average current (20ma) and peak current (30ma), but doesn&#039;t list a minimum current.  Guessing 1ma, I need &lt;i&gt;1/2r &amp;lt; 0.001&lt;/i&gt;, so &lt;i&gt;r &amp;gt; 500&lt;/i&gt;.  At that point, though, &lt;i&gt;I&lt;sub&gt;1&lt;/sub&gt;&lt;/i&gt; is just 6ma - not nearly bright enough to impress, particularly with a 16% duty cycle when multiplexing all 6 LEDs.  All the same, I figured I&#039;d try it.  The closest resistor I had was 470Ω, so I gave that a shot.  The result was bad on all fronts: the expected LED is dim, and the unwanted LEDs are still visible.&lt;/p&gt;

&lt;p&gt;I suspect that, to get this to work, I&#039;d need to reduce the supply voltage to something less than twice the LEDs&#039; forward voltage drop.  Then two LEDs in series would carry no current.  I considered doing this with a simple voltage divider on each microcontroller pin, but this of course ruins the tri-state behavior that&#039;s critical to charlieplexing.  I could build that by using two transistors for each pin, but by that point the benefits of charlieplexing in terms of component count are long lost.&lt;/p&gt;

&lt;p&gt;So, in short, for good charlieplexing, make sure that your source voltage is less than twice the &lt;i&gt;V&lt;sub&gt;f&lt;/sub&gt;&lt;/i&gt; of your LEDs.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;[EDIT: it turns out, after some futzing that this also &quot;works fine&quot; if you just leave out the ballast resistors.  Presumably this relies on a limited duty cycle and a &quot;high enough&quot; internal resistance to not melt the LEDs]&lt;/i&gt; &lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 31 Jan 2010 02:58:57 +0000</pubDate>
    <guid isPermaLink="false">http://code.v.igoro.us/archives/35-guid.html</guid>
    
</item>
<item>
    <title>2005 Mac Mini as an Arduino Development System</title>
    <link>http://code.v.igoro.us/archives/32-2005-Mac-Mini-as-an-Arduino-Development-System.html</link>
            <category>Arduino</category>
    
    <comments>http://code.v.igoro.us/archives/32-2005-Mac-Mini-as-an-Arduino-Development-System.html#comments</comments>
    <wfw:comment>http://code.v.igoro.us/wfwcomment.php?cid=32</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://code.v.igoro.us/rss.php?version=2.0&amp;type=comments&amp;cid=32</wfw:commentRss>
    

    <author>nospam@example.com (Dustin J. Mitchell)</author>
    <content:encoded>
    &lt;p&gt;I have an early Mac Mini that&#039;s not good for much of anything anymore.  It&#039;s not too fast, and it&#039;s a 32-bit PPC chip, so most proprietary-blob software is off-limits, meaning it doesn&#039;t make a good media PC.  I put Gentoo on it, and decided to use it to interface with my new Arduino Duemilanove.  I&#039;m more interested in the Arduino as a processor I can play with, rather than a gateway to flashing LEDs, so I don&#039;t want the full IDE - just a compiler and assembler, and a USB-based programmer.&lt;/p&gt;

&lt;p&gt;This post documents the process I followed to set all of this up. &lt;h2&gt;Smoketest&lt;/h2&gt;
As a smoketest, I downloaded the Arduino application on my Macbook and modified one of the blinkie examples to make a chaser for a 7-segment display I had handy.  I tweaked the code, hooked up some jumpers, and clicked the &quot;Upload&quot; button.  The code was pretty simple, but I did encounter an elementary digital logic problem: my display was common-anode, but a digital HIGH is +5V.  I can&#039;t simply ground the common pin - what to do, then?  My confusion was based on the false assumption that logic LOW is unconnected - of course, it&#039;s actually ground.  So I connected the common anode to the +5V rail, and set up to illuminate each segment with a LOW digital out signal (routed through a 220Ω resistor).  Here&#039;s the code:&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/284880.js&quot;&gt;&lt;/script&gt;

&lt;h2&gt;Software&lt;/h2&gt;

&lt;p&gt;Next up, installing the requisite software on the Mini.  First, the crossdev tools.  Most documentation suggests simply:&lt;/p&gt;

&lt;pre&gt;
emerge crossdev
crossdev --target avr
&lt;/pre&gt;

&lt;p&gt;But this failed:&lt;/p&gt;

&lt;pre&gt;
 * ERROR: cross-avr/avr-libc-1.6.4 failed.
 * Call stack:
 *               ebuild.sh, line   49:  Called pkg_setup
 *   avr-libc-1.6.4.ebuild, line   40:  Called die
 * The specific snippet of code:
 *              die &quot;AVR toolchain not found&quot;
 *  The die message:
 *   AVR toolchain not found
&lt;/pre&gt;

&lt;p&gt;The solution, available from &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/bugs.gentoo.org/230343&#039;]);&quot;  href=&quot;http://bugs.gentoo.org/230343&quot;&gt;Gentoo bug #230343&lt;/a&gt;, is to add the &lt;tt&gt;--without-headers&lt;/tt&gt; flag, which instructs the crossdev tool to build the compiler first, then the C library.  The &lt;tt&gt;-s4&lt;/tt&gt; builds a stage-4 compiler, including the C++ frontend.&lt;/p&gt;

&lt;pre&gt;
crossdev -s4 --target avr --without-headers
&lt;/pre&gt;

&lt;p&gt;This takes a &lt;i&gt;long&lt;/i&gt; time on a system of this vintage.&lt;/p&gt;

&lt;p&gt;While I was in the root shell, I installed &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/avra.sourceforge.net/&#039;]);&quot;  href=&quot;http://avra.sourceforge.net/&quot;&gt;avra&lt;/a&gt;, an AVR assembler:&lt;/p&gt;

&lt;pre&gt;
emerge avra
&lt;/pre&gt;

&lt;p&gt;Next up, the kernel driver.  For the particular board I have, I need kernel support for the FTDI USB-to-serial chip.  The driver is &lt;tt&gt;ftdi_sio&lt;/tt&gt;, and the kernel option is &lt;i&gt;Device Drivers -&gt; USB Support -&gt; USB Serial Converter Support -&gt; USB FTDI Single Port Serial Driver&lt;/i&gt;.  If you happen to be on a PPC machine, don&#039;t forget to run &lt;tt&gt;ybin -v&lt;/tt&gt; after upgrading the kernel.  With this set up, the USB serial device appears at &lt;tt&gt;/dev/ttyUSB0&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the programmer.  I&#039;m using &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.nongnu.org/avrdude/&#039;]);&quot;  href=&quot;http://www.nongnu.org/avrdude/&quot;&gt;avrdude&lt;/a&gt;.  I installed this from portage.  I had to install version 5.8 (keyworded ~ppc) to get the ATMEGA328P support.  The problem is, avrdude doesn&#039;t automatically reset the device by pulsing DTR. The Arduino IDE does this just before running avrdude.  There is a patch available on &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/savannah.nongnu.org/patch/?6866&#039;]);&quot;  href=&quot;http://savannah.nongnu.org/patch/?6866&quot;&gt;Avrdude bug #6866&lt;/a&gt;, but it hasn&#039;t yet been merged.  Rather than try to set up an avrdude ebuild in a local portage overlay, I opted for the simpler solution described &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1201441300&#039;]);&quot;  href=&quot;http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1201441300&quot;&gt;in the arduino.cc forums&lt;/a&gt;: reset the device with a perl script just before invoking avrdude.  The code is simple:&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/285343.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;I needed to emerge dev-perl/Device-SerialPort first. Then, to upload a new program:&lt;/p&gt;

&lt;pre&gt;
./pulse &amp;&amp;amp; avrdude -c arduino -b 57600 -p m328p -D -U flash:w:/tmp/Blink.cpp.hex:i -P /dev/ttyUSB0
&lt;/pre&gt;

&lt;h2&gt;Compiling&lt;/h2&gt;

&lt;p&gt;Up to now, I&#039;ve been using Blink.cpp.hex, compiled earlier on the Macbook.  Now it&#039;s time to start building locally.  All of the libraries and headers that make an Arduino sketch into an executable are in the &lt;tt&gt;dev-embedded/arduino&lt;/tt&gt; ebuild.  I keyworded this (~x86 since there&#039;s no ppc keyword in the ebuild) and added &lt;tt&gt;USE=-java&lt;/tt&gt; since I don&#039;t need the IDE, and emerged it.&lt;/p&gt;

&lt;p&gt;I copied &lt;tt&gt;/usr/share/arduino-0017/hardware/cores/arduino/Makefile&lt;/tT&gt; into my sketch directory and ran make.  The result:&lt;/p&gt;

&lt;pre&gt;
/bin/sh: /usr/share/arduino-0017/hardware/cores/arduino/Print.d: Permission denied
&lt;/pre&gt;

&lt;p&gt;There are some comments in the ebuild about this -- apparently the IDE builds the &lt;tt&gt;.d&lt;/tt&gt; files when it is first run, using group id &lt;tt&gt;uucp&lt;/tt&gt;.  The easiest fix was just to run make as root, once, to build these files.&lt;/p&gt;

&lt;p&gt;The Makefile references &lt;tt&gt;wiring_serial.c&lt;/tt&gt;, but this file is not present in the distribution.  I removed it from the Makefile.  Presumably I&#039;ll be on my own to configure serial I/O?&lt;/p&gt;

&lt;p&gt;I&#039;m starting to get the impression that using the IDE is the smart way to go here!  The next error is from the linker, unable to find its script:&lt;/p&gt;

&lt;pre&gt;
/usr/libexec/gcc/avr/ld: cannot open linker script file ldscripts/avr5.x: No such file or directory
&lt;/pre&gt;

&lt;p&gt;This is &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/bugs.gentoo.org/show_bug.cgi?id=147155&#039;]);&quot;  href=&quot;http://bugs.gentoo.org/show_bug.cgi?id=147155&quot;&gt;Gentoo bug #147155&lt;/a&gt;, which at the moment is not fixed.  The workaround:&lt;/p&gt;

&lt;pre&gt;
ln -s /usr/lib/binutils/avr/2.20/ldscripts /usr/avr/lib/ldscripts
&lt;/pre&gt;

&lt;p&gt;And finally, we have a build:&lt;/p&gt;

&lt;pre&gt;
dustin@erdos ~/tmp/Blink $ make
# Here is the &quot;preprocessing&quot;.
# It creates a .cpp file based with the same name as the .pde file.
# On top of the new .cpp file comes the WProgram.h header.
# At the end there is a generic main() function attached.
# Then the .cpp file will be compiled. Errors during compile will
# refer to this new, automatically generated, file.
# Not the original .pde file you actually edit...
test -d applet || mkdir applet
echo &#039;#include &quot;WProgram.h&quot;&#039; &gt; applet/Blink.cpp
cat Blink.pde &gt;&gt; applet/Blink.cpp
cat /usr/share/arduino-0017/hardware/cores/arduino/main.cxx &gt;&gt; applet/Blink.cpp
/usr/bin/avr-gcc -mmcu=atmega168 -I. -gstabs -DF_CPU=16000000 -I/usr/share/arduino-0017/hardware/cores/arduino -Os -Wall -Wstrict-prototypes -std=gnu99  -o applet/Blink.elf applet/Blink.cpp -L. applet/core.a -L/usr/avr/lib -lm
cc1plus: warning: command line option &quot;-Wstrict-prototypes&quot; is valid for Ada/C/ObjC but not for C++
cc1plus: warning: command line option &quot;-std=gnu99&quot; is valid for C/ObjC but not for C++
/usr/bin/avr-objcopy -O ihex -R .eeprom applet/Blink.elf applet/Blink.hex


   text    data     bss     dec     hex filename
      0    1244       0    1244     4dc applet/Blink.hex
&lt;/pre&gt;

&lt;p&gt;running &lt;tt&gt;make upload&lt;/tt&gt; as root, right after pressing the reset button in the board, successfully uploads the program.  Blinkies!&lt;/p&gt;

&lt;h2&gt;Cleanup&lt;/h2&gt;

&lt;p&gt;A few small changes will make a lot of this easier.  First, I want to make sure that the USB device is writable by a non-root user, using udev.  First, I used the following command to get the udev identifying information for the device.&lt;/p&gt;

&lt;pre&gt;
udevadm info --attribute-walk -n /dev/ttyUSB0
&lt;/pre&gt;

&lt;p&gt;The identifiers for the device are given from most-specific to least-specific.  The device itself doesn&#039;t have much to identify it:&lt;/p&gt;

&lt;pre&gt;
  looking at device &#039;/class/tty/ttyUSB0&#039;:
    KERNEL==&quot;ttyUSB0&quot;
    SUBSYSTEM==&quot;tty&quot;
    DRIVER==&quot;&quot;
&lt;/pre&gt;

&lt;p&gt;but I need something to match on this device, so I used &lt;tt&gt;SUBSYSTEM==&quot;tty&quot;&lt;/tt&gt;.  To avoid confusion with other tty devices, though, I needed something more specific.  Looking at the parent entry, I see&lt;/p&gt;

&lt;pre&gt;
    ATTRS{interface}==&quot;FT232R USB UART&quot;
&lt;/pre&gt;

&lt;p&gt;which looks like a good identifier for this component.  Aside from setting the ownership and permissions, I decided to add a &lt;tt&gt;/dev/avr&lt;/tt&gt; symlink, too.  The completed rule is:&lt;/p&gt;

&lt;pre&gt;
SUBSYSTEM==&quot;tty&quot;, ATTRS{idVendor}==&quot;0403&quot;, ATTRS{idProduct}==&quot;6001&quot; GROUP=&quot;users&quot;, MODE=&quot;0666&quot;, SYMLINK+=&quot;avr&quot;
&lt;/pre&gt;

&lt;p&gt;The first three fields match the device using the numbers from &lt;tt&gt;lsusb&lt;/tt&gt;, and the last three set the proper group-id, mode, and dev-tree symlink for the device.  I put this rule in &lt;tt&gt;/etc/udev/rules.d/10-user.rules&lt;/tt&gt; and updated udev:&lt;/p&gt;

&lt;pre&gt;
udevadm trigger
&lt;/pre&gt;

&lt;p&gt;sure enough, &lt;tt&gt;/dev/avr&lt;/tt&gt; now exists.  I added this path as the &lt;tt&gt;PORT&lt;/tt&gt; in the Makefile.&lt;/p&gt;

&lt;p&gt;The second problem is that the makefile is not smart enough to reset the unit before uploading.  That&#039;s easily fixed, using a variant of the &lt;tt&gt;pulse&lt;/tt&gt; script from above, by adding a perl invocation to the Makefile (don&#039;t forget the whitespace must be a tab character!):&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/285472.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Finally, I commented out the value of &lt;tt&gt;CDEBUG&lt;/tt&gt; in the Makefile, as I don&#039;t see any real utility for debug symbols on a microcontroller.&lt;/p&gt;

&lt;h2&gt;Summary&lt;/h2&gt;

&lt;p&gt;This turned out to be a lot of work -- the Arudino developers have done a good job of encapsulating a lot of complexity in a nice, easy-to-use IDE.  But now I can use my usual editor and workflow to develop programs for the ATMEGA328P, and that means a lot to me!&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 24 Jan 2010 00:00:28 +0000</pubDate>
    <guid isPermaLink="false">http://code.v.igoro.us/archives/32-guid.html</guid>
    
</item>

</channel>
</rss>