Activity Workshop
 

GPIO pins

GPIO (for General Purpose Input / Output) is the name given to the set of 26 vertical pins in the corner of the Pi next to the yellow video socket. They can be used for all sorts of things, but for our purposes, "output" is usually going to mean lighting up an LED, and "input" is probably going to mean detecting a switch being pressed, at least at the beginning. Of course you can control motors and searchlights and other high current stuff too, but then you'll need some buffering / amplifying / driving circuitry too because the Pi can only handle so much current going through it. The huge advantage of LEDs is that they can be driven directly from the Pi, so this is where we'll start.

Not all of these 26 pins are generic inputs and outputs. Some of them have a fixed function, such as +3.3V, +5V and ground. Some are carefully designated "Do Not Connect" meaning that they shouldn't be used for anything. Some of the others have cryptic names including MOSI, MISO, SDA0 and so on, and correspond to optional advanced features such as I2C (Inter-Integrated Circuit), CLK (Clock), UART (Universal Asynchronous Receiver/Transmitter), PWM (Pulse-Width Management) and SPI (Serial Peripheral Interface bus). But these pins can be configured to be GPIO pins if you want. Finally, there are six pins which are always GPIO pins.

So, you can have between six and maximum seventeen GPIO pins, of which any number can be inputs and any number outputs. That's quite some flexibility. If you need even more inputs, you can get complicated with the I2C pins and rig up additional GPIO connections through this bus. But we'll keep things simple.

There's a good overview of the functions of the pins (including those of the new models) at wikipedia.

How to connect?

The first problem is how to physically connect wires to these pins. They look like they'll accept an IDE ribbon cable, except for the fact that such a cable has 40 wires and not 26, so the plug is too big for the pi and will prevent you putting the case lid back on. There are special cables, sometimes called "jumper cables" or maybe "dupont cables", and you'll probably want female to male cables to connect the pi to a breadboard. But these are surprisingly expensive for what they are, and often come in large quantities with international shipping.

Another option is a dedicated "breakout board", but these again are expensive and overengineered, and take up more valuable breadboard space than necessary. Finally, you could decide to make your own connector, using a cannibalised IDE cable and some soldering, or getting your own ribbon cable and the appropriate plugs / headers / sockets. A local friendly electronics shop would be invaluable here.

Some cases for the pi already have slots for allowing ribbon cables through, or holes which you can pass wires through. It's a good idea to take advantage of these, to protect the pi and avoid waggling the GPIO pins too much.

Pin numbering

The easiest way to refer to the pins is with the board pin number, going from 1 to 26. If you hold the pi with the SD card slot on the left, and the yellow video socket at the top, then the block of GPIO pins are in the top-left corner of the board, as shown in the picture below. For a bigger overview, see the basics page.

picture of GPIO pins

Location of the 26 GPIO pins, starting with pin 1 on the bottom left (marked P1) and pin 2 above it

Pin 1 is the one nearest the SD card slot, the lower-leftmost of the pins as you look at them, and is marked with a little "P1" on the board. Then count the pins from bottom to top, and left to right, so the pin above pin 1 is pin 2, then pin 3 is next to pin 1 with pin 4 above it, the next pair is pins 5 and 6, and so on down to pins 25 and 26 closest to the yellow video socket. So the lower row starting with pin 1 are all odd, and the upper row next to the edge of the board are all even.

Unfortunately, there's a second way of numbering these pins, which is much lower level and requires knowledge of which pins on the Broadcom chip these GPIO pins are connected to. So any code which refers to these numbers becomes sensitive to which revision of the Pi you're using, and is liable to break when a new revision comes out. Plus, there's no logical order to the pin numbers any more, so you have to constantly cross-reference with some kind of lookup table. This second scheme is called the "BCM numbering", and uses a selection of numbers between 0 and 27.

Some people apparently have strong feelings about which scheme you should use, but you can decide for yourself. For me, the board numbering makes much more sense and results in more understandable, less fragile code, but Mike Cook confidently asserts in The Magpi that anyone who thinks that is "an idiot!".

Lighting an LED

So let's start right at the beginning. Without having to write any code, let's just light up an LED using the Pi's 3.3V and 0V power lines. The circuit for this couldn't be much simpler.

circuit diagram

I'm using a 4.7 kΩ resistor here (even though it's a bit too large) for two reasons - firstly it's what I had readily available, and secondly the resulting current of less than 1 mA is gentle on the pi and still sufficient to light up the LED and show that it works. Depending on what LED you've got you may need a smaller resistor than this in order to get the LED to light up properly.

Of course, this isn't really using the Raspberry pi, I could have done the same with a power supply or a little battery. So the next step is to control the LED using the GPIO pins.

Lighting an LED with python

I've chosen python here to program with, mainly because it's a nice level to program at and fun to use. And the interactive python prompt is excellent for just getting something working, and then it's a painless step to convert that "scratchpad" into a working program that you can call repeatedly and build upon.

So the first thing we need to do is make sure that python is installed (which it is by default in Raspbian), and also that the RPi.GPIO library is available too (which again, it is). So we're good to go. Now we just need to start python as root (using sudo python) because apparently anything which uses the GPIO pins requires root privileges. Odd but true.

Now we choose a GPIO pin to use, and rather arbitrarily I chose pin 11, also known as GPIO 17. So we connect a wire to this pin, and connect this into our circuit instead of the 3.3V pin. So if I set this pin to be an output and set it high, the LED will light, and if I set it to low, the LED should go off.

