Introduction: Programming the ATTiny85, ATTiny84 and ATMega328P : Arduino As ISP


I've recently been developing a few ESP8266 based IoT projects and found the core processor was struggling to carry out all the tasks I needed it to manage, so I decided to distribute some of the less important activities to a different microcontroller(s) in this way freeing up the ESP8266 to get on with its job of being an IoT device.

Given I wanted to publish my project to as wide an audience as possible I opted to use the Arduino IDE as the development platform of choice since it has such a widely supported community.

Design Constraints

In order to provision a reasonable spread of target devices allowing for the selection of an appropriate microcontroller for the application at hand, I settled on the following Atmel parts; ATMega328P, ATTiny84 and ATTiny85. To limit the complexity of the necessary programmer I constrained the choice of clock to internal for all devices and 16MHz external for only the ATMega328P and ATTiny84.

What follows is a collection of notes on programming with the Arduino and a description of how I put together a simple Arduino Uno based programmer for these devices (Pics above).


What parts do I need?

To build the programmer you will require the following parts

  1. 1 off Arduino Uno
  2. 2 off 28 pin Zero Insertion Force (ZIF) DIP sockets (to hold ATMega328P, ATTiny85, ATTiny84)
  3. 1 off Arduino prototype shield (I got mine here;
  4. 2 off 5MM LEDs
  5. 2 off 1K resistors
  6. 1 off 10K resistor
  7. 4 off 22pF Ceramic capacitors
  8. 2 off 16MHz crystals
  9. 3 off 0.1uF ceramic capacitors
  10. 1 off 47uF Electrolytic Capacitor
  11. 1 off 10uF Electrolytic Capacitor
  12. Various lengths wire wrap wire.


What software do I need?

Arduino IDE 1.6.9


What skills do I need?

  1. Knowledge of Arduino IDE
  2. Some knowledge of electronics and how to solder
  3. A great deal of manual dexterity
  4. A load of patience and good eyesight


Topics covered

          1. General Introduction to programming Atmel Microcontrollers
          2. ISP or Bootloader : It's all a bit confusing
          3. Circuit overview
          4. Setting up your programmer
          5. Using your Arduino ISP Programmer
          6. Developing code on your target system
          7. Gotchas
          8. Conclusion
          9. References used



          As always, you use these instructions at your own risk and they come unsupported.

          Step 1: General Introduction on Programming Atmel Microcontrollers

          There are two methods available for programming Atmel microcontrollers;

          1. In System Programming (ISP),
          2. Self Programming (via a bootloader).

          The former method (1) directly programmes the microcontroller via the SPI interface after first putting the device into reset. Unless instructed otherwise a compiled executable source programme is written to the device incrementally into code memory from where it is executed at start up. There are many ISP devices capable of programming Atmel devices, a few of which being (pic 1); AVRISPmkII, Atmel-ICE, Olimex AVR-ISP-MK2, Olimex AVR-ISP500. Picture 2 shows how the ISP device connects to the ATMega328P (oddly marked ICSP) on the Arduino Uno R3 board (pic 3 gives the ISP pin out). It it also possible to programme an Atmel microcontroller via it's SPI interface using an Arduino Uno as ISP (picture 4), here the Uno is being used to programme an ATMega328P.

          The latter method (2) uses a small code stub known as a 'bootloader' permanently resident in executable code memory (usually locked to prevent accidental overwriting pic 5). This code is executed first thing upon power up or device reset and allows the microcontroller to re-programme itself with new code received via one of its interfaces from a source external to itself. The bootloader method is used by the Arduino IDE to re-programme Arduinos mapped as a USB comm port on the PC (Or MAC, Linux box etc., pic 6) and in the case of the Arduino Uno communicates with the Atmel device via it's serial interface on IC Pins 2 and 3 of the ATMega328P. Also the Arduino Uno (with the ATMega328P micrcontroller removed) can be used to programme an ATMega328P via the bootloader method effectively acting as a USB to serial adapter device (pic 7).

          What is a USB to serial adapter?

          A USB to serial adapter is a piece of hardware which plugs into your PCs USB port and looks like a serial com port (a legacy from earlier times when computers used a serial communications standard known as EIA-232, V24 or RS232) allowing you to send and receive serial data at the same electrical levels of the microcontroller. When you Select Tools -> Port -> COMx from the Arduino IDE you are connecting/interfacing your PC to your Arduino.

          A device like this is sometimes referred to as an FTDI (pic 8, which is actually a brand name) or CH340G etc. USB to serial on the Arduino uno is achieved via an ATMega16U2-MU(R) IC ZU4 as in the Arduino Schematic below.


          For clarity picture 9 identifies the two Atmel devices and their respective ISP connectors on the Arduino Uno R3.


          Note 1 : If you choose to go down the FTDI device route ensure you purchase from a reputable seller as there have been a lot of cheap counterfeit devices on the market which have failed upon application of a windows update.

          Check out the Dave Jones EEVblog rant 'EEVblog #676 - RANT: FTDI Bricking Counterfeit Chips' below;

          Note 2: It is also advisable to place a 'sacrificial' USB hub between your PC and the target device just in case you short something out (better still use an isolation USB device.). You will thank me for this advice.

          Note 3 : Unless otherwise stated for 'ATMega328P' read 'ATMega328P-PU'

          Step 2: ISP or Bootloader : It's All a Bit Confusing

          So how come there are so many ways to programme the Arduino?

          Ok, so by now you are probably wondering why there are so many different ways to programme an Arduino. Well I suspect for Massimo Banzi it was about flexibility/extensibility and reducing the entry point to get as big a following as possible.

          Or to quote the Arduino Introduction;

          • Inexpensive,
          • Cross-platform,
          • Simple, clear programming environment,
          • Open source and extensible software,
          • Open source and extensible hardware.

          Put simply, if you only want to go as far as programming the native Arduino (Uno, Due, Nano, MEGA etc.) you only require a little knowledge of programming, a computer and USB lead which will allow you to create many different projects and truly be a part of the maker community.

          Alternatively if you want to take the next step and embed an Arduino device or you break your Arduino board microcontroller and it's not an SMT part all you need is a little knowledge of programming, electronics and an Arduino Uno and you can re-programme a replacement or alternatively programme a very wide range of Atmel devices, opening up far more opportunities to create outstanding projects.

          And all of this without the need for expensive electronics kit.

          However, if you are a serious embedded systems developer you will use 'Atmel Studio' and an ISP/JTAG as this will allow you to directly set device configuration fuses, debug your code on the microcontroller along with register interrogation, stack traces and breakpoints etc. none of which are available with the Arduino IDE.

          So why choose ISP or Bootloading?

          Ok, so assuming you are reading this Instructable because you are at the point where you want to embed an ATMEL device programmed via the Arduino IDE, how would you make this choice?

          To be honest, in reality there's not much between them.

          If you use the ISP method you will save yourself the memory space the bootloader occupies and the start up/reset time will be quicker as the Arduino/ATMEL device will execute your code 'right out of the blocks' and not pause looking for serial data from the PC to upload.

          Depending on what circuit you are going to embed your design into you could also use either method, though you may need more than a passing knowledge of electronics to competently achieve this. In the case where microcontroller I/O count is an issue and start up speed/code space are not a major consideration, you may choose to use the bootloader as this method only uses three pins (less the Clock line) one fewer that the ISP method.

          It also depends upon what development paradigm you adopt;

          • Write your code, download to ATMEL device with programmer, move ATMEL device to target system for testing,


          • Directly develop with ATMEL device in target system for testing.

          Here the latter is a better development method and is faster (you also don't run the risk of getting an IC pin stuck in your 'finger') but requires a good knowledge of electronics.

          My general preference where performance isn't an issue is to burn the bootloader and use a serial programmer with the ATMEL device in the target system and develop code with the Arduino IDE.

          Now here's where it may get a little more confusing...

          • For Bootloading

          Bear in mind, if you want to programme a 'factory fresh' Atmel microcontroller via a bootloader you will first need to programme the bootloader code on to the device using the ISP method. Though you can purchase ATMega328P microcontrollers with the bootloader already programmed, however, they will cost more.

          • For ISP

          If you want to use the ISP method you should always programme your Arduino with the bootloader at least once. This is to ensure you set the specific device configuration fuses for that microcontroller. This instruction is slightly misleading given for the ATTiny85/84 burning the bootloader in fact only sets device configuration fuses.


          Consequently this Instructable details how to programme an Atmel device using the ISP method as this gives the most flexibility for developing code for a given microcontroller.


          By way of example I have included circuits for the ATMega328P depicting ISP and Serial programming configurations for both 16MHz external and 8MHz internal clocks (pics 1 and 2 above).

          Step 3: Circuit Overview

          The circuit design above (pic 1) details the necessary system level connections to programme either the ATMega328P, ATTiny84 or ATTiny85 via the SPI interface as an ISP programmer (Arduino As ISP with 'ArduinoISP' code loaded on the Arduino Uno connected to the prototype shield).

          Although it may not be obvious from the diagram, all circuitry can be placed on the Arduino Shield Prototyping board such that no modifications to the Arduino Uno are necessary meaning it can be re-purposed if required.

          The heart of the circuit is the Arduino Uno R3 which when programmed with the Built In Examples sketch : ArduinoISP will generate the source signals with which to program the target devices.

          LED_P (LED2) or programming LED will flash during the programme cycle of any chip.

          LED (LED1) is connected to Arduino programmatic Digital Pin3 and can be used to test your device with the modified blink programme 'ATTiny84-85-ATMega328_Blink.ino'. Digital Pin3 was specifically chosen as it will work interchangeably with all three devices; ATTiny84, ATTiny85 & ATMega328, giving a good indication your set up is working correctly.

          Note 1 : C6 10uF Electrolytic Capacitor must be placed near to the Arduino Reset pin where it enters the prototyping Shield. Without this capacitor the programming device will not work. This is because the Arduino IDE asserts the DTR line prior to programming the Arduino which engages the bootloader. (See PDF file below, specifically Pin 13 U3). By including this capacitor the programming Arduino Uno does not reset, executing it's code which forwards the compilation download from the Arduino IDE to the target device.

          Note 2 : Ensure you use the stackable Arduino headers (F/M on top, M on the bottom) as they can come in useful if you accidentally programme any device with the wrong clock source.

          Note 3 : Only 'ONE' Atmel device can be programmed at any one time.

          Pictures 2 ... 4 show the various build states during construction of the programmer.

          Pictures 5 ... 7 show how to wire up the ATMega328P, ATTiny84 and ATTiny85 for programming via SPI with breadboard.


          Step 4: Setting Up Your Programmer

          There are two parts to establishing your Arduino ISP Programmer, these are as follows;

          1. Preparing your Arduino Uno (Target Device Programmer, pic 1 above)
          2. Preparing your Arduino IDE (Control PC, pic 1 above)

          Preparing your Arduino Uno

          This is a relatively simple procedure and is as follows;

          1. Ensure you have Arduino IDE 1.6.9 installed,
          2. Ensure you do not have the ISP programming prototype shield plugged onto your Arduino Uno R3 (if you do you will not be able to programme it as the 10uF capacitor C6 will prevent the Arduino IDE from resetting the ATMega328P),
          3. Ensure your Arduino Uno R3 is connected to your PC (sorry MAC users) via USB,
          4. Run up Arduino IDE and connect to your Arduino Uno R3,
          5. From File->Examples->11.ArduinoISP->ArduinoISP, open the ArduinoISP sketch,
          6. Programme your Arduino Uno R3,
          7. Once complete, plug your ISP programming prototype shield onto the Arduino Uno R3 as in pic 2 above.

          Preparing your Arduino IDE

          This is also a two part process, 'out of the box' the Arduino IDE will allow you to programme the ATMega328P as this is the microcontroller on the Arduino Uno R3, however as a default it is assumed a 16MHz external clock is used.

          Hence part one will be to add the capability to programme this device to use the internal 8MHz clock and part two to add ATTiny functionality.

          Part 1 : Adding ATMega328P 8MHz Internal clock capability to the Arduino IDE

          1. Go here;
          2. Download '', and unzip.
          3. Drop everything in 'breadboard' directory into your hardware directory (see pic 3 above).
          4. Mine is here; C:\Program Files (x86)\Arduino\hardware
          5. Restart Arduino IDE.
          6. New boards selection will appear; 'ATmega328 on a breadboard (8 MHz internal clock)'
            • Tools->Board->ATmega328 on a breadboard (8MHz internal clock). See pic 4 above

          Part 2 : Adding ATTiny capability to the Arduino IDE

          I did some 'shopping around' and found the best ATTiny Core which suited my purposes was the ATTiny Core by Spence Konde (aka Dr. Azzy). It can be found here.

          Full installation instructions for which are here, or as follows;

          Via Board Manager Installation.

          1. Select; File -> Preferences,
          2. Choose 'settings' tab
          3. Enter the URL below in "Additional Boards Manager URLs" (see pic 5 above)
          4. Now Select Tools -> Boards -> Board Manager...
          5. Locate ATtinyCore and click "Install" (see pic 6 above)
          6. You should now have ATTiny Boards available (see pic 7 above)


          OK, so what have I got now?

          Once you have completed the above using your Arduino IDE you will be able to programme the following (see pic 8);

          • ATMega328P
            • Internal 8MHz Clock
            • External 16MHz Clock
          • ATTiny85
            • Internal 1MHz Clock
            • Internal 8MHz Clock
          • ATTiny84
            • Internal 1MHz Clock
            • Internal 8MHz Clock
            • External 16MHz Clock


          Note : If the new boards manager entries are not available the in 'Boards Manager' you may need to restart the Arduino IDE. See here for boards manager bug.

          Step 5: Using Your Arduino ISP Programmer

          If you have followed all the above steps then you are now ready to programme your target device with your new Arduino ISP Programmer.

          If you remember in step 2, I mentioned that if you have a factory fresh ATMEL device you will need to download the bootloader at least once such that you set the device fuses, the description which follows will show you how to do this along with how to download your code directly via SPI.

          In the case of the ATMega328P programming the bootloader with your Arduino ISP Programmer will allow you to actually bootload code, whereas for the ATTiny85 and ATtiny84 it just results in setting the micrcontroller fuses.

          For the ATMega328P

          Initial set up

          • Select Tools->Programmer->Arduino As ISP (see pic 1 above)

          Bootloader Download

          • Assuming 8MHz internal clock is to be used;
            • Select Tools->Board->ATmega328 on a breadboard (8 MHz internal clock) (see pic 2 above)
            • Select Tools->Burn Bootloader (see pic 3 above)
          • Assuming 16MHz external clock is to be used;
            • Select Tools->Board->Arduino/Genuino Uno (see pic 2 above)
            • Select Tools->Burn Bootloader (see pic 3 above)

          ISP Code Download

          • Assuming 8MHz internal clock is to be used;
            • Select Tools->Board->ATmega328 on a breadboard (8 MHz internal clock) (see pic 2 above)
            • Select Sketch->Upload Using Programmer (see pic 4 above)
          • Assuming 16MHz external clock is to be used;
            • Select Tool->Board->Arduino/Genuino Uno (see pic 2 above)
            • Select Sketch->Upload Using Programmer. (see pic 4 above)


          For the ATTiny85

          Initial set up

          • Select Tools->Programmer->Arduino As ISP (see pic 1 above)
          • Select Tools->Board->ATtiny25/45/85 (see pic 5 above)
          • Select Tools->Chip->ATtiny85

          Bootloader Download (This action just sets the microcontroller fuses)

          • Assuming 1MHz internal clock is to be used;
            • Select Tools->Clock->1 MHz (internal) (see pic 6 above)
            • Select Tools->Burn Bootloader (see pic 3 above)
          • Assuming 8MHz internal clock is to be used;
            • Select Tools->Clock->8MHz (internal) (see pic 6 above)
            • Select Tools->Burn Bootloader (see pic 3 above)

          ISP Code Download

          • Assuming 1MHz internal clock is to be used;
            • Select Tools->Clock->1MHz (internal) (see pic 6 above)
            • Select Sketch->Upload Using Programmer (or Upload) (see pic 4 above)
          • Assuming 8MHz internal clock is to be used;
            • Select Tools->Clock->8MHz (internal) (see pic 6 above)
            • Select Sketch->Upload Using Programmer (or Upload) (see pic 4 above)


          For the ATTiny84

          Initial set up

          • Select Tools->Programmer->Arduino As ISP (see pic 1 above)
          • Select Tools->Board->ATtiny24/44/84 (see pic 7 above)
          • Select Tools->Chip->ATtiny84
          • Select Tools->Pin Mapping->Counter Clockwise (like ATTiny Core)

          Bootloader Download (This action just sets the micrcontroller fuses)

          • Assuming 1MHz internal clock is to be used;
            • Select Tools->Clock->1 MHz (internal) (see pic 8 above)
            • Select Tools->Burn Bootloader (see pic 3 above)
          • Assuming 8MHz internal clock is to be used;
            • Select Tools->Clock->8MHz (internal) (see pic 8 above)
            • Select Tools->Burn Bootloader (see pic 3 above)
          • Assuming 16MHz external clock is to be used;
            • Select Tools->Clock->16MHz (external) (see pic 8 above)
            • Select Tools->Burn Bootloader (see pic 3 above)

          ISP Code Download

          • Assuming 1MHz internal clock is to be used;
            • Select Tools->Clock->1MHz (internal) (see pic 8 above)
            • Select Sketch->Upload Using Programmer (or Upload) (see pic 4 above)
          • Assuming 8MHz internal clock is to be used;
            • Select Tools->Clock->8MHz (internal) (see pic 8 above)
            • Select Sketch->Upload Using Programmer (or Upload) (see pic 4 above)
          • Assuming 16MHz external clock is to be used;
            • Select Tools->Clock->16MHz (external) (see pic 8 above)
            • Select Sketch->Upload Using Programmer (or Upload) (see pic 4 above).


          Can I test what I've just done?

          Yes, using your ISP programming prototype shield just insert a microcontroller of choice; ATMega328P, ATtiny85 or ATtiny84 and download the code contained in 'ATTiny84-85-ATMega328_Blink.ino' below. If you are successful, led 1 (Red Led in my build) will flash once a second.


          Note : The 'ATTiny84-85-ATMega328_Blink.ino' blink programme below, assumes Tools->Pin Mapping->Counter Clockwise (like ATTinyCore) for ATTiny84 programming.

          Step 6: Developing Code on Your Target System

          As I mentioned in step 2 there are two ways to develop your code on an ATMEL device, namely;

          1. In System Programming (ISP),
          2. Self Programming (via a bootloader).

          If you follow these instructions you will be able to use both methods for the ATMega328P running either an internal 8MHz clock (remove C1, C2 and Q1) or 16MHz external clock. If you are a novice developer I would recommend using a bootloader as it will work the same as your Arduino if you connect it as in picture 1 above. However, for the ATTiny85 and ATTiny84 only the ISP method is available.

          Consequently if using the ISP methodology you would typically;

          1. Develop your code using the Arduino IDE,
          2. Programme and download to the ATMEL device,
          3. Remove device from programmer,
          4. Insert in target platform,
          5. Power up and run code,
          6. Test for functional correctness.
          7. Repeat steps 1...6 until code is working correctly.

          For completeness I included pictures of the Arduino pin equivalencies when you programme a given device (pics 2 ... 4).


          Note 1 : Actually there is a common third technique known as cross platform development not covered here. Here is an example Instructable where I use this approach.

          Note 2 : When programming with the bootloader/Serial adaptor(FTDI) configuration select the following;

          • Tools->Board-> Either 'Arduino/Genuino Uno' or 'ATmega328 on a breadboard (8MHz internal clock)'
          • Tools->Programmer->AVRISP mkII
          • Sketch->Upload

          Step 7: Gotchas

          Here are some typical gotchas I came across when using this programming/development method.

          1. The wrong I/O is changing for ATTiny84.
            • Have you selected the correct Pin mapping (Tools->Pin Mapping) when you programmed the device?
          2. You're using an FTDI device and it stops working.
            • You may have a fake FTDI device which has been bricked by a windows update. See Dave Jones EEVblog rant 'EEVblog #676 - RANT: FTDI Bricking Counterfeit Chips' here
          3. You're getting odd timing delays, or no activity at all, you can download via SPI but in the case of the ATMega328P bootloading won't work.
            • Have you burnt the bootloader at least once?
          4. You inadvertently selected the wrong clock source prior to uploading and now you can't burn code via SPI or bootloader.
            • If for instance you selected the 16MHz external clock on the ATTiny85 all you need to do is wire a clock source to your device and re-programme. As I did in pics 1 and 2. This is where Step 3, Note 2 comes in handy.
          5. You purchased your factory fresh ATMega328P microcontrollers, when you try to programme them you get a device signature error something along the lines above (pic 3).
            • Ok, this is a little more tricky to solve, depending upon the ATMEL part you have actually purchased, during compilation an unexpected signature byte has been detected.
            • For example you may have actually purchased some ATMega328s and not ATMega328Ps, the signature for the ATMega328 is 1E 95 14, and the ATMega328P is 1E 95 0F (ok so pic 3 is not a brilliant example, but it's along the right lines)
            • To resolve this locate the 'avrdude.conf' file. Mine was located here; C:\Program Files (x86)\Arduino\hardware\tools\avr\etc
            • Search the file and find the signature for the 'ATmega328p' which is : signature = 0x1e 0x95 0x0F;
            • Change 0x0F to 0x14 and save.
            • You should be able to programme the device now.
            • Don't forget to change the signature back to the way it was when you're done.
            • I've included in the references a link and section details for Atmel Microcontroller Signature Bytes for the ATMega328P, ATTiny85 and ATTiny84.
          6. You just added the ATTiny core and you can't find the newly added boards
            • This may be the 'Open twice boards manager bug' see here.

          Step 8: Conclusion

          I've been using this programming device reliably for some time now without any issues, given the initial design contrants the end result fit the bill very well. My only wish would be to have been able to use a bootloader for the ATTiny85/84 as this would have made things a lot easier during the code debug phase.


          On a personal note I learned a great deal about the Arduino and it's community given I needed to wade through 'tonnes of guff' to get to the truth about programming the various devices in all their glory (you can see evidence of this by the sheer number of links in the reference section and I only just 'scratched the surface').

          In completing my research I was totally flabbergasted at how well the various git hub forums are supported, kudos to Spence Konde that is one dedicated guy.

          Also the degree of foresight the Arduino creators must have had to come up with such a flexible all encompassing design is truly impressive.



          A word of advice. Watch out for cheap Chinese knock off parts. When purchasing the 28 Way ZIF DIP sockets I thought I was getting a great deal on some 'TEX TOOL' parts.

          At least that's what they looked like from the EBAY listing, actually being titled as such.

          "4pack 28pin ZIF socket for DIL ICs Textool 0.3" Zero Insertion Force narrow DIP"

          However, once I took delivery it was then I found out they were in fact 'TFX TDOL' clearly a choice of text remarkably similar to 'TEX TOOL' along with the green molding (check out the pic above).

          What was it UK trading standards say... 'If it sounds too good to be true, it usually is.'

          If only I had listened, then maybe the locking lever would be still working after more than 10 uses.

          Step 9: References Used

          What is Arduino?

          Excellent source for bootloading the ATTiny85

          Atmel Microcontroller Signature Bytes

          Arduino Uno R3 cct

          ISP source

          Atmel AVR

          ATTiny Core - 1634, x313, x4, x41, x5, x61, x7, x8 and 828 for Arduino 1.6.x, by Spence Konde, aka Dr. Azzy

          High-Low tech ATTiny Core

          Arduino Playground - ArduinoOnOtherAtmelChips : Unofficial listing of support for other Atmel chips in Arduino IDE

          Using an Arduino as an AVR ISP (In-System Programmer)

          Using an Arduino as an FTDI for bootloading

          Open twice boards manager bug

          Arduino bootloader details

          Wikipedia reference to Arduino

          Programming the bootloader at least once to programme the fuses

          Arduino prototyping shield

          USB to serial

          Programming ATMega328P with Arduino Uno using internal clock

          Arduino Uno Standalone

          EEVblog #676 - RANT: FTDI Bricking Counterfeit Chips!

          Building an Arduino on a Breadboard

          How to burn 1Mhz & 8Mhz bootloader using Arduino IDE 1.6.5-r5

          EIA-232, V24, RS232

          Arduino Products

          Atmel Studio


          Microcontroller Contest 2017

          Participated in the
          Microcontroller Contest 2017