Raspberry Pi and Arduino, what an iconic pair.
The Pi brings gigahertz of processing heft, a ton of memory, and can interact with computer networks and peripherals, but it sucks at interacting with analogue voltages and real-time critical tasks. That’s where the Arduino excels.
While a full Arduino board is super handy for learning, exploring, and prototyping, it’s too bulky and expensive to suit a finished product.
At some point you’ll probably want to replace it with a standalone microcontroller. If your needs are simple enough, maybe you could use one as small and cheap as an ATtiny85.
The ATtiny85 is an AVR microcontroller, in the same family as Arduino boards. It’s compact, low power and affordable.
By default, the internal clock is set to 1MHz. For many Raspberry Pi projects, this is enough, because we do most of our computation on the Raspberry Pi’s vastly more powerful hardware.
If you need faster processing, you can set the internal clock to 8MHz. Using an external clock, you can run it at up to 20MHz.
This IC can run on anything from 1.8 to 5.5 volts. For Raspberry Pi projects, it can be handy to run it at 3.3 volts so that we don’t have to worry about handling different logic levels.
Running it at a higher voltage, you can use the higher clock speeds and supply more current and voltages from the pins. Or you can run it at a lower voltage to save power.
The downside of using such a small microcontroller is that you don’t have many pins. Of the 8 available, 2 are for power and ground, and another is a reset pin. This leaves five pins for input and output.
A Raspberry Pi has plenty of GPIO pins already, so often, our reason for wanting a microcontroller is to do things that the Pi can’t do well or at all, like reading and writing analogue voltages.
If you use two of these five pins to connect to an I2C bus, you’ll have three I/O pins left over. Two of them have an ADC to read analogue voltages, and one has PWM hardware.
For a complete look at what the pins can do, read the datasheet.
This is an AVR microcontroller, which means you can use the Arduino IDE to compile your hex files before writing them to the chip. Most of the code you already know from your Arduino projects will run here.
Sometimes, hardware differences mean that certain elements of your code won’t work. For instance, it doesn’t have the same I2C hardware, so the wire.h library we used when we set up I2C on an Arduino Uno won’t work here. To use I2C you will need something like the TinyWire library.
The flash memory on the ATtiny85 is relatively constrained. Your program has to fit within 8kb.
Getting your program on to an Arduino board is quite straightforward. You plug it into a USB port and press “upload” on the Arduino IDE.
There’s nothing to plug a cable into on the ATtiny85 – it’s just an 8 pin IC. To load a program, we have to interact with those pins.
Specifically, we first connect the power and ground pins. Then we pull the reset pin to low, which sets it ready to receive a program. We then use a 3 pin SPI connection to write the data.
You can do this with little USB programmers available off the shelf for around $20. If you’re programming a lot of microcontrollers, maybe that’s a good buy. Maybe you don’t want this expense and clutter for a thing you might only do once.
It’s also possible to set up an Arduino board as an AVR programmer.
So why don’t we use the SPI hardware on the Raspberry Pi?
This is a great opportunity to take a closer look at what’s happening when you program these microcontrollers.
What I also find super convenient is that we can run this all from the command, which means you can do it over an SSH session. So, you can enjoy the nice display and fast compile times of a much more powerful laptop or desktop PC, without it cluttering your work area.
Let’s now go through writing a simple program to this chip. For this, you’ll need:
The ATtiny85 works just fine with no IC socket, but the pins can bend when you move it around over and over again while prototyping. 80 cents saves you this small but real annoyance.
We’re assuming this isn’t your first rodeo with the Arduino IDE. You should be fine if it’s only your second or third.
If you’re totally unfamiliar with the SPI interface, you might also want to quickly read up on how SPI works. You will get a little bit more out of this if you know what MOSI, MISO, and SCLK pins do.
By default, the SPI protocol is switched off on Raspberry Pi OS. To enable it, type:
1 |
sudo raspi-config |
Select Interface Options and then SPI and then Yes. Exit the configuration menu.
You need to restart the Pi for this to take effect, so type:
1 |
sudo reboot |
Open your Arduino IDE on your machine of choice. Let’s set it up to compile for ATtiny chips.
Click File and select Preferences. In the field marked Additional Boards Manager URLs, paste:
1 |
https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json |
Press OK to close the window.
(If you don’t see a field to paste this URL, you are probably using an old version of the Arduino IDE. This will happen if you installed it using the apt package manager on Raspberry Pi OS. To fix this, install the latest version from the Arduino website).
Click on Tools and then hover over the Board: “Arduino Uno” (or whatever board you currently have selected).
Select Boards Manager. Scroll all the way down to find the ATtiny boards and install the latest version.
Now return to the Tools menu and set it to an ATtiny85 running at 1MHz.
We’re now ready to compile some code.
The Arduino IDE contains a whole bunch of built-in examples that are pretty much perfect for testing purposes, so let’s nick one of ‘em.
Select File, hover over Examples and then 01. Basics and then click Blink. This is nearly ready to compile just as it is.
You’ll notice though that this uses the constant LED_BUILTIN to refer to the board’s built-in LED. The ATtiny85 doesn’t have a built-in LED, so this won’t work. Let’s set it to a pin number. I recommend you choose pin 3, because it will still be available after connecting the SPI pins.
Once you’ve tweaked this code, it should look like this:
1 2 3 4 5 6 7 8 9 10 11 |
void setup() { pinMode(3, OUTPUT); } // the loop function runs over and over again forever void loop() { digitalWrite(3, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(3, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } |
Save this sketch as Blink85.
All that’s left to do now is click the Sketch menu and select Export compiled Binary. Within your Arduino, you’ll find a file named Blink85.ino.tiny8.hex. We’ll write this hex file to the chip.
Copy this file to your Raspberry Pi’s home folder.
Connect the GPIO extension board to your Raspberry Pi and then insert it into the left side of your breadboard.
If you’re using an IC socket, insert the ATtiny85 into it. On the top of the IC, you will see a small circular indentation in a corner. This marks pin 1. Place the IC on the breadboard a few rows down from the extension board, with pin 1 in the upper right.
Your breadboard should now look something like this:
Connect one of the Raspberry Pi’s 3.3-volt pins to the positive power rail running along the bottom of the breadboard, and a ground pin to the negative power rail running across the top.
Then connect pin 4 to the negative power rail, and pin 8 to the positive power rail.
We need to put some resistors on the board so that the circuit doesn’t draw too much current.
The ATtiny85’s SPI pins run across the bottom of the chip, beside the power pin. Attach a 1k resistor to each of those. Place the other leg of each resistor in the unoccupied rows to the left of the IC.
also need a 1k resistor on the reset pin. That’s pin 1. Place the other leg of the resistor in a row to the left of the IC again.
We’ll
We also need a resistor in series with the LED connecting to pin 3. Place your 470 Ohm resistor between the negative power rail and one of the rows on the right of the IC.
Now that the resistors are on the board, let’s connect the Raspberry Pi’s SPI pins.
Pin 7 on the ATtiny85 is the SCLK pin, so connect the attached resistor to the Raspberry Pi’s SCLK pin. That’s GPIO11, located at header pin 23.
Pin 6 on the ATtiny85 is the MISO pin, so connect the attached resistor to the Raspberry Pi’s MISO pin. That’s GPIO09, located at header pin 21.
That leaves pin 5, which is MOSI. Connect the attached resistor to the Raspberry Pi’s MOSI pin.
We’ll also want to wire a GPIO pin to, so attach GPIO22 to the resistor on pin 1.
The last thing to place on the breadboard is the LED. Remember that the longer leg – the anode – has to connect to positive. Connect the anode to pin 3 and the cathode to the 470 Ohm resistor attached to ground.
We’re nearly there! We have our Pi connected to our microcontroller and a simple program to write to it. Now we just need some software that will do the programming.
Avrdude is a command-line utility that does just that.
We actually need Kevin Cuzner’s version of avrdude, which lets us use the on-board SPI hardware as a programmer. So even if you already have a different avrdude package installed, follow these instructions.
First, update your Raspberry Pi and install dependencies:
1 2 |
sudo apt update && sudo apt upgrade -y sudo apt install bison automake autoconf flex gcc-avr binutils-avr avr-libc -y |
These commands will take a few minutes. Next, clone avrdude from github:
1 |
git clone https://github.com/kcuzner/avrdude |
Then navigate to the directory with the installation scripts and run them:
1 2 3 4 |
cd avrdude/avrdude ./bootstrap ./configure sudo make install |
To, we need to pull the ATtiny85’s reset pin low. That’s connected to GPIO22, so let’s use the GPIO command to set that to output and pull it low.
1 2 |
sudo gpio -g mode 22 out sudo gpio -g write 22 0 |
Now let’s test the connection. Type:
1 |
sudo avrdude -p t85 -c linuxspi -P /dev/spidev0.0 -b 10000 |
That’s a bit of a mouthful, right? What’s going on there? Well, the -p t85 tells avrdude that it’s talking to an ATtiny85, the -c linuxspi says to use on-board SPI hardware, the -P devspidev0.0 says to use SPI port 0 and the -b 10000 says to run it at 10000 baud.
If everything is connected and working, you should see output like this:
Now we can write our hex file to the ATtiny85. So, let’s navigate back to the home directory.
1 |
cd ~ |
The next avrdude command is very similar to the one we just ran, we just have to add an instruction to write the file, like this:
1 |
sudo avrdude -p t85 -c linuxspi -P /dev/spidev0.0 -b 10000 -U flash:w:Blink85.ino.tiny8.hex |
All that’s left to do now is to bring the reset pin up to take the microcontroller out of programming mode.
1 |
sudo gpio -g write 22 1 |
If your LED is now blinking, you have successfully programmed an ATtiny85!
Don’t panic, this should be easy to troubleshoot. Check:
If the ATtiny85 doesn’t offer quite what your project needs, there’s a whole world of AVR microcontrollers to explore. This procedure works very similarly for most of them.
Just check the pinout to see where the reset and SPI pins are located and load the right profile into the Arduino IDE.
It’s that easy.