Programming Arduino with avrdude

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:

avrdude -p m328p -P /dev/ttyUSB0 -c arduino -b 19200 -F -u -U flash:w:blink.hex

But in my case it did not; instead, I got the following error:

avrdude: stk500_recv(): programmer is not responding

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 avr-gcc and 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:

arduino > build_transcript.txt

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 avrdude.

The magic words. My hours of hackery and detective work finally turned up this as the correct invocation of avrdude:

avrdude -v -p atmega328p -c arduino -P /dev/ttyUSB0 -b 57600 -D -U flash:w:blink.hex:i

The 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.

  1. -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 avrdude was throwing. The correct value seems to be 57600, at least for my set of devices, and the Arduino IDE build transcript confirms it.
  2. -p This specifies the target type. The configuration file for avrdude has a long list of supported targets, with all the important parameters for each. The Duemilanove uses Atmel’s Atmega 328p, and m328p is just the flag for this. Consult the documentation for a full list.
  3. -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 -P option. 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.

3 Comments on “Programming Arduino with avrdude”

  1. John Pateman says:

    Very helpful article. I was also having problems with my avrdude uploads when invoked directly but not when using the Arduino app. I was using the avrdude provided by CrossPack for OS X. Avrdude has a master config file (avrdude.conf). Doing a ‘diff’ on the version provided by the Arduino app and the version from CrossPack revealed a few differences – essentially some adjusted timing limits. I backed up the original CrossPack avrdude.conf and dropped in a copy of the version provided by Arduino and my board flashed first time.

  2. Sean says:

    Thanks for publishing this – I had a bad upload causing my arduino to not connect as a USB device (“unable to enumerate USB device” on Ubuntu Linux). My arduino IDE picked ttyS0 as the only port available and I couldn’t use the reset-and-quickly-upload-blink method.

    Using “while true; do ls -l /dev/ttyA*; done” on the command line I could see the arduino was briefly connecting as /dev/ttyACM0 before loading the last (bad) upload, upsetting the connection and causing /dev/ttyACM0 to disappear.

    I used your method to get a Blink.ino.hex and the output from the while command above in a second terminal to time the avrdude command to reset the arduino at the first attempt.

    Previously when my arduinos had become unresponsive, I think I must have still had /dev/ttyACM0 selected in the arduino IDE, so resetting them by uploading blink was straightforward. You saved my evening!

  3. Makagucci says:

    Thank you.

    I had gotten all but the baud rate. It had kept crossing my mind, the need for for me to set it. Thanks to you, I finally got there.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s