Projects

Programming The ATtiny85

It Packs A Punch!

Tim Blythman

Issue 9, March 2018

The ATtiny85 IC is one of the smallest microcontrollers you can get (it’s not the smallest Atmel microcontroller – the ATtiny10 has only six pins!), which makes it ideal for those applications where space is at a premium.

BUILD TIME: 1 hour
DIFFICULTY RATING: intermediate

If you thought building the Arduino PIC Programmer from last month looked too hard, but you still want to see what eight-pin microcontrollers offer, then you’re going to love taking a peek at the ATtiny85. Not only does our programmer run on an Arduino, but you can actually program the ATtiny85 using the Arduino language and IDE. As a bonus, the programmer can be built to work with the popular ATmega328P, as found in Arduino Uno boards.

But how do you program and use something so small? It obviously doesn’t have a USB interface like our beloved Uno, nor socket headers to connect jumper leads to. Like our PIC programmer, we want to be able to plug our microcontroller in, program it, and then deploy it in our application circuit. This programmer does this, providing ISP (In System Programming) programming signals to a ZIF (Zero Insertion Force) socket. We’ve also added some components to the programming circuit so that you can do some basic testing without removing the microcontroller from the circuit, and also a ZIF socket for an ATMega328, as this microcontroller is also commonly available in an easy-to-use DIP package.

THE BROAD OVERVIEW

Compared to the Arduino PIC Programmer (or any other PIC programmer), which needs a 13V source to force the target microcontroller into programming mode, programming Atmel microcontrollers generally only needs logic level signals, which can be easily achieved from another Atmel microcontroller such as an Arduino Uno. There are high voltage programming modes for Atmel microcontrollers (where high voltage refers to more than 5V), but they are not needed in most cases, including an ATtiny85.

The programming method we will use is called ISP. This is effectively an SPI interface with the microcontroller’s RESET pin used as SPI Slave Select, so it is fairly easy to implement on a microcontroller that supports SPI. The Arduino community has created a sketch called ArduinoISP, which allows an Arduino board to behave as an in-system programmer, sending data via the USB serial port of the host Arduino board. So as you can see, the software side of our ATtiny85 Programmer is quite straightforward.

The hardware side is all about making the connections to the right pins. We’ll firstly look at how these connections can be made on a breadboard, in case you just want to see how it works. Then we’ll build an Arduino shield that has a programming socket, so if you need to work with something a bit more permanent you can.

We’ll also have a look at how you can program the ATtiny85 using the Arduino IDE. As you can imagine, a tiny eight-pin DIP package isn’t going to replace your Uno board, so we’ll also take a look at the limitations of this microcontroller.

HOW IT WORKS

Unlike an Arduino Uno, an ATtiny85 does not normally have a bootloader (see latter in this project for ways to install a bootloader on the ATtiny85). This is a small program that sits in the flash memory, and is what actually runs when you first power it up. You might notice that the onboard LED on an Uno blinks a few times, no matter what sketch is loaded – this is the bootloader letting you know it is there. The bootloader listens in the first second of power-up, searching for a certain sequence of data on the serial port, and if it is detected it goes into sketch upload mode. Without this handy piece of code, we need another way of putting our program onto the chip, and as noted earlier, we can use ISP. Another advantage of not using a bootloader is that the bootloader takes up precious flash program space, and with a small microcontroller like the ATtiny85 – which has just 8kB of flash – anything saved will help.

To do a basic test of ISP programming an ATtiny85 with an Uno, you will need an Uno main board, an ATtiny85 IC, a breadboard and some jumper leads. An IC socket can help too.

The first step is to configure the Arduino IDE to work with the ATtiny85, as this is not included by default. The following assumes you are using at least version 1.6.4, as this is when the Boards Manager was introduced. Open the Preferences window from File>Preferences and if there are existing entries, add a comma at the end, then add: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json

Preferences

Then go to Tools>Board>Boards Manager, search for “attiny” and install the option that looks like this:

Boards Manager

After this, the Tools>Board menu should give you a few ATtiny options.

Board Menu

Note that there are a few sub-menu options, so make sure (when working with the ATtiny85) that the options selected are “ATtiny85” and “internal 8MHz oscillator”. Be careful not to choose an external oscillator mode, as this might cause the ATtiny85 to appear “bricked”, as it will be expecting an external clock source, which probably isn’t connected.

