Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / IoT / Raspberry-Pi

Raspberry Pi - [Episode 2] In, Out, that's what it's all about.

4.82/5 (8 votes)
5 Dec 2013CPOL10 min read 29.5K  
Real World Interfacing to the Raspberry-Pi using a Gertboard.
Raspberry Pi Logo

Introduction

In my first Raspberry Pi article, I gave a quick look at the board, and showed how easy it was to load up an OS and kick the board into life, connect to the internet and browse to The CodeProject.

In this article, I hope to demonstrate how to hook up the board to the real world. Unlike the Arduino boards, there are no easy input output digital in/out or analog pins, just a simple general purpose input output (GPIO) set of pins.

Well, much to my happiness, there is a board for that!

Bring on the Gertboard!

The Gertboard is an interface extender board that connects to the Raspberry Pi via the GPIO pins using a ribbon cable. The image below is what the Gerboard (left) hooked up to RasPi (right) should look like when I'm finished. (photo courtesy of Element14);

Image 2

I purchased mine through Element 14 (Part Code 211-5337). Just like the original RasPi release, there was a back order when I ordered mine, so just had to wait.

The kit I ordered was an unassembled unit and I don't mind dusting off the soldering iron. That was until I saw the kit when it arrived and discovered absolutely tiny surface mount components! In total there were 33 individual bags of components, IC's and various headers and jumpers and of course the 1x Gertboard PCB.

On the Farnell website, you can now order fully assembled boards which will take away some of the pain and trouble for some. (Part Code 225-0034).

Farnell now have a whole section dedicated to the Raspberry Pi, with various boards, cases, cameras and other accessories.

Building the board

After opening the package that arrived and spreading everything out. I noticed that there were no assembly instructions. So hadn't a clue where each component should go. A quick search online and found the assembly manual and user manual linked from the RasPi website back to Element14;

The photo below shows everything spread out still in its packaging before the mammoth task begins:

Image 3

After downloading the assembly manual and opening up, it was nice to see in the intro a guide to soldering the surface mount devices. I had never attempted to solder these before, so was a little bit apprehensive given how small they were. As an example, there were 2 x 0 Ohm SMD resistors in the kit. These are 2mm x 1.2mm. In the photo above you can see the SMD component strips at the bottom left in the white bags.

I also had treated myself to a new soldering station. I did have an old 25W basic soldering iron, but thought it was about time to leave the dark ages. Well almost the dark ages, at least I didn't have to heat the iron up on a fire!

So it was time to get down to business. First thing I did was laid out the bags of SMD components. These only had the Farnell/Element14 part number on them and no content description. It is worth going onto the website and look up each component and write its description on the bag. The SMDs, whether capacitors or resistors look the same, so you don't want to mix them up. Also, when assembling the board, stick to one component type at a time, again so as you don't mix them up. Once completed with that component type, put away the bag of any spares and move to the next. It is advisable to start with the smallest component size, and then work up to the larger things like IC holders and Fuse holders.

Take your time, follow the instructions. All going well, everything should work out just fine!

How did it go then?

It went not too bad. Trying to open the SMD component wrappers was a bit of a pain, and the very first packet resulted in the capacitors being spread all over the place, but managed to find them all. I managed to put one of the resistor bridges into the wrong holes, but noticed when I had tacked the first leg.Then I put an IC holder in the wrong way round, but only had soldered 2 corners, so managed to recover the situation without much of a fuss.

In total it took me 2 hours 8 minutes to assemble the board. That included having to go and answer the doorbell at one point! Below, is the finished article;

Image 4

Let's Do The Time Lapse!

On the RasPi website, there was a time lapse video by Mike Cook of him building his Gertboard. I had never done a time lapse video before, so thought I would also have a go at this. This would also be a good excuse to put my GoPro HD Hero 2 to use!

The video below was created by first shooting a time lapse sequence of the build at 1 Frame / 5 Seconds @ 3200 x 2400 resolution, then using the GoPro Cineform Studio convert this to 1280x720 HD Output at 10 Frames per second.

http://www.youtube.com/watch?v=hNPQao6wops

As you can see in the beginning of the video, the use of tweezers was definitely required to tackle the SMD components. They were a nightmare! I also had the pleasure of my eldest, Maya (8), joining me later to do a bit of supervising. Talk about (at least) twenty questions...

