Introduction: The Raspberry Pi - Arduino Connection

About: hobbyist, tinkerer, old curmudgeon
The Pi is a fine little computer board, though not nearly as good as
the Arduino when it comes to I/O capabilities. The beautifully-engineered
Gertboard is a plug-in add-on that neatly overcomes this deficiency
by giving the Pi access to an ATMega328, but it's a very complex and
expensive solution. An alternative would be to interface an Arduino
running at 3.3 volts to the Pi, though this is easier said than done.
But, we won't let that stop us, will we?

You can buy a prebuilt  commercial version
of something similar to this project.
It's called an AlaMode, and it goes for something like $50.
Our version will cost about a third of that to build.

As a first step, we will build an Arduino plug-in board for the Pi.
It is customary to call Pi boards "plates," but indulge me and permit
me to name this particular board a hoody. Thank you.

We will be using generic stripboard to build our project. Small (3-3/4"
x 2-1/16") boards can be obtained on eBay for a bit over a dollar apiece.
It is also possible to use something like a Radio Shack 276-168 protoboard
($3.49). The main component, though, is an 3.3-volt Arduino Pro Mini.
This will permit connecting directly to the Raspberry Pi ports and other
3.3-volt devices without having to do level shifting.


Quite a number of Pi projects involve connecting sensors and devices
directly to the GPIO pins. This is not a good idea. Use buffer chips,
such as the 74HC4050 hex buffer, between the devices and the GPIO.
This protects the Pi from overvoltages, current surges, and your mistakes.
Far better to blow out a fifty-cent buffer chip than a $35 Pi.

This particular project connects directly to the GPIO Rx and Tx pins.
However, we are connecting to a 3.3 volt device, which limits the risk.
Still, a buffer chip would not be a bad thing here.


This is a moderately complex project, and beginners need not apply.
It requires skill at soldering and in the use of hand tools. Experience
with a continuity tester and a steady hand with a knife blade are also
helpful.

Ready? Well, then, let's get on with it!


Step 1: Parts Needed

  1. Arduino 3.3-volt Pro Mini clone
  2. 1 - stripboard (protoboard), 3-3/4" x 2" or larger
  3. 1 - 24-pin wire-wrap socket ***
  4. 1 - 26-pin, stacking header
  5. 2 - 40 pin female header strip (as for Arduino projects)
  6. 4 - female-to-male jumper cables / patchcords
  7. Nokia 5110 display (optional, but recommended) 
  8. Raspberry Pi, model A preferred (lower power drain)
  9. Video display for the Pi, Atrix lapdock recommended
  10. Hookup wire
Nothing terribly exotic, folks, and fairly cheap to get, too.


Cost:
  • stripboard              $1.25
  • wire-wrap socket   $1.50
  • stacking header     $2.00
  • jumper cables        $4.00 (for set of 40)
  • female header strips                     $1.00
  • Nokia display         $6.00
  • Arduino pro mini  (or clone of same),  3.3 volt model   $7.00


Total is under $25, if you don't already have any of the components laying
around.


Tools:
  • Soldering iron
  • wire cutters (Plato 170 or similar)
  • sharp knife (or optionally a Dremel-type rotary tool)
  • continuity tester (preferred) or a multitester



Notes:

*** Do not use a regular 24-pin socket. The legs of the Arduino pro mini
      will not fit into the holes. But, you can substitute two 14-pin strips of female headers.
    

Yes, it is possible to use a "normal" mini-Arduino powered at 3.3 volts for this project.
Some examples of such are the Boarduino and Ardweeny.
Be aware, however, that the ATMega328 chip is not rated to run at 16 MHz powered
at 3.3 volts. So, you would be running it out of spec, or essentially overclocking it.
I've done some experimenting with this, and at least some, maybe most ATMega328s
can be programmed and run at 3.3 v. But, of course, your mileage may vary.

Step 2: Building the Board [1]: Installing the GPIO Header

I used a stripboard to build the Raspberry Pi interface
board/hoody. Stripboard has the advantage of design flexibility --
it does not constrain the component layout to any particular configuration.
It's also much cheaper than equivalent-sized solderable protoboards.
The chief disadvantage of stripboard is the necessity of extensive cutting
of copper traces on the solder side.

It's advisable to have a preliminary idea of the layout before beginning.
A rough diagram on a sheet of paper helps.

I mounted the 26-pin stacking (long-pin) GPIO header near one edge
of the board, with the female (plug-in) part of the header on the
copper-trace side. The trick is for the header not to mount flush
against the board, but to stand off about 1/4" high in order to permit
soldering the pins to the copper traces. But, first we need to cut
thirteen rows of traces where the GPIO header will mount, so that adjacent
header pins will not be shorted to each other (see 2nd and 3rd illustrations).
Cutting the traces requires going back and forth with a sharp knife blade
with a fair amount of pressure (caution!), then follow-up checking with
a continuity tester. It's a fair amount of work, and next time I try
something like this I'll probably use a Dremel tool with cutting disk,
rather than a knife.

With the thirteen traces cut, carefully mount the GPIO header
approximately 1/4" in elevation. This will give enough room to maneuver
the tip of the soldering iron between the pins to solder them. A couple
of dabs of poster-mounting putty hold the header in position prior to
soldering. Solder one end pin, then carefully straighten out the header
so it sits perpendicular to the board. Solder the remaining pins, then
use the continuity tester to look for shorts beween pins, both sideways
and across. A good continuity tester with audible indicator is especially
helpful here.


After soldering, the header pins will protrude 1/4" or a bit more on the perfboard
(non-solder) side. This is convenient, as these will function as posts to attach
patch-cords and jumpers. Each post will be an electrical connection to the
corresponding GPIO pin underneath when the board is mounted on the Pi.

Step 3: Building the Board [2]: Installing the Arduino Socket

The interface board needs a means of plugging in an Arduino, and
specifically a 3.3-volt mini Arduino Pro. This is where the 24-pin
wire-wrap socket comes in. For some reason, the Arduino Pro module neatly
plugs into a wire-wrap socket, but the pins are too fat for a regular
24-pin socket
. Fortunately, wire-wrap sockets are widely-available and
not too expensive. I happened to have a couple laying around from a 2716
EPROM project I was working on several decades back.

Position the socket about an inch down from where the two rows of posts
stick up from the GPIO header on the perfboard side (see pics). Solder
the socket flush onto the board. After soldering, clip the protruding
pins flush on the copper-trace side of the board. Then, cut the rows
of copper traces between the two rows of soldered pins on the socket,
so that adjacent pins do not short together.

From the 40-pin female header strip, clip off two 12-pin strips.
On the perfboard side, position a 12-pin female header strip on each side
of the IC socket. This will provide plug-in points for jumper-wires to
access the Arduino pins. Secure the header strips so they are vertically
positioned relative to the board. Now, turn over the board and solder
each row.

There is a sort of art to clipping off sections of female header strip.
There are no notches, as with male header strip, so the clipped-off
strips will usually come out a bit ragged, but this hardly matters. The
trick is to clip in the middle of a hole, and this will either leave
a metal prong hanging, or the prong will just fall out. It wastes one
hole of the strip each time you clip, but there is no avoiding this.

There is a piece of female header strip left over. Clip off an 8-pin
strip from it. You will have to get the second 40-pin strip in order to
be able to clip the second 8-pin strip because one pin always gets wasted
in the clipping process. These two strips will make up a socket for an
optional Nokia 5110 monochrome display for our project. The two rows will
short together on the solder side, so jumper wires can be electrically
connected to the pins of the Nokia display. Position the strips, then
turn over the board and solder them. Finally, cut rows of copper traces,
so that the Nokia socket is electrically isolated from everything else.

I installed two dual-row "utility" socket strips on the periphery of
the board. The installation and soldering procedure is the same as that
for the Nokia socket. The actual number of pins in these socket rows is
arbitrary, but they are useful for power and ground busses, among other
things. After soldering, cut appropriate rows of copper traces to isolate
these strips electrically from the rest of the board.

Step 4: Wiring It Up: Part 1

Now that the interface hoody is built, where do we go from here?
We must still plug in the Arduino Pro and the Nokia display into the
sockets we've prepared. Then, we'll run jumper wires and patch-cords --
from the Arduino to the display, and, in the following step, from the
Arduino to the GPIO posts.

If you have just purchased a Nokia 5110 display, then you will need
to solder a row of male headers to the 8 solder holes for the power
and date lines. Take note of how the holes are labeled.

Nokia 5110 displays, unfortunately, do not have a standard pinout
configuration. They do all have the same complement of pins, but they
are not necessarily in the same position on the display board's
connector. Even the labeling of the pins varies, though they still
have the standard functions.

  • Arduino     Nokia display pin name          Nokia display pin number
  • (Digital)
  •  
  • pin 7 -     Serial clock out (SCLK)             varies
  • pin 6 -     Serial data out (DIN)                 (see pin labels on display)
  • pin 5 -     Data/Command select (D/C)
  • pin 4 -     LCD chip select (CS)
  • pin 3 -     LCD reset (RST)
  •  
  • Vcc           --> Nokia Vcc (3.3 v.)
  • Ground     --> Nokia Ground
  • Vcc           --> Nokia backlight

If possible, use different colored jumper wires for each function,
say red for Vcc, black for ground, and appropriate colors for the
data lines. This will make it easier to trace the connections and to
double-check your work. Work slowly and meticulously, and be especially
careful not to make any errors with the Vcc and ground connections.

Note that in the illustration the two end pins in each strip of the Nokia socket
have wire jumpers. This is because I used 10-pin strips, and the Nokia display
uses only 8 pins. The jumpered holes are blocked from use.


We're almost done with the hardware part of the project, so you can stop
and have a cup of coffee.


Step 5: Wiring It Up: Part 2

Time to connect up the GPIO header posts with the Arduino pins.
We will use female-to-male jumper patch-cords.

There are only four, count 'em, four connections to make.
Here is where the two rows of female headers alongside the Arduino socket come
in handy.

  1. Vcc (3.3v) on the Arduino connects to the GPIO Vcc (3.3v) pin:    Pin #1.
  2. Ground on the Arduino connects to the GPIO Ground pin:           Pin #6.
  3. TxD on the Arduino connects to the GPIO RxD pin:                        Pin #10.
  4. RxD on the Arduino connects to the GPIO TxD pin:                        Pin #8.

Note that TxD connects to RxD, and vice-versa. The reason for this is that
signal-out on one device goes to signal-in on the other. It's a bit confusing
at first, but quite logical when you think about it.

To facilitate tracing and troubleshooting, use a red jumper for Vcc and a
black one for ground, and two other colors for TxD/RxD and RxD/TxD.

Check your work, and be especially careful with Vcc and ground. A mistake
here could be costly.


Whew! All done with the hardware! Now, on to the software.

Step 6: Software, Part 1: Arduino Sends Data to Pi

A preliminary note:
This, and the following two steps work on a Pi running Fedora Remix 18
(Pidora). I had only partial success with Arch Linux, and no joy at
all with Raspian or Occidentalis, possibly because these distros tie
up /dev/ttyAMA0.


We're not quite ready to plug the interface hoody into the Pi.
First, let's load a program into the Arduino Pro that will tell
it to broadcast data on its serial port. Hook up an appropriate
serial/tty-to-USB cable or an FTDI breakout board to the 6-pin right-angle
programming header. Plug the USB end into your laptop computer
running the Arduino IDE, and upload the following sketch into the Arduino.
So, this would give the Pi access to analog ports and devices that connect
to same.

This is a simple sketch that increments a variable and sends it to
serial-out as part of a "Line Number #" string. It will display in the
console or on an xterm on the Pi running minicom
(sudo yum install minicom if it's not already installed).


* ArduinoTalks.ino
   Arduino sends message to the Pi */

//#include <stdlib.h>
#define DELA 1200  // Time between message sends.
int cnt=0;


void setup() {
  Serial.begin(9600);

}

void loop() {
  Serial.print("Line Number # [");
  Serial.print(cnt);
  Serial.println("]");
  delay(DELA);
  cnt++;
 
}



You can also download it:
http://bash.deta.in/ArduinoTalks.ino


Now, we're finally ready to plug our interface hoody into the Pi's GPIO
connector. Carefully orient the pins so that female header Pin 1 plugs
into GPIO Pin1, etc. Gently press down, and ...

   Note: This step does not need the Nokia 5110 display. You can leave
   it plugged in if you like, or remove it.

All right, hook up the Pi to power and a video display. Make sure an
SD card with Pidora is in the card slot underneath. Now boot it up and
invoke minicom (sudo minicom -s) in the console or in an xterm. You'll
have to set minicom to the /dev/ttyAMA0 serial port, because this is
what rx and tx are hooked to. The default setting of minicom is
/dev/modem, so you can cd /dev and sudo ln -s ttyAMA0 modem.
And set the baud rate to 9600, because that's what the sketch has
set the Arduino serial transmission speed to.

Cross your fingers. Can you see the data that the Arduino is sending?

This might seem trivial and of little practical value, but consider this.
Suppose the Arduino is receiving data from a sensor connected to
an analog pin. Then the Arduino could communicate this data directly
to the Pi through minicom. And note that minicom can save the data sent
to it in a logfile.



Step 7: Software, Part 2: Pi Sending Data to the Arduino (Blinking an LED)

And now for something a bit more difficult. Let's have the Pi tell the
Arduino how many time to blink an LED. We'll use the Arduino's on-board
LED at D13 for simplicity, though it's certainly possibly to change the
LedPin variable in the sketch, and hook up an outboard LED-plus-resistor
between the appropriate digital pin and ground.


The "driver" is a short shell script. That's right, a lowly Bash script.
In fact, it's even possible to do it right from the command line in
the console or in an xterm: echo 3 > /dev/ttyAMA0 for three blinks, for
example, or echo 7 > /dev/ttyAMA0 for seven blinks. No Python programming
and no libraries to install! Well, I don't much care for pythons or nasty
sorts of snakes that wrap around and the crush you. If I run into one,
I'm liable to Bash it over the head.

=== Recall that /dev/ttyAMA0 is the Pi's serial port. ===

It's necessary to run a minicom session in order to initialize the
/dev/ttyAMA0 serial port. Then, Control-A Q to exit minicom without
resetting the serial port. Note that it's also possible to send blink
commands directly from within minicom -- typing a 5 in the minicom
window blinks the Arduino's LED 5 times, and it's not even necessary
to set local echo. The Arduino receives anything sent to /dev/ttyAMA0
on its hardware serial port (Rx and Tx), and it it can interpret what comes its way
if programmed by an appropriate sketch. You see, folks, if you use the
Arduino as a go-between, you don't need to mess with Python or libraries.
 

Summarizing: Run a minicom session to initialize /dev/ttyAMA0, and then
Control-A Q to exit. And note that the Arduino has to have the following
sketch loaded. Then finally, run the Bash script below from the console
or an xterm.


Here is the Arduino sketch:

/*
  ArduinoListens.ino
 
  Pi sends a digit (1 - 9) to Arduino,
  and Arduino blinks LED at D13 that many times.
*/

#define DELA 500   // Long delay.
#define DSHORT 250 // Short delay.
const int ledPin = 13;

void setup() {               
  pinMode(ledPin, OUTPUT); // Initialize pin as output.
  // Pin 13 has an LED hooked to it.
  Serial.begin(9600); 
}

void loop() {
   if ( Serial.available() )
   { light(Serial.read() - '0'); } // How many positions past ASCII 0?
   delay (DELA);
}


void light(int n) {
  for (int i = 0; i < n; i++)
  {
  digitalWrite(ledPin, HIGH);   // Turn the LED on.
  delay(DSHORT);       
  digitalWrite(ledPin, LOW);   // Turn the LED off.
  delay(DSHORT);               // Wait.
  }
}


You can download it here:
http://bash.deta.in/ArduinoListens.ino



And here is the Bash script:

#!/bin/bash
# Accepts command-line arg telling Arduino how many times to blink
#+ (0 - 9).

DEFAULT=1          # One blink if no command-line arg.

if [ -z "$1" ]     # If no command-line arg ...
then
  blinks=$DEFAULT
else
  blinks=$1
fi

port=/dev/ttyAMA0  # Direct connection to Pi rx and dx pins.

echo $blinks > $port

exit $?

# TODO:
# ----
# 1) Error checking on command-line input.
# 2) More than 9 blinks by parsing multi-character command-line arg.


You can download it here:
http://bash.deta.in/blink-ard.sh


Not a very complex sketch, and think of how easy it would be to modify it to
run a servo or stepper motor.


Blink! Blink! Blink!



Step 8: Software, Part 3: Pi IP Address on Nokia Display

As a grand finale, the Pi will send its IP address to a Nokia 5110
display. We will need to have the display plugged into its wired-up
socket. Additionally, the Pi will require a wireless adapter plugged into
a USB port and the appropriate procedures taken so that the Pi logs on to
the local network. And, of course, the Arduino needs to have the sketch
below loaded.

Boot up the Pi with the required equipment plugged in. After boot-up,
run a minicom session just as in the previous step, to initialize the
Pi's serial port. Finally, run the Bash script further down in this step.


Here is the Arduino sketch:

/* Nokia PCD8544 display, Serial port data in. */
/* In this particular case, the IP address. */
/* Run shell script that parses and sends IP addr. to /dev/ttyUSB0. */

#include <stdio.h>


#include "PCD8544.h"
/* Digital pins. */
// pin 7 - Serial clock out (SCLK)
// pin 6 - Serial data out (DIN)
// pin 5 - Data/Command select (D/C)
// pin 4 - LCD chip select (CS)
// pin 3 - LCD reset (RST)
PCD8544 nokia = PCD8544(7, 6, 5, 4, 3);

#define INTERVAL 500
#define BUFFSIZE 80 // Serial buffer.

char line1[40]="IP Address:"; // Header.
int DELAY=4000; // Interval between updates of display.


void setup(void) {

  nokia.init();
  nokia.command(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL);
  Serial.begin(9600);   // Start The Serial UART at 9600 Baud.
  
  nokia.clear();
  nokia.drawstring(0, 0, line1);
  nokia.display();
}

void loop(void)
{
 
  char serialdata[BUFFSIZE+3];
  int lf = 10;
 
 
  Serial.readBytesUntil(lf, serialdata, BUFFSIZE);
 
 
  nokia.drawstring(0, 1, serialdata);
 
  nokia.display();
 
// delay(INTERVAL);
}

You can download it here:
http://bash.deta.in/NokiaSerial.ino



Here is the Bash script:

#!/bin/bash
# inet.addr.sh
#  Echo the Pi's IP address to a serial port . . .
#+ . . . to which we happen to have attached an Arduino.
#  Run this script after Aduino is powered up with appropriate sketch
#+ (NokiaSerial.ino).

command=ifconfig
addr_hdr="addr:"
addr_prefix="inet 192"      # For Pidora. May change for other distro!
serial_port=/dev/ttyAMA0    # Direct connection to Pi rx and dx.

# ifconfig | grep "inet 192" | awk '{print $2}' | sed s/addr://
ipaddr=$(${command}| grep "$addr_prefix" |
awk '{print $2}' | sed s/$addr_hdr//)

echo $ipaddr > "$serial_port"   # Not necessary to put in loop or repeat.
# echo $ipaddr   # Debug.

exit $?


You can download the script here:
http://bash.deta.in/inet.addr.sh


Do you see the Pi's IP address on that little Nokia display?
Amazing, isn't it?

This particular application is handy if you set the Pi up as a headless server.
After the Pi boots up, it displays its IP address on the network,
and this indicates that everything is working okay. It also makes it easier
to do a remote log-on from another computer. As an exercise,
you might modify the Bash script to additionally display something about the
Pi's state on the other available lines of the Nokia display, such as
free space on the SD card (df command).

Step 9: Where Do We Go From Here?

Now that we know how to interface the Pi with an Arduino, it opens up
a number of possibilities.

  • Hook up a GPS module to the Arduino, and use the Pi as a front end to
  • parse and display the data, and maybe show the location on Google maps.
  •  
  • Hook up a geiger counter to the Arduino, and use the Pi as a front end
  • to graph the data.
  •  
  • Hook up the Arduino to control a remote IP-enabled security camera,
  • and have the Pi display and save what the camera sees.
  •  
  • Control a servo or stepper motor.