Before building, open the ArduinoISP sketch from File>Examples>11.ArduinoISP>ArduinoISP, and upload it to the Uno (remembering to select Uno again for now), then connect everything up as shown, noting that pin 1 on the ATtiny85 is the top left corner with the notch to the right. If you aren’t familiar with IC pin numbering, the numbers increase anti-clockwise from pin 1.

The connections are as follows:

UNO PINATTINY85 PIN
5V8
GND4
D101
D115
D126
D137

There is also an extra wire on the Uno, going from RESET to the top right pin on the ISP header – this holds the RESET pin high and keeps the Uno from resetting and being accidentally reprogrammed instead of passing on its programming instructions to the target microcontroller (the ATtiny85).

I’ve also connected an LED between pin 2 (which is confusingly called “pin 3” under the Arduino IDE) and ground via a resistor. With this, we can test basic sketches such as “Blink”.

Brand new ATtiny85 ICs are set to have a 1MHz internal oscillator, and so they will appear to run slow if the sketch expects an 8MHz internal oscillator. To fix this, we make sure we have the ATtiny with 8MHz internal oscillator selected from the Tools>Board Menu, select “Arduino as ISP” as the programmer from the Tools>Programmer menu (note: there may be a similar sounding but different programmer called “ArduinoISP”), and that the Uno’s serial port is selected in the Tools>Port menu.

Fig 1

Click Tools>Burn Bootloader. I did mention before that we aren’t actually using a bootloader, but this is how the Arduino IDE can also set the configuration fuses on the ATtiny85.

void setup() {
  pinMode(3, OUTPUT);
}
void loop() {
  digitalWrite(3, HIGH);
  delay(1000);           
  digitalWrite(3, LOW);
  delay(1000);
}

You should see a “Done burning Bootloader” message in the Arduino IDE. If this is the case, the setup is probably correct, and you can open up the Blink sketch and change the references from pin 13 to pin 3.

Finally, click Upload (Ctrl-U or Sketch>Upload). If the LED starts flashing on for a second and off for a second, then you have a working ATtiny85 programmer on a breadboard.

If you get messages like “Programmer not found”, check that you have the correct programmer selected, that the serial port is correct, and that the ArduinoISP sketch is properly loaded onto the Uno (you might need to temporarily disconnect the wire on RESET to allow the sketch to be uploaded to the Uno).

If you get a message like “Wrong microcontroller found”, then check which “board” has been selected (e.g., you might have an ATtiny25 selected by default instead of ATtiny85). If the LED isn’t flashing at the right speed, then you might have an oscillator speed mismatch between the IDE and IC, so reselect the right speed from the Tools menu and select “burn bootloader” before uploading the sketch again.

The Build

THE BUILD

The build I’ve done incorporates sockets for both the ATtiny85 and also the ATMega328 as used in the Uno, as this is commonly available in an easy to use DIP package. Only if you want to work with both microcontrollers will you need both ZIF sockets – I’ll explain which parts are used for which microcontroller as we go.

I’ve used an Uno as the main board that does the programming, but the pinouts I’ve used should work with other main boards, because the connections are made to the ISP header.

Parts Required:JaycarAltronics
1 x Arduino Uno or compatible Board XC4410 Z6280
1 x Prototyping Shield XC4482 Z6260
1 x Basic 5mm LED ZD0150 Z0800
1 x 470Ω Resistor RR0564 R7042
1 x 18 Pin ZIF Socket PI6480 P0592
1 x ATtiny85 IC ZZ8721 Z5105
1 x 28 Pin ZIF Socket PI6483 P0599
1 x 16MHz Crystal RQ5296 V1089
1 x ATMega328 IC ZZ8727 Z5126

Some small lengths of wire offcuts are needed; I’ve cut up some jumper cables so that it’s easier to colour code the wiring. The LEDs and resistors are not mandatory, but are great for testing with the “Blink” sketch to confirm the programming is occurring properly.

I’ve built the circuit on the Jaycar proto shield. The Altronics version has a slightly different layout, so you may need to improvise a bit if you are using this. It also lacks the ISP header, which we use for board portability. It was a tight fit for both sockets, so I would recommend using the Jaycar proto shield if you are building the version with both sockets. Most of the construction occurs on the proto shield (and in fact, the Uno can easily be borrowed temporarily if need be, simply by unplugging and reprogramming).

I’ve used this colouring code throughout to help you follow the wiring. If you are using a proto shield that doesn’t have an ISP header, you’ll have to use the Uno equivalent pins, and you’ll only be able to use the shield with an Uno. There’s a diagram of the microcontroller pinouts in the “The Code” section too.

