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.
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.
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.
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.
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.
/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
/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
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.