Chapter 9: Using an Arduino Uno as an ISP...

This part of the tutorial will concentrate on the ATmega328P & ATmega328-P devices but, what is discussed here will apply to other AVRs.

If everything in the world was fair, every Atmega328P or -P you bought would be exactly as it was when it left the factory but this isn't always the case. Some sellers tinker with the devices and put bootloaders on them before they sell them, others, for reasons best known to themselves, sell devices with bootloaders already installed but don't tell you. One thing you can rely on is that most of the time sellers don't say what has been done to the devices unless you buy from a source that only sells "virgin" devices.

A friend of mine a while back bought a job lot of Atmega328P-PU devices for a pittance from a far East seller on eBay and was dismayed when they wouldn't program with his AVRISP MKII. He came to me for help as I've been working with microprocessors since the mid 1970s and it was obvious that the on-board oscillator wasn't running. I removed his 16MHz crystal and injected a 1MHz clock signal from my stand-alone clock generator and hey-presto, we were able to program the chips. I believe that what he bought were devices that had failed during commercial programming and it was cheaper for the seller to pass them on rather than spend time rectifying the problem. This episode is what prompted me to include a clock generator in the modified ArduinoISP sketch discussed later.

 To use an Arduino board (we're using the Uno R3) as an ISP is very simple as you obviously already have a board which is programmable and can be made to do the job. Arduino provide a sketch called "ArduinoISP" which you will find on the "File/Examples" menu. This sketch performs all the functions of an ISP but, it can be improved upon and I have done so.

From now on I will refer to the "rduinoISP_Multi" sketch, not because you can't use the original "ArduinoISP" sketch but because the updated sketch offers 2 more features as follows:

  1. The "ArduinoISP_Multi" sketch will allow the programming of both types of ATmega328 devices, ATmega328P and ATmega328-PU (see here for the different devices)
  2. An 8MHz clock is provided for devices that are either bricked or won't respond to normal methods of programming

Remember, you do NOT have to have a crystal and capacitors to provide a clock for your device. You can use the device's internal clock and save space and money, In most cases, you can also use the device pins that were previously connected to the crystal as I/O pins.

Let me give an example of point "2". You could have an AVR that has been around for a while and you have forgotten what clock source it was programmed to use. By supplying a clock signal you don't have to worry as it is likely that the device will be recovered and programmed. You could have a failed programming attempt which has left the device in an unknown state, again using a clock source can recover the situation.

Point "1" is very important to some users as the ATmega328P and the ATmega328-P devices are not the same as explained in the above link. AVRDUDE, in its current form, does not recognise the ATmega328-P devices despite them becoming more widely available and being cheaper.

To turn the Arduino Uno into an ISP you simply have to upload the "ArduinoISP_Multi" sketch to the board, put the target device on a breadboard, make a few connections to the target device using jumper wires and away we go.

The only decision we are left with is do we need a bootloader? It's up to you as you can program the sketches straight on to the device or add a stand-alone USART and use a Serial Port to upload sketches to the device in the same way that you do with your Arduino board. It's your call.UNO with Programming Shield

An alternative to the breadboard method of programming AVR devices is to use a programming shield as shown on the left.

Shields, such as this one from BoardStuff provide and easy way to program ATmega328s and a range of ATtiny AVRs without all the hassle of jumper wires and breadboards.

All the signal connections are taken care of and there are links to control power, 8MHz clock and RESET override for pre-R3 UNO boards which can reset themselves during programming.

Most shields also provide an ICSP header for In Circuit programming of AVRs which means that you can build your project and program the AVR without having to keep removing it and re-inserting it after programming.

If you still want to use a breadboard for programming, here's how to wire up your Arduino to your target device (ATmega328-PU in this example). The circuit is quite simple and can be made up with a breadboard and a few jumper wires.

Please note: If you use my "ArduinoISP_Multi" sketch, this method will program both the ATmega328P and the ATmega328-PU without any other modifications or files. The "ArduinoISP_Multi" sketch takes care of the "Invalid signature" error when programming ATmega328-PU devices.

ArduinoISP Circuit
Arduino ISP_8MHz  pins and function
Arduino Pin Atmega328x Pin Function
13 19 SCK
12 18 MISO
11 17 MOSI
10 1 RESET
9 9 8MHz Clock
8 NA Error LED (Red)
7 NA Program LED (Yellow)
6 NA Heartbeat LED (Green)
5V 7 5V
GND 8 0

An example circuit for programming an ATmega328 using the ArduinoISP and the pins and signals used.

The "Optional" 10uF electrolytic capacitor is shown as it has been reported by others that the Arduino board can "reset" itself during programming. This problem does not affect all Arduino boards and I have never seen it myself using an Arduino Uno R3. If you see your Arduino board performing a "reset" at the start of programming, simply upload the ArduinoISP_Multi sketch to your board and attach the capacitor (watch the polarity). When you are finished, remove the capacitor as its sole purpose is to prevent a "reset" event on the board and with it in place you won't be able to upload sketches.

The dotted line on the diagram is the 8MHz clock signal which is provided to do away with the need to put a crystal and capacitors on the target device. The clock signal can be attached to the "XTAL1" input pin of any device. Despite being a fixed 8MHz clock signal, the target device speed is independent of the input frequency and will work at the speed set by the fuses when it is in its final location. Regardless of whether you set the fuses to 16MHz crystal operation or 1MHz internal oscillator operation, the 8MHz clock signal will do the job.

The LEDs on pins 6 - 8 are optional but useful as an indicator that things are working correctly. The colours are only suggestions. Connect the LEDs with a 1K series resistor to the Arduino board outputs shown.

The observant among you will notice that I do not have the 8MHz clock signal attached to my breadboard example and this is simply because I know the state of the device. It is clearly labeled "AT328 8MHZ INT" which means "ATmega328-PU" with "8MHz Internal clock".

ATmega328 devices are supposed to be shipped by ATmel with the internal 8MHz oscillator enabled and the "Divide by 8" fuse set giving an operational clock speed of 1MHz which is sufficient to start programming the device. Unfortunately, I find that quite a few "new" devices don't respond to programming the first time but, the 8MHz clock signal always gets over this problem.

You MUST use the "Burn Bootloader" tool to change the fuses on the device and it's up to you whether you include a bootloader or not. Both "Burn Bootloader" and "Upload Using Programmer" will overwrite the bootloader if you used one so be careful how you use these tools.

Don't be tempted to use bootloaders that have not been written for the device as this can cause the "Serial Upload" feature to fail due to incorrect internal timing which is based on the system clock. For example, if you change the fuses to make the device work at 8MHz and then use a bootloader written for 16MHz operation things will probably not work the way you think they will.