ISP FUNCTIONCOLOURATMEGA328 PINATTINY85 PINUNO PIN
MISOGreen18612
MOSIOrange17511
SCKYellow19713
SCKYellow19713
RSTBlue1110
5VRed7 and 2085V
GNDBlack8 and 224GND
Crystal9 and 10

To make the project transferable to other Arduino main boards (this should work fine with a Leonardo or Mega, although perhaps not a 3.3V board like a Due), I’ve run the SPI connections from the ISP header on the proto shield. Because the ZIF socket is quite large and ends up covering the ISP header, I had to make this connection first.

ISP Wires

The green wire is on the top left pin, the yellow wire on the middle left pin and the orange wire on the middle right pin. If your proto shield doesn’t have the ISP connections, then you will have to use an Uno, and also the alternative ISP connections listed in the table. Make sure these solder joins aren’t too tall, as the ZIF socket has to sit over the top of them.

The ZIF sockets can now be fitted. If you are fitting both, they’ll have to be placed as indicated. If you’re only fitting one, you might have more flexibility.

ZIF in place

You might find it easier if the handles on the ZIF sockets are placed in the “down” position, allowing the sockets to lie flat while soldering. The power connections to the 18 Pin ZIF Socket for the ATtiny85 can be made with small solder bridges to the 5V and GND rails of the proto shield.

Solder Bridges

After this, we can start laying down the other connections. I’ve put down the red, black and blue wires next. The red wire goes to the 5V supply on the microcontrollers and proto shield, and needs to go to pins 7 and 20 on the ATMega328. The black wire is GND, and goes to pins 8 and 22 on the ATMega328 and GND on the proto shield. You’ll see the solder bridges we have done in the last step are the power connections on the ATtiny85 – pin 8 for 5V and pin 4 for GND. The blue wire is for RST (on the target microcontroller), and goes to pin 1 on both the ATMega328 and ATtiny85, and then back to pin 10 on the proto shield.

Red and Black in place

To get our programmer functional, we need the green, orange and yellow wires connected. Green (MISO) goes to pin 18 on the ATMega328 and pin 6 on the ATtiny85; orange (MOSI) goes to pin 17 on the ATMega328 and pin 5 on the ATtiny85; and yellow (SCK) goes to pin 19 on the ATMega328 and pin 7 on the ATtiny85.

One final component we need for the ATMega328 is a 16MHz crystal oscillator, and this is attached between pins 9 and 10. Nearly all advice I’ve heard recommends capacitors be fitted to the crystal to help with stability, but I’ve never had an issue leaving them off – perhaps there’s enough stray capacitance in all the extra traces on the proto shield to provide a similar effect.

Although this is almost sufficient to get the programmer working, I’ve added two test LEDs as well, so that a simple sketch like “Blink” can be uploaded to demonstrate that everything is working as it should be. The LEDs are each in series with a 470Ω resistor, and connect to pin 2 on the ATtiny85 (this is known as digital “pin 3” under the Arduino IDE), and pin 19 on the ATMega328 (which is digital “pin 13” on the Uno – the same as the onboard LED). There’s also a wire link between RST and 5V to keep the Uno from resetting.

I’ve positioned the microcontrollers in place so that you can see where they should sit – closest to the end with the handle, with pin number 1 nearest the handle. Don’t put them in yet; only put them in when you are ready to program, and only one at a time.

Schematic

You’ll notice I’ve pulled a little trick with the LED for the ATMega328 (the yellow LED), and placed it near the ATtiny85, but connected it to the yellow wire – running back to pin 19 on the ATMega328. The resistor cleverly loops back to the ground track, running up the middle of the ZIF socket. I felt this was an easier choice than trying to add more wires to the large ZIF socket.

Don’t attach the Uno yet, as we still need to program, and it won’t be able to be programmed while the RST-5V link is in place.

Top and bottom

THE CODE

The code used for the Uno is the same as on the breadboard – upload the ArduinoISP sketch before attaching the shield (if the shield is attached, the reset is disabled, which prevents normal sketch uploading from occurring). Next, attach the shield and test the uploading works using the “Arduino as ISP” programmer selection.

Debugging is much the same, and when uploading to the ATMega328 as target microcontroller, the normal “Uno” board profile is used, so choose Sketch>Upload Using Programmer (or Ctrl-Shift-U).

