Build an ‘Arduino’ on a Raspberry Pi

This is, after all, supposed to be a blog about Raspberry Pi. With all the stuff about Arduino and Atmel AVR chips, you might think I have wandered off. However, just to prove that Pi and 'Duino work well together, here's how I hand-built a board to sit on the Raspberry Pi GPIO pins and provide extra programmable I/O.

I had been thinking of giving this a go for a while. There are several commercial boards which offer this kind of functionality, but they all seem a bit expensive and a bit complicated. For me part of the joy of Raspberry pi is the way that things don't have to seem like "magic". We can make things ourselves, and by doing that we can understand them better. I was particularly prompted to start this by someone who pointed me at the "Pico PiDuino". On the surface this seems like any other basic AVR circuit such as a Shrimp, but the key point with this one is that it ignores most of the external components (resistors and capacitors etc.) and relies on the Raspberry Pi both to provide a good quality power supply and as a programming adapter.

The Pico PiDuino design does, however, include three LEDs connected to non-standard ports. If you remove those, the circuit is very simple. Simple enough for me to try and build one on some proto-board without tearing my hair out.

piduino-1

The basic circuit is very simple. The 3.3V and ground lines from the Raspberry Pi GPIO header are connected to Vcc and ground on one side of the AVR, and then crossed over to the other side in the characteristic slipped-X pattern. Then a 16MHz crystal is connected to the appropriate pins. If we were neither concerned about programming the ATmega, nor communicating with the Raspberry Pi, we could stop here. A pre-programmed chip could be inserted and would start doing its thing (blinking a LED, or whatever) when the Pi powers up.

piduino-2

In practice, removing the chip to program it every time would be fiddly, slow, and risky. It would be easy to damage the device or the socket. Luckily, though, pretty much all microcontrollers have some sort of "in-system programming" feature, which allows them to be re-programmed without needing to remove them from the circuit. In the case of Atmel's ATMega devices, this is done using the SPI pins (MOSI, MISO, and SCLK). All that is needed is to pull the RESET pin (pin 1) low to enter programming mode, then supply the new program over the SPI connection. The Raspberry Pi has a built-in SPI facility, so to program the AVR we need to connect the SPI pins, and also connect CS0 (GPIO8) to the reset line.

Double Pi layout

So far, this is pretty much like a stripped-down "PicoPiDuino", but I don't want to have a breadboard and a bunch of hook-up wires flopping about. I want a nice neat board to sit on my Pi. So I tramsferred the design to some proto-board I had lying around (you may recognize the size of board from my article a few months ago where I built a board to hold an ADC chip.


Double Pi SPI and power connected

In general I much prefer stripboard (such as Veroboard) over this kind where the holes are not connected at all, but it's hard to argue with such a convenient sized board. Wiring the power and SPI programming lines was fiddly enough, but the hardest bit turned out to be something I had ignored when working on a breadboard. In order to connect things to the microcontroller I need some headers, and each pin of each header needs to connect across to the appropriate pin on the chip. Eventually I got the knack of using a fine piece of copper from some spare wire to guide the solder across from one pad to the next, then let it cool and snip off the excess. This is a problem that generally does not happen with stripboard or PCBs. I did as much of the wiring as I could on the underside of the board, both to keep it looking neat, and to avoid getting in the way of anything I might plug in to the headers later.

With the basic board built, I needed to test it. Although it was really tempting to just pop it onto the Raspberry Pi to see if it works, I did not want to risk blowing up the Pi if I had accidentally shorted power and ground together, for example. So my next step was to go all round every connection and its neighbours with a continuity tester to make sure everything was in order. Only when I was happy with the continuity testing did I put the board on the Pi and tentatively power it up. Luckily, no problems with or without the AVR chip.

The next step was to program the chip using the Raspberry Pi, so I could actually see it doing something. I took my inspiration for the software setup from Gordon Henderson's guide to using an ATMega on a Gertboard. I didn't follow his steps exactly, as I don't have the rest of the Gertboard attached.

After the usual update process (if required)

sudo apt-get update
sudo apt-get upgrade

Install the Arduino IDE and tools. This is the same as you would do if you were planning to work with an actual Arduino board.

sudo apt-get install arduino

Then the bit specific to this configuration. First we need Gordon's modified "avrdude", which knows how to use a GPIO pin to control the RESET line.

cd /tmp
wget http://project-downloads.drogon.net/gertboard/avrdude_5.10-4_armhf.deb
sudo dpkg -i avrdude_5.10-4_armhf.deb
sudo chmod 4755 /usr/bin/avrdude

To check that everything is in place, with the ATMega connected and the board plugged in, enter:

avrdude -p m328p -c gpio

This should result in a confirmation message (you can see an example screenshot part-way down Programming Your Pico PiDuino. If you get a message indicating that the Pi could not contact the AVR, then you should check your wiring again,

Once everything is we meed to add definitions to the Arduino IDE boards.txt and programmers.txt to let us select the right connections when trying to program the device. Gordon recommends downloading some config files with the entries already added. This is usually OK, but if you have made any changes to these files yourself (for example by adding support for a different board, or for programming a chip using the internal oscillator) beware that they will be overwritten.

I decided to just add some entries to the top of each of the two files.

To /usr/share/arduino/hardware/arduino/boards.txt add the following:

##############################################################

gert328.name=Gertboard with ATmega328 (GPIO)

gert328.upload.using=gpio
gert328.upload.protocol=gpio
gert328.upload.maximum_size=32768
gert328.upload.speed=57600
gert328.upload.disable_flushing=true

gert328.bootloader.low_fuses=0xE7
gert328.bootloader.high_fuses=0xDA
gert328.bootloader.extended_fuses=0x07
gert328.bootloader.path=atmega
gert328.bootloader.file=ATmegaBOOT_168_gert328.hex
gert328.bootloader.unlock_bits=0x3F
gert328.bootloader.lock_bits=0x0F

gert328.build.mcu=atmega328p
gert328.build.f_cpu=12000000L
gert328.build.core=arduino
gert328.build.variant=standard

To /usr/share/arduino/hardware/arduino/programmers.txt add the following:

gpio.name=Raspberry Pi GPIO
gpio.protocol=gpio

Now, when you start the Arduino IDE you should look in the Tools menu and select Gertboard with ATmega328 (GPIO) as the board type, and Raspberry Pi GPIO as the programmer. Now load up an example program (for example, the trusty "Blink") and send it to the device using File::Upload Using Programmer or press Ctrl-Shift-U.

avr-blink

And finally, here's an animated GIF of the board on the Raspberry Pi, with an LED between pin 13 and GND, running a "Blink" program compiled and transferred to the device direct from the Raspberry Pi.


3 Comments

  1. Pingback: Arduino serial communication finally working | Raspberry Alpha Omega

  2. Frank, I just came across your tutorials, really enjoying them and learning a good bit in the process. I’m also working on interfacing RaspberryPi with Arduino (to get ADC and PWM, mainly). Anyway, I had a question about your boards.txt entry above… In the text of the post, you say you’re using a 16MHz crystal on the ATMEGA328, but then in your boards.txt, you’re telling it to comile code as if you’re using 12MHz?
    gert328.build.f_cpu=12000000L
    Is this an oversight, or is there a timing problem when interfacing with the Pi that makes this necessary?
    Thanks for the informative articles, keep them coming!

Leave a Reply

Your email address will not be published. Required fields are marked *