(Note I could have also connected 3.3V at the top and this GPIO pin at the bottom, it doesn't matter. The only difference is that then the LED would be on when the output is low and off when the output is high, just the opposite).

circuit diagram

So now in python, I have to load the GPIO library, choose which pin numbering to use, and then set my pin to be an output.

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.output(11, GPIO.LOW)

If you want to use the BCM numbers, then just use GPIO.setmode(GPIO.BCM) and use pin number 17 instead of 11.

Now, I can turn on the LED with GPIO.output(11, GPIO.HIGH) and turn it off again with GPIO.output(11, GPIO.LOW) - very simple!

Flashing

All the hard work is done. Now I just need to make a loop, and wait for a bit between turning the LED on and off:

import time
for i in range(20):
    GPIO.output(11, GPIO.HIGH)
    time.sleep(0.5)
    GPIO.output(11, GPIO.LOW)
    time.sleep(0.5)

Fairly straightforward - it loops 20 times, each time turning the LED on and then waiting half a second, turning it off again and waiting another half-second. Obviously you can change this value 0.5 to make it flash faster or slower.

Reading a wire contact

About the simplest input you can construct is just a pair of wires - the Raspberry pi can easily react to whether those two wires are touching or not. For this, we connect one wire to a GPIO pin, and configure it to be an input with an internal pull-up resistor. Then we connect the other wire to the ground pin (pin 6). If the wires aren't touching, the input is high (due to the pull-up resistor), and if the wires are touching, then the input is low (connected to ground).

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN, pull_up_down=GPIO.PUD_UP)

With a simple loop, you can print out to the screen whether the wires are touching or not:

import time
for i in range(20):
    if GPIO.input(11):
        print "not touching"
    else:
        print "touching!"
    time.sleep(1)

Polling in a loop

This provides an easy way of waiting until the wires are touched together. Effectively it's the same as constantly nagging the poor Raspberry pi with the question "are they touching yet? Are they touching yet? Are they touching yet?". As you can imagine, this isn't very efficient, and there's a lot of time spent just asking and answering.

while GPIO.input(11):
    time.sleep(0.1)

There's another disadvantage here too - maybe the wires just very briefly touch, inbetween your questions. Depending on the wait period between the questions, there's a chance you might miss the exact moment when the wires are touching. Make the wait period too long and you'll risk missing the very thing you're waiting for; make it too short and you'll just spend all your time in a tight loop asking whether the wires are touching or not and you won't have time to do anything else.

Fortunately, there are other ways of getting the same result a lot more efficiently and being kinder on the Pi. For these though, you'll need a relatively new version of the Rpi.GPIO python library, and some versions of Wheezy still have the older version 0.4.1a. So you'll need to upgrade your library to a newer version.

Welcome to linux's packaging magic - if you haven't seen this before, it's cool. The newer version of the library is already waiting for you in the special Raspberry Pi repository of Debian Wheezy, so all you need to do is update your package lists, and then upgrade the packages you want:

sudo aptitude update
sudo aptitude install python-rpi.gpio python3-rpi.gpio

You could also do a full sudo aptitude upgrade to upgrade everything at once, but that will take considerably longer.

Hey presto, the packages are automatically downloaded over the internet, saved, unpacked, updated and prepared for you. And if you now ask python:

import RPi.GPIO as GPIO
print GPIO.VERSION

It will now say 0.5.3a (at the time of writing) and the following methods will be available to you.

Waiting and then checking

A slightly more efficient way of reacting to this wire touch is to tell GPIO that you're waiting for a falling edge (in this case, the input will fall from high to low when the wires touch), and to then repeatedly ask if that has happened or not. The advantage here is that it doesn't matter if the wires only briefly touched inbetween calls, you can still tell whether it happened or not. So instead of "are they touching? are they touching? are they touching?", this detection method is more like "have they touched (since I last asked)? have they touched? have they touched?". It's still rather resource-intensive, but the risk of missing events is reduced.

GPIO.add_event_detect(11, GPIO.FALLING)
while not GPIO.event_detected(11):
    time.sleep(0.1)

Here you can increase the wait time without risking missing something, but then you will increase the latency (time to react), and make the latency more variable.

Blocking the thread

Another new way is to just not do anything until the condition is reached. This apparently doesn't use much effort from the Pi, and is certainly a short piece of code, but the disadvantage is that you can only wait for one channel (you can't wait for either this touch or that touch with this method).

GPIO.wait_for_edge(11, GPIO.FALLING)

Registering a callback

Finally, a powerful way to ask to be informed, rather than waiting and checking. So instead of "are they touching? are they touching? are they touching?", this is more like "tell me when they touch". Then I can do other things, or nothing at all, and a method (or methods) which I define, will be called when the specified thing (or things) happen.

def somethingTouched(channel):
    print "something touched on channel", channel
 
 GPIO.add_event_detect(11, GPIO.FALLING, callback=somethingTouched, bouncetime=300)

In this case, I just specify that this method should be called every time a falling edge on pin 11 is detected, and I use a so-called "bouncetime" of 300ms to ignore fast-flickering changes caused by the wires coming into contact.

There's lots more about this, very well explained, at the Rpi.GPIO wiki. Unfortunately one thing which it doesn't appear to be able to do is to register a callback on a falling edge to methodA and one for a rising edge to methodB, for the same input pin. The best you can do is register a callback for either edge to the same method, but then you don't know which edge was triggered. You can test the pin value, but that no longer tells you whether the value is consistent with the triggered edge or not.