You’ll notice that the ATMega328 circuit has a crystal while the ATtiny85 does not. This corresponds to the bootloader and fuse settings that are installed on the ICs. As I mentioned earlier, it is best to avoid selecting any ATtiny85 board profile that uses an external oscillator, as it will not work without a crystal attached.

Working in a similar fashion, there are board profiles for the ATMega328 that use its internal 8MHz oscillator instead of the 16MHz crystal. Obviously you lose some processing speed and the oscillator is not as accurate, but there are two more pins available and if you are designing a circuit, there is one less component that has to be laid out. Another advantage is that at 8MHz, the ATMega328P will work reliably down to about 2.5V (depending on brown-out settings), while it will only work down to about 4V at 16MHz. This means that projects running directly from a single lithium battery or two AAs are possible with an 8MHz oscillator.

To set up an ATMega328 to run at 8MHz, we need to select a board profile that matches this, then use this board profile to burn the bootloader (which includes the oscillator setting), and finally use the same profile to upload sketches. If the 16MHz Uno profile is used to upload sketches to an 8MHz ATmega328, it will appear to run slow, because the sketch expects the oscillator to be faster.

Fortunately, there should be one installed by default – this is the Arduino Pro Mini, which has four sub-options. The one we want to use is “ATMega328 (3.3V, 8MHz)”. This doesn’t mean that we have to run it at 3.3V, just that the Pro Mini runs at 3.3V by default. Choose the board as shown.

Pro mini

Next, burn the bootloader and upload a sketch via the programmer.

Another thing you might have noticed from the setup of our test LED, is that the IC pins don’t correspond to the pin numbers used in the Arduino IDE. The following diagram explains the pins on the ATtiny85:

Fig 3

The next diagram illustrates the pins on the ATMega328 as they correspond to the Uno (and also Pro Mini) pinout.

fig 4

WHERE TO NEXT?

The next step will be to use these instructions to build an actual project to program your microcontroller. These two microcontrollers both lend themselves to prototyping on a breadboard, which is what you probably would have done before Arduino was around. So following is a project I built a few years ago – to be honest, I can’t even remember what it does, but it is some sort of motor control!

project

Constructed on stripboard, this one uses an ATMega328, and it is tucked under the LCD, which is on header sockets for easy removal and access to the ATMega328 for programming. An Arduino and display shield would not have fitted in this case, let alone the other ICs and circuitry I’ve added. Of course, a similar design using an ATtiny85 would be even smaller.

Compared to the ATMega328, the ATtiny85 has 8kB of program flash and 512 bytes of RAM, versus 32kB of program flash and 2kB of RAM for the ATMega328. This alone will mean that your program will probably be able to do less.

As previously noted, the much smaller ATtiny85 will not replace an Uno. The limitation of only five IO pins can be restrictive as even devices like the HD44780 character LCDs need six IO outputs to work, and that’s before you consider what other functions you want your project to have.

There are also less hardware features – for example, there is no hardware serial port, or I2C or SPI support, so many libraries using these default interfaces won’t work at all. That said, there are some replacement libraries, especially branches of the “TinyWire” variant of the I2C library. A I2C interface is handy as it only requires two pins, and multiple devices can run from these same two pins with different addresses. A good choice for a display would be one of the small I2C OLED displays, which are often less than one-inch across in size. A great example of what can be done with this sort of display is an ATtiny85 based Tetris® game, which you can see at https://github.com/dombeef/pockeTETRIS

This all said, the ATtiny85 can be a great way to extend your Arduino knowledge beyond what is included in the IDE, and for making very small projects.

Expansion:

XC4496
ZZ8485

You might be thinking how you can get by with so few IO options from these chips. But the electronics world has you covered! Consider ZZ8485 from Jaycar - a 256kB I2C EEPROM, allowing storage of data that won’t fit into the ATtiny85’s memory.

Modules such as the XC4496 Compass and Magnetometer module available from Jaycar uses I2C, and can be used to sense the magnetic field in three dimensions.

There are a range of other modules using I2C, including functions like compass, magnetometer, real-time clock, accelerometer, gyroscope, thermometer or barometer and there are even EEPROM ICs which can also be added to an I2C bus to add extra storage space.

On the other hand, there are also libraries which can turn the ATtiny85 into an I2C slave, so that you can construct custom sensor modules to connect up to a larger Arduino like an Uno.

Addressable RGB LED modules and strips can easily be configured to run many LEDs from one pin, allowing the creation of tiny programmable lights that can respond to their surroundings.