What is on the board?

The Gertboard has various functions. These are all broken out to various headers, allowing you to use them as you see fit. The main functions on the board are;

  • 2 x Digital to Analog converters (8-bit)
  • 2 x Analog to Digital converters (10-bit)
  • 12 x LED indicators
  • 3 x pushbuttons
  • 6 x Open collector outputs
  • 12 x Digital IO
  • 1 x Motor Controller (bidirectional up to 18v @ 2Amps)

There are also 3 x Pushbuttons strapped to 3 of the IOs and also 12 x LEDs strapped to the IO.

Another noticeable aspect of the Gertboard, is the fact that it also has a ATMega328 microcontroller built onto the board, with all pins broken out to a set of headers. This effectively means there is an Arduino also on the board.

Testing the board

NOTE: Version 1 (Self Assembly) and Version 2 (Pre-Assembled) are slightly different in terms of connectors and jumpers, so you do need to refer to the correct guides for your own board.

In the user manual, there are links to download sample code from Element14 website, but there are a whole bunch of other things out there on the Gertboard. A good place to start is in this forum; http://www.raspberrypi.org/phpBB3/viewforum.php?f=42

Having downloaded and installed the latest version of Wheezy (as per my Episode 1 article), next need to get hold of the suitable python test code.

From the command console on the Raspi you can do the following;

wget http://raspi.tv/download/GB_Python.zip
unzip GB_Python.zip
cd GB_Python
nano README.txt

In the readme file, there are further instructions and links to code and demos videos on Youtube of the running code.

For the purpose of this article, I will just test a couple of these.

LED Test

Running the command;

sudo python leds-rg.py

results in the program printing out which jumpers you should connect for the test, and then waits for you to hit 'Enter'. This will run the LEDs through a sequence 1->12->1 etc.

Unfortunately, for whatever reason only the LEDs 1 to 8 would work on my board. I swapped the jumpers over on Pins B1 and B12 to confirm the B12 is trying to at least drive a signal, and this was confirmed by LED1 lighting up when it should as 12. The next thing I went to do was to swap over 2 of the ICs, just in case one of these was fried. I went and pulled the IC (U5) which drives the leds 9/10/11/12, and this is when I noticed I didn't have the jumper links installed which determine if this is Input or Output, popping these jumpers in, reinserting the IC and rerunning the test confirmed that the LEDs were now all sequencing correctly. Panic over!

RasPi.TV published a video of this test on Youtube here: http://www.youtube.com/watch?v=fFHEi1ur7yg (Note, in video you will only see that they have jumpered only the 1st 10 LEDs instead of the full 12).

Button Test

Running the command;

sudo python buttons-rg.py

results in the program again printing out the instructions of which jumpers to insert and then waits for your to press 'Enter'. Once you press the key, the program outputs the binary state of the buttons e.g. '111' and illuminates the LEDs, when you press the buttons, the binary state and LEDs change as you would expect.

Reference test on RasPi.TV : http://www.youtube.com/watch?v=DwlI2Fr1AXg

Code Behind

Often the best way to learn and understand what is going on is simply to open up the someone else code and take a peek. The code below is the LED test from leds-rg.py;

Python
#!/usr/bin/env python2.7
# Python 2.7 version by Alex Eames of http://RasPi.TV 
# functionally equivalent to the Gertboard leds test by 
# Gert Jan van Loo & Myra VanInwegen. Use at your own risk
# I'm pretty sure the code is harmless, but check it yourself.
 
import RPi.GPIO as GPIO
from time import sleep
import sys
board_type = sys.argv[-1]
 
if GPIO.RPI_REVISION == 1:      # check Pi Revision to set port 21/27 correctly
    # define ports list for Revision 1 Pi
    ports = [25, 24, 23, 22, 21, 18, 17, 11, 10, 9, 8, 7]
else:
    # define ports list all others
    ports = [25, 24, 23, 22, 27, 18, 17, 11, 10, 9, 8, 7]   
ports_rev = ports[:]                            # make a copy of ports list
ports_rev.reverse()                             # and reverse it as we need both
 
GPIO.setmode(GPIO.BCM)                                  # initialise RPi.GPIO
 
for port_num in ports:
    GPIO.setup(port_num, GPIO.OUT)                  # set up ports for output
 
