Wednesday, June 27, 2012

Writing sketches to a ATmega328 pre-loaded with the Arduino Uno bootloader using an Arduino Uno and ArduinoISP

Hopefully this post is not excessively redundant, but I had difficulty finding clear instructions on the Internet on how to:

Upload a new sketch to a standalone ATmega328 (pre-loaded with an Arduino bootloader) using an existing Arduino Uno without removing the existing ATmega chip from my Uno.

This is useful because:
  • You won't need to buy an external AVR programmer (this method is very low cost!)
  • It doesn't require constant removal of the on-Arduino ATmega328 chip to "directly" use the Tx/Rx lines (because those pins will eventually break
I found several posts on how to program a standalone ATmega with a bootloader (for example, the main ArduinoISP page), but those pages typically did not discuss uploading sketches using ArduinoISP.  I did find one page suggesting a (complicated) method of doing this by modifying boards.txt, though I did not have success using that method.

Anyway, some trial and error over the course of an hour or so revealed that uploading sketches to an external ATmega is very simple.  For this, you will need:
  • An Arduino Uno (mine is rev 3)
  • An ATmega328 microprocessor pre-loaded with Arduino bootloader (I bought this one, preloaded with the Uno optiboot bootloader, from Sparkfun).
  • A 16 MHz crystal oscillator
  • Two 22 pF ceramic capacitors
  • A 10 kOhm resistor
  • A capacitor with capacitance > 10 uF (I used a 22 uF capacitor, but others have reported success with  10 uF capacitors).
First, wire up the external ATmega circuitry:
  • Pins 7 and 20 to +5V
  • Pins 8 and 22 to Gnd
  • Pin 1 (reset) to +5V through a 10 kOhm resistor
  • Crystal oscillator to pins Z and K
  • A 22 pF capacitor connecting each pin of the oscillator to ground
A good diagram is found here: http://www.jameco.com/Jameco/workshop/JamecoBuilds/arduinocircuit.html (Note: those instructions also connect pin 21 [AREF] to Gnd, but I did not do so when I tried this).

Next, connect your Arduino Uno to the USB port of your computer, open up Arduino IDE (version 1.0.1 or later), select the ArduinoISP sketch from the examples file (see image below) and upload this to your Arduino like you would any other sketch.

How to find the ArduinoISP sketch

Now disconnect your Uno from the USB port (thereby disconnecting power) and wire the following connections:
  • Arduino pin 10 to Standalone Pin 1 [Reset]
  • Arduino pin 11 to Standalone Pin 17
  • Arduino pin 12 to Standalone Pin 18
  • Arduino pin 13 to Standalone Pin 19
Make sure you also supply power to the breadboard by connecting the 5V and Gnd pins on the Arduino board to the breadboard power supply rails.  The final circuit is the same as the one on the ArduinoISP page (i.e. using an external circuit); image here: http://arduino.cc/en/uploads/Tutorial/BreadboardAVR.png

If your arduino auto-resets when a serial connection is established (e.g. when you load a new program), you will need to disable it.  There is a page describing this, but for my Uno, the simplest solution was to put a 22 uF capacitor between the reset and Gnd pins.  Others have reported success with other capacitor values; the most common value I have seen is 10 uF.

Your Arduino is now ready to act as a programmer for the standalone ATmega chip.  Plug it back into the USB port.  Load the sketch you want to program the standalone ATmega chip with into the Arduino IDE (I recommend "blink" while you are trying this out for the first time).  Set the IDE to use the programmer "Arduino as ISP" as in the image below:

Configure Arduino IDE to use the connected Arduino as an ISP

Then upload the sketch using the programmer:

Upload your sketch using the connected (ArduinoISP) programmer

The Rx/Tx lines should flash for a few seconds on your Arduino board.  When it finishes, your standalone ATmega should be programmed with the desired sketch.  The Arduino will continue to be programmed with the ArduinoISP sketch.

Disconnect power (the USB plug) from both circuits and remove the jumpers between the Arduino and the standalone ATmega chip.  Remove the 22 uF capacitor between the Reset/Gnd pins on your Arduino to return it back to a state where you can re-program it away from the ArduinoISP state.

Hopefully, you now know how to program an external ATmega chip by (completely reversibly!) converting your Arduino to an ISP.  Please feel free to leave comments if (a) this worked for you, (b) this didn't work for you and tell us what you're seeing, or (c) if you've noticed any mistakes in my instructions (though I have striven to eliminate errors).

Standard disclaimers and statements
I am not affiliated Arduino or any of the retailers mentioned above.  I have not accepted compensation in any form from any organization in support of this project.  Use this information at your own risk as there is always a possibility of undetected inaccuracies.  I am not responsible for any adverse effects your use of this information causes including, but not limited to, damage to hardware or humans.