The ATtiny85 is also suited to simple tasks. It would also suit being built into a version of the PIC Pocket Remote (without the PIC). With just one pin needed to output a signal to the 433MHz module, the chip will fit neatly into a small fob case and easily be able to handle a one-dimensional task like this.

BOOTLOADERS FOR THE ATTINY85

bootloaders

Despite their miniscule size there are, in fact, two versions of ATtiny85 boards that not only add a bootloader to simplify sketch uploading, but also provides USB support. As you can imagine, the USB support takes up a big chunk of our 8kB of flash program space, leaving close to 6kB free for our sketches. These two projects are known as the “Adafruit Trinket” and the “Digistump Digispark”; remarkably, both use the same circuit to connect to USB, because they are both based on the V-USB project for adding USB support to Atmel microcontrollers. Note: the V-USB implementation is not completely compliant with the USB specification, so there is no guarantee that this will work on all computers.

Just like any bootloader, it’s possible to “burn” it onto a blank microcontroller using a programmer like we have built on the preceding pages, and create your own version. The bootloader on the Digispark is one that disables the RST pin, so if you want to use the ATtiny85 for anything different, you’ll need a high-voltage programmer – for this reason, I would be careful about trying it.

As a bonus, these boards also offer better support in terms of libraries, than what is available with a plain ATtiny85.

You can build the above project on a breadboard to test out the USB bootloaders. To do so, you’ll simply need:

Parts Required:JaycarAltronics
2 x 68Ω Resistors RR0544 R7080
1 x 1.5kΩ Resistor RR0576 R7048
2 x 3.6V Zener Diode ZR1399 Z0306

I created a USB breakout by cutting up an old USB lead, and soldering some pin headers onto the wire. I would recommend checking the polarity of the red and black wires (and even checking that they are in fact 5V and GND as their colours suggest). Also, if you are still having trouble getting it to work, try reversing the white and green wires, as sometimes they appear not to be wired to the standard. I would also recommend keeping the USB lead as short as possible – I was getting occasional glitches with the leads I was using.

Of course, this is just the USB circuit. The ATtiny85 first needs to have the bootloader burnt, but unfortunately, this is not as easy as using the Arduino IDE. I’ve found the best tool for working directly with flashing microcontrollers is one called “AVRDUDESS”, which is actually a GUI for the program (called “AVRDUDE”) and does the uploading under the Arduino IDE. It is possible to use AVRDUDESS, for example, to read the HEX file off an Arduino board and write it to another board, which can be quicker than using the Arduino IDE to compile and upload every time.

fig 5

So, if you have the Arduino IDE installed, you should have AVRDUDE installed, and you can just install AVRDUDESS from http://blog.zakkemble.co.uk/avrdudess-a-gui-for-avrdude/.

The other thing you will need is the respective HEX file for either the Trinket or Digispark. The Trinket HEX file can be downloaded from Adafruit’s Github page at https://github.com/adafruit/Adafruit-Trinket-Gemma-Bootloader. In this case, we need the trinketgemma_v1.hex file. On the other hand, the Digispark actually uses a bootloader called “micronucleus”, and the Digistump page points to the micronucleus page at https://github.com/micronucleus/micronucleus. We need the t85_default.hex file.

Open AVRDUDESS, and select programmer type as “Arduino”, the COM port should correspond to the COM port of the programmer you have built. Under Flash, open the HEX file you want to use, and under MCU, choose ATtiny85. Under Flash, select “write” then click “go”. The HEX file should upload. If there are issues, check under Options to confirm that AVRDUDESS knows where to find the AVRDUDE program.

AVRDUDESS

If that has worked, there is one more step, and that is to set the configuration fuses. For the Digispark firmware, set the L (low) fuse to 0xE1, the H (high) fuse to 0xDD and the E (extended) fuse to 0xFE and then click “write” under fuses. This configuration does not disable the reset pin, so you will not have a true Digispark clone, but it should allow you to test that it works.

For the Trinket firmware set the L (low) fuse to 0xF1, the H (high) fuse to 0xD5 and the E (extended) fuse to 0xFE and then click “write” under fuses.

Now, to get the newly flashed board working under the Arduino IDE, you will need to add board support. Using the Board Manager, add the following URLs:

https://adafruit.github.io/arduino-board-index/package_adafruit_index.json

http://digistump.com/package_digistump_index.json

Then add the boards by searching on Boards Manager for “trinket” and “digispark” respectively.

After this, try uploading sketches. Both bootloaders behave slightly different ways to other boards, so you may need to unplug and replug the USB to initiate the upload.