def led_drive(reps, multiple, direction):           # define function to drive
    for i in range(reps):                      # repetitions, single or multiple
        for port_num in direction:                  # and direction
            GPIO.output(port_num, 1)                # switch on an led
            sleep(0.11)                             # wait for ~0.11 seconds
            if not multiple:                        # if we're not leaving it on
                GPIO.output(port_num, 0)            # switch it off again
 
# Print Wiring Instructions appropriate to the board
if board_type == "m":
    print "These are the connections for the Multiface LEDs test:"                
    print "BUFFER DIRECTION SETTINGS, jumpers on all OUT positions (1-12)"
    print "GPIO 25 --- BUFFERS 1 \nGPIO 24 --- BUFFERS 2"
    print "GPIO 23 --- BUFFERS 3 \nGPIO 22 --- BUFFERS 4"
    print "GPIO 21 --- BUFFERS 5 \nGPIO 18 --- BUFFERS 6"
    print "GPIO 17 --- BUFFERS 7 \nGPIO 11 --- BUFFERS 8"
    print "GPIO 10 --- BUFFERS 9 \nGPIO 9 --- BUFFERS 10"
    print "GPIO 8 --- BUFFERS 11 \nGPIO 7 --- BUFFERS 12"
 
else:
    print "These are the connections for the Gertboard LEDs test:"                
    print "jumpers in every out location (U3-out-B1, U3-out-B2, etc)"
    print "GP25 in J2 --- B1 in J3 \nGP24 in J2 --- B2 in J3"
    print "GP23 in J2 --- B3 in J3 \nGP22 in J2 --- B4 in J3"
    print "GP21 in J2 --- B5 in J3 \nGP18 in J2 --- B6 in J3"
    print "GP17 in J2 --- B7 in J3 \nGP11 in J2 --- B8 in J3"
    print "GP10 in J2 --- B9 in J3 \nGP9 in J2 --- B10 in J3"
    print "GP8 in J2 --- B11 in J3 \nGP7 in J2 --- B12 in J3"
    print "(If you don't have enough straps and jumpers you can install"
    print "just a few of them, then run again later with the next batch.)"
 
raw_input("When ready hit enter.\n")
 
try:                                        # Call the led driver function
    led_drive(3, 0, ports)                  # for each required pattern
    led_drive(1, 0, ports_rev)
        # run this once, switching off led before next one comes on, forwards
    led_drive(1, 0, ports)                  
        # run once, switch led off before next one, reverse direction
    led_drive(1, 0, ports_rev)
        # (1, 1, ports) = run once, leaving each led on, forward direction
    led_drive(1, 1, ports)
    led_drive(1, 0, ports)        
    led_drive(1, 1, ports)
    led_drive(1, 0, ports)
except KeyboardInterrupt:                   # trap a CTRL+C keyboard interrupt
    GPIO.cleanup()                          # clean up GPIO ports on CTRL+C
GPIO.cleanup()                              # clean up GPIO ports on normal exit

As you can see it is fairly straight forward and commented to help understand what is going on without any more description. The code below is from the button test, this will allow use to understand how we read back onto display the state of the buttons (buttons-rg.py);

Python
#!/usr/bin/env python2.7
# Python 2.7 version by Alex Eames of http://RasPi.TV 
# functionally equivalent to the Gertboard buttons test by 
# Gert Jan van Loo & Myra VanInwegen
# Use at your own risk - I'm pretty sure the code is harmless, 
# but check it yourself.
 
import RPi.GPIO as GPIO
import sys
board_type = sys.argv[-1]
 
GPIO.setmode(GPIO.BCM)                  # initialise RPi.GPIO
for i in range(23,26):                  # set up ports 23-25 
    GPIO.setup(i, GPIO.IN, pull_up_down=GPIO.PUD_UP)  # as inputs pull-ups high      
 
# Print  Instructions appropriate for the selected board
if board_type == "m":
    print "These are the connections for the Multiface buttons test:" 
    print "GPIO 25 --- 1 in BUFFERS"
    print "GPIO 24 --- 2 in BUFFERS"
    print "GPIO 23 --- 3 in BUFFERS"
    print "Optionally, if you want the LEDs to reflect button state do the following:"
    print "jumper on BUFFER DIRECTION SETTINGS, OUT 1"
    print "jumper on BUFFER DIRECTION SETTINGS, OUT 2"
    print "jumper on BUFFER DIRECTION SETTINGS, OUT 3"
 
