Arduino is a flexible, usable, and quite popular physical computing platform. One of the strengths of Arduino is it’s well-developed and well-supported IDE, which takes almost all of the grotesque contortions out of the build process. The Arduino IDE, for its level of usability, does a pretty good job of supporting tweaks to build process, but I’ve become a bit of compilers geek, and so I wanted to figure out how to flash arbitrary executables onto the board. I misguidedly believed that the task would be straightforward and easy, and although it was once I figured out the magic words, the quest for answers was not. What follows is a short exegesis of the incantations for summoning the demons and binding them to your compile-time bidding. As always, comments and corrections are welcome.
Materials. I conducted my experiment on a System76 Pangolin laptop running Ubuntu 10.10, but I have no reason (yet) to believe that a similar procedure shouldn’t work with other platforms that support all the right tools. You’ll also need
avr-gcc, a cross-compiler for the AVR chip that runs the Arduino, and
avrdude, a very handy (but not always friendly) utility for loading code onto Atmel AVR microcontrollers. I used version 4.3.5 of
avr-gcc and 5.10 of
avrdude. Obviously, you’ll also need an Arduino. I’m presently using the Duemilanove, which is not quite the latest Arduino but which, as of this writing, seems to be better supported by the tools than the latest Arduino, the Uno. Programming microcontrollers often requires a programmer and a parallel cable, or multiple USB cables, but Arduino ships with its own bootloader, and so it is possible to load and run code using only a single USB connecting your computer to the board. (Unless you’ve broken your Arduino or done something deliberately experimental, the bootloader should be intact.) You’ll also need a USB standard A to USB standard B cable for the connection, but if you bought the Arduino as part of a kit, it almost certainly came with one.
Getting Started The start of my search was this rather helpful blog post on programming Arduino with avr-gcc by Javier Valcarce. The post seems very thorough and clear, and I was able to reproduce all the correct behaviors for avr-gcc using the given instructions. In fact, I recommend following them if you want to use
avr-gcc to compile straight C (not C++, not Processing) programs for your Arduino. However, I wasn't able to reproduce the correct behaviors for
avrdude. Supposing that the binary we wish to load is called
blink.hex, and adapting Mr. Valcarce's procedure, the following invocation should work:
But in my case it did not; instead, I got the following error:
Apparently many people encountered this problem; the forums contain numerous pleas for help in addressing this error. I hacked around, read manual pages, and tried all of the suggestions I could find, but none resolved the problem.
Taking a clue from Arduino IDE. The really mysterious thing about this problem is that compiling and uploading from the Arduino IDE seems to work just fine, provided that you choose the right board type and communication port. The IDE uses both
avrdude, and so it's only reasonable to suppose that it must invoke them when a program is uploaded to the board. Fortunately, it turns out that it's possible to view the invocation that the IDE uses. To do so, locate the
preferences.txt file that Arduino IDE reads to determine its settings. At the bottom of this file, add the following two lines:
(It couldn't hurt to also put a comment near your changes that you can find them later if you want to change the settings back.)
Now, when you hit the 'upload' button on the IDE, you should be able to view a full transcript of the build-and-upload process. Unfortunately, this is all written to a tiny window below the editor. You might find it more helpful to invoke the IDE from the command line as:
Which will also write the transcript to the given text file
build_transcript.txt, so that you can view it later. Now, if you're able to compile and upload programs using the IDE, you should be able to infer the right invocation of
The magic words. My hours of hackery and detective work finally turned up this as the correct invocation of avrdude:
man page for
avrdude gives a full description of all the options, but it's worth explaining a few of these, because my findings seem to contradict much of the advice floating around the forums.
- -b This option sets the baud rate for communicating with the board. Most documents I read lead me to believe the baud rate should be set to 19200. However, this is apparently far too slow, and most likely accounts for the failure-to-respond error that
avrdudewas throwing. The correct value seems to be 57600, at least for my set of devices, and the Arduino IDE build transcript confirms it.
- -p This specifies the target type. The configuration file for
avrdudehas a long list of supported targets, with all the important parameters for each. The Duemilanove uses Atmel's Atmega 328p, and
m328pis just the flag for this. Consult the documentation for a full list.
- -P Specifies the communication port. As soon as the Arduino is hooked up to your USB, it should be assigned a file in
/dev/, and this is the string that needs to be passed to the
-Poption. The easiest way to find this is just
dmesg | grep ttyUSB*
In most cases, the correct port will be the last (often only) one to appear.
Closing thoughts. I probably could have saved a lot of time if only I had known up front how to view the Arduino IDE build transcript. Unfortunately, I made the classic mistake of just charging through one speculative trial after another, each time thinking that I had almost gotten to the answer. However, this was my own mistake: the official Arduino page briefly explains the build process, and does mention how to turn on a verbose build transcript. Many commenters online seem to have been equally perplexed by the ability to build and upload using the IDE but their apparent inability to use
avrdude from the command line. This simple approach can hopefully save everyone a whole lot of trouble.
Arduino is a really excellent piece of work, and this seems like as good a time as any to give a shout out to the many, many people responsible for its creation, maintenance and continued evolution. It sounds cheesy, but it's essential to remember: nice things like this exist because curious, industrious people take it upon themselves to create and to share. If you like the results, then educate yourself, and get involved in the community.