Arduino Nano ISP : Using a Nano as an ISP programmer
How to use a Nano as an Arduino Nano ISP: Not having an AVR programmer I wanted to program an ATMega328P for use
as a bare-board Arduino, and one convenient way is to use an
Arduino board as a an ISP: an In System Programmer.
The purpose of using an ISP programmer is to put back the bootloader,
which all Arduino boards need before you can upload a program using the Arduino IDE.
You may have bought an unprogrammed chip that needs a bootloader to
get it working with the IDE and in that case you can use the method here
to re-program the device (of course you need at least one device with
the bootloader already installed e.g. Arduino Uno or Nano).
If you don't have at least one bootloading programmed chip then you
will need to use a "real" programmer and AVRDude as the
You can choose from many different Arduino boards to program your target board (Arduino.cc
suggests ATmega, 32U4 or ATtiny - common ones are "Arduino Uno" and
"Arduino Nano" as the programming device).
The IDE probably just
changes pins in the bootloader sketch for the different boards (hinted
at in the bootloader sketch) to get the correct SPI pins the only other
signal needed is a general purpose I/O pin which is used as a reset
The ISP programming method simply uses the SPI interface to connect programmer and target by 4 signal lines:
RST - ReSeT.
MOSI (SPI) - Master Out Slave In.
MISO (SPI) - Master In Slave Out.
SCK (SPI) - Serial Clock.
Note: MOSI, MISO and SCK are the same SPI pins used in chips that use
the SPI interface in your own projects. RST is a signal from any I/O
pin (it is not the Arduino board reset signal).
These (SPI) signals are connected to the same pins on programmer (Nano) and
target (here the ATMega328P on a solderless breadboard). Notice how the
names of the signals allow direct connection between different chips
because they include the sources and target names. This is very
different to RS232 where you have to remember to cross over Rx and TX signals!
The connections are always the same for programmer and target boards.
So all you need to re-program the bootloader into an Arduino, is
another Arduino! (with a bootloader already programmed into the chip)
Step One - Program the Programmer
This sounds a bit odd, but you need to program the Arduino Nano that will
be used as the Arduino Nano ISP programmer with the ISP programming sketch. This turns
the Arduino into an ISP programmer.
Here the Nano is used as the programmer.
Select the Arduino ISP from the example programs in the IDE:
Menu > File > Examples > 11.ArduinoISP > ArduinoISP
From the Tools Menu select four options:
Board: "Arduino Nano". This is the programmer board in use.
Port : COMnn. The port your to which your Nano is attached.
Programmer : "Arduino as ISP".
They should all match the screen shot below - except for the Port number
which you can find by clicking the port entry (as shown below).
Program the sketch into the Nano.
Menu > Sketch > Upload
Step Two - Connect Programmer to Target
After programming the board to create the Arduino Nano ISP
programmer, disconnect the USB cable and make the connections to the
You have to connect all the SPI wires (see breadboard layout below)
but you don't really need to
connect the LEDs. One you might find useful is the heartbeat LED but it
is not essential. This will pulse slowly on and off, showing that the
program is active in the Nano.
In the breadboard layout below the LED connections are:
pin D7 : Yellow : Programming.
pin D8 : Red : Error.
pin D9 : Green : Heartbeat.
TIP: Don't bother with the LEDs - See the screen shots of IDE output below - you can see the programming status easily on that.
You can choose which pins will be used for MOSI, MISO and SCK
if you set PIN_MOSI, PIN_MISO and PIN_SCK to your desired pins - in the
sketch (save the sketch as a different file to allow editing) - in this
case the Ardino ISP sketch will use bit-banged SPI if these pins are
not set to the standard SPI pins.
Nano to Bare-board connections, and crystal+caps:
pin 1 (RSTn)
pin 20 (AVCC), pin 7 (VCC)
pin 22, pin 8
Cap1 to GND (22pF)
Cap2 to GND (22pF)
16 MHz Crystal
pin 9 and pin 10
Arduino Nano ISP programmer connected to
target bare-board Arduino chip:
This is the schematic for the above (10pF should be 22pF as in list above).
Warning: Fritzing makes it really difficult to change component
values (crystal capacitors) so I didn't! - also the schematic tool
is bad (single net operation). I have not tried the PCB but have
noticed it is not well regarded i.e. don't use it. Only use Fritzing for
breadboard graphics as above.
Arduino Nano ISP programmer to
bare-board Arduino chip schematic:
Step Three - Select Bootloader Type
Select the Arduino as ISP from the "Programmer:" Option:
Step Four - Burn Bootloader to Target
The next step is to program the target board (Arduino Nano ISP) with the bootloader:
Menu > Tools > Burn Bootloader
IDE Burn bootloader Output
Burn Bootloader Fail : Arduino Nano ISP
As an experiment I took out the Crystal before running the bootloader. This is the result:
This is interesting as the PIC microcontrollers do not require a crystal
to program them but they do require high voltage unlike the Arduino. It
also means that the ATmega328P will be more susceptible to bricking if
the fuses are set badly and a bad clock configuration is made. Using
information on this page that can never happen as the Arduino IDE sets
these fuses - I am talking about when you set the fuses yourself when
Burn Bootloader Success : Arduino Nano ISP
This is the result when you have successfully programmed the bootloader
(it is also the reason that you don't really need the LEDs as you can
see success or failure from the IDE status screen):
Using the Bare-Board Arduino
Using the bare-board arduino requires that you have a USB to serial
adaptor that connects to the RX and Tx pins of the Arduino chip.
Note: The signals Rx and Tx must be crossed over at the ATmega328p. So:
Adaptor-Rx connects to 328P-Tx.
Adaptor-Tx connects to 328P-Rx.
In many cases the serial interface adaptor will only have four connections:
This presents a problem as the Arduino schematic shows that the
Arduino is reset at a specific using a DTR signal from the serial
interface. Without the DTR signal the programming sequence hangs. That
is, unless you do a manual reset at the correct time - alternatively buy
a serial adaptor with the DTR signal as an output (and add the 100nF
capacitor - see schematic below).
Arduino Reset Problem
On Arduino boards another external signal starts bootloader - in fact
it resets the board - this extra signal is called DTR (or Data Terminal
Ready) - it is a separate output from the serial interface. A
bootloader is only
active for a few seconds at power up, or after a reset, after which
control is passed to the 'previously-loaded' program.
When an RS232 transmission is started the sending equipment asserts
DTR and this signal is used to perform a target
reset (so the bootloader wakes up). In the Arduino Schematic a 100nF
capacitor sits between this signal and the reset input of the ATMega328p
(which is also pulled up by a 10k resistor - see C5 in the circuit below).
This combination is used since DTR only changes state at the start
and end of a sequence of byte transmissions. The idea is that when DTR
goes low the Reset input is pulled low momentarily and then it is slowly
pulled up to 5V by the 10k pull-up (RN1D). It is a sort of cheat reset
method using the characteristics of capacitors to do the job.
The signal trace below shows the capacitor action - showing the reset
pin of the Arduino (This is 1V/div and 500us/div, the voltage between
blue horizontal lines is 4.7V - the lower blue line is 0V):
This reset system works because the reset input has a hysteresis
level of 0.1V (at 5V supply) which creates a clean signal
in the microcontroller that ignores noise on the slowly rising input.
For the reset pin VIL= 0.1VCC MAX and VIH=0.9VCC
MIN. For the above trace thresholds are 0.1*4.7 = 0.47V and
0.9*4.7=4.23V and gives an low reset signal of duration ~ 1.5ms.
In the trace below, when DTR goes high, a high voltage spike is
created with a peak value of 9.12V! The scope settings are :at 2V/div, 5ms/div, high blue
line is at 9.12V, yellow horizontal signal is at 4.7V:
Note: The reason that the ATmega328P can handle this higher voltage
is that the RESET input pin is specified for operation up to 13V,
probably for high voltage programming. You can not do this on other
The time between DTR low and DTR high depends on how long the programming takes - for the the blink sketch it is 1.9seconds.
Programming Arduino without DTR
It is possible to program the bare-board Arduino using a
4-connection-serial-adaptor but only if you use a manual reset button on
the target board. The key thing to get right is to push the reset
button at the correct time during the programming process. This does
mean you have to keep an eye on the IDE and what it is doing!
Alternatively: Remember to buy a serial to USB adaptor that has a
breakout pin with the DTR signal available - add the 100nF capacitor
between DTR and the reset pin, and the 10k pull-up from the reset pin to
5V, and it's ready to go.
Here is the setup for a 4-connector USB to serial adaptor connected to the bare-board Arduino:
Note: Pin 2 of the ATmega328p is Rx, and pin 3 is Tx.
Bare Board Programming Failure
If you don't push the reset button at all then you will get this IDE status message:
If you push-and-release the button too soon the compiler will be still compiling and programming will fail.
If you push-and-release the button too late you will get a programming failure message.
Bare Board Programming Success
However if you push and release the button just after the "Uploading" text appears in the IDE then you get the following:
Simple Bare Board Blink Sketch
You can try out the following sketch on the bare-board Arduino
(attach an LED via 1k resistor to D13 and to ground - pin 19 of the
// Simple slow-fast blink on built in LED Arduino D13.
digitalWrite(LED_BUILTIN,HIGH);// Turn the LED on.
digitalWrite(LED_BUILTIN,LOW);// Turn the LED off.
digitalWrite(LED_BUILTIN,HIGH);// Turn the LED on.
digitalWrite(LED_BUILTIN,LOW);// Turn the LED off.