else:
    print "These are the connections for the Gertboard buttons test:"
    print "GP25 in J2 --- B1 in J3"
    print "GP24 in J2 --- B2 in J3"
    print "GP23 in J2 --- B3 in J3"
    print "Optionally, if you want the LEDs to reflect button state do the following:"
    print "jumper on U3-out-B1"
    print "jumper on U3-out-B2"
    print "jumper on U3-out-B3"
 
raw_input("When ready hit enter.\n")
 
button_press = 0        # set intial values for variables
previous_status = ''
 
try:
    while button_press < 20:             # read inputs until 19 changes are made
        status_list = [GPIO.input(25), GPIO.input(24), GPIO.input(23)]
        for i in range(0,3):
            if status_list[i]:
                status_list[i] = "1"
            else:
                status_list[i] = "0"
        # dump current status values in a variable
        current_status = ''.join((status_list[0],status_list[1],status_list[2]))
        # if that variable not same as last time 
        if current_status != previous_status:
            print current_status                # print the results 
            # update status variable for next comparison
            previous_status = current_status
            button_press += 1                   # increment button_press counter
 
except KeyboardInterrupt:          # trap a CTRL+C keyboard interrupt
    GPIO.cleanup()                 # resets all GPIO ports used by this program
GPIO.cleanup()                     # on exit, reset all GPIO ports 

Temperature Test with DS18B20 1-Wire Temperature Sensor

I have a project in mind in which I want to monitor my home central heating, hot water, solar thermal and solar PV systems. To allow me to monitor the temperature I purchased a bunch of 'One Wire' temperature sensors. These were pre-wired into a waterproof probe and on a 1 metre lead. These sensor are Dallas Semiconductos DS18B20 and each sensors has a unique ID allowing them to be bus wired and polled.

The image below is my test setup, from left to right, RasPi, Gertboard, breadboard, Arduino (it just happens to be attached to the breadboard, but is not used in this article). You can see the tip of the sensor at the middle bottom of the image.

Image 5

Rather than re-invent the wheel for a test, a quick search on Google pulled up this excellent tutorial over at Adafruit: Adafruit's Raspberry Pi Lesson 11. DS18B20 Temperature Sensing.

After following the example in the tutorial, as you can see below I successfully managed to read the device from the console and from a python script.

Image 6

Image 7

In the Python output above, you can see the temperature in 'C and 'F e.g. (33.5, 92.3)

Temperature Test Code

The slightly modified version of the example code from the tutorial is shown below;

Python
import OS
import glob
import time
import subprocess

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

base_dir = 'sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'

print "Device Folder: " + device_folder
print "Device File : + device_file

def read_temp_raw():
    catdata = subprocess.Popen(['cat', device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = catdata.communicate()
    out_decode = out.decode('utf-8')
    lines = out_decode.split('\n')
    return lines

def read_temp():
    print "Raw device data :"
    lines = read_temp_raw()
    print lines[0]
    print lines[1]
    print lines[2]

    while (lines[0].find('YES') > 0):
        lines = read_temp_raw()
        equal_pos = lines[1].find('t=')
        if equal_pos != -1:
            temp_string = lines[1][equal_pos+2:]
            temp_c = float(temp_string) / 1000.0
            temp_f = temp_c * 9.0 / 5.0 + 32.0
            return temp_c, temp_f

while True:
    print "Current Temperature ('C, 'F):"
    print(read_remp())
    print ""
    print "Sleeping.....(1 Second)."
    time.sleep(1)

As you can see in the code above, it basically is parsing strings to extract the temperature from the line 't='. This is scaled up so need to be divided by 1000 to get the centigrade reading. The code will only currently work for a single bussed sensor, it will need to be modified to read multiple sensors.

What Next?

Well I am pleased with what has come together so far.

Next up, I will look at scaling this up to my multi sensors for temperature and optical (want to look at the burner viewing window to see when the heat demand is running). Then look at integrating my solar systems etc.

Demanding on how all that goes, it might make the subject of a future article.

Thanks for getting this far......see you in the next episode maybe.

Reference Links

History

5th December 2013 - Article first published.
 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)