26 comments:

  1. Thank you! I had been trying for two days to get this to work but was missing the critical "Upload using programmer" step.

    ReplyDelete
    Replies
    1. Great! Yeah, it seems like it should be really simple, but finding instructions was surprisingly Google-resistant. I'm glad it's working for you!

      Delete
  2. Thanks!
    Works great on my Uno R3!
    The 22uF to cancel the reset did the job also.
    Great job!

    ReplyDelete
  3. Once you've got the code uploaded onto the arduino on a breadboard (or say, perfboard, or PCB)...

    Is there a way to debug your code using a serial connection?

    That is, if you've got Serial.println("Debug stuff here"); points in your code, and you'd like to see them -- can you wire the Serial data pins in such a way that you could see that through the Arduino serial console?

    Thanks much!

    (I've tried using a tutorial for uploading a sketch using the Uno as a programmer, esp: http://arduino.cc/en/Tutorial/ArduinoToBreadboard which has you remove the ATMega328p from the Uno pcb. But, I can't quite get it to work)

    ReplyDelete
  4. thanks, this post really help

    ReplyDelete
  5. Thanks a lot for this blog, it worked at once on my uno-rev3.
    I didn't remove pin 21 to GND and I didn't use a capacitor between reset and GND but that all didn't matter.
    It worked just fine.

    ReplyDelete
    Replies
    1. Glad it worked and thanks for the report on what worked for you!

      Delete
  6. very useful, i do have Arduino UNO R3 and follow your instruction and it was successful i did load a sketch to my ATMega328-Pu, but i did not put a caps on my arduino auto-reset to disable it where you said you put 22uF capacitor between the reset and the Gnd pin since i dont have any of those caps value by that time.

    Does it make any side effect on my arduino board? coz ill be loading more sketches on that set up from time to time now.

    ReplyDelete
    Replies
    1. If it works, I don't think you have anything to worry about. The purpose of that capacitor is to prevent the reset line from being pulled low (I think) upon USB connection (as would occur when programming the standalone chip).

      Delete
  7. Wow! It worked like a champ!! Last several hours I have been looking for exactly this - loading a Sketch on standalone ATmega328P using my Arduino Uno with SMD ATmega328 which I cannot get rid of momentarily. You are very right no other tutorial seems to address this particular need. Thank you so much for your blog post, it saved me waiting for another good 15 days to get an FTDI from HongKong or China.

    Here is my hardware and settings, just in case other people benefit from the info: Arduino Uno v.2 with SMD ATmega, Arduino IDE 1.0.5, Standalone ATmega328-P, Reset to ground via a 10uF capacitor - a successful recipe!

    (Sorry about my name in exotic alphabets, it is "Sayedur" in English.

    ReplyDelete
  8. Would be nice if your tutorial showed how to do this without the crystal and capacitors. I've uploaded a bootloader without them, so it should be possible to also upload sketches without them too. Guess this isn't the tutorial I was looking for.

    ReplyDelete
    Replies
    1. For quite some time I am uploading sketches without crystal and capacitors. For this I have to bootload the Atmega328 at 8Mhz (internal). Then connect Arduino 11-13 to ATmega's 11-13, and Arduino's 10 to ATmega's reset (no resistor or capacitor needed here too). Download ArduinoISP on Arduino, afterwards select a board that runs at 8Mhz (e.g. Lilypad) and Upload using programmer.

      Delete
  9. Did anyone get an "Invalid Device Signature" when using "Upload Using Programmer", If so; how did you solve it?

    ReplyDelete
    Replies
    1. I got that error. Can you tell me how to solve it. I use a 328p-pu, arduino uno. mihirbosemj@gmail.com

      Delete
  10. Splendid! Tried this with the minimal configuration using 8MHz internal clock and breadboad.zip available from Arduinio website and it worked! Just had to choose board as "ATMega328 on a breadboard (8MHz internal clock)". Great post!

    ReplyDelete
  11. "Upload Using Programmer" was the key!!
    Thanks! :D

    ReplyDelete
  12. Thanks buddy it's working great...

    ReplyDelete
  13. Thank you so much. Youre a lifesaver

    ReplyDelete
  14. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. It was very easy and useful! It works! I don't use 22uF capacitor between the reset and the GND! I load sketches on two of my Atmega328P and it was OK!
      Thank's a lot!
      Good luck!

      Delete
  15. This comment has been removed by the author.

    ReplyDelete
  16. great!, is exactly the same what I'm looking for several days ago. Thank you very very much for sharing this information!!

    a last question: uploading a sketch in this form does not erases the bootloader?

    ReplyDelete