Building a Home Security System with Raspberry Pi
上QQ阅读APP看书,第一时间看更新

Getting acquainted with the GPIO

Before we embark on connecting lots of things to our Pi board, it might be a good idea to just get acquainted with the GPIO through a couple of simple projects that will help us understand how to interact with the digital I/O pins using shell scripts.

Let there be light

This simple little project shows how to connect a GPIO output to an LED, and switch it on and off using shell commands.

The following diagram shows how to connect up the circuit using a breadboard:

Note

The pretty diagram that you just saw was produced using a free software tool from fritzing, which is an open-source hardware initiative to make electronics accessible as creative material for anyone. Download it from fritzing.org.

The LED anode (the positive side) is connected to the D0 digital I/O (pin 11 of the connector or GPIO17). When this pin is switched on, it will provide a 3.3V supply to the LED.

The LED is connected to the Ground pin via a 220R resistor on the cathode (negative side). The resistor limits the voltage to the LED and the current through it, otherwise it would burn out, as you can only supply up to about 2V to LEDs. With a current of around 10mA being drawn by the LED on a 3.3V supply, a 220R resistor works well to protect both it and the GPIO.

Here's the circuit diagram for it:

Note

Calculating LED Resistor Values…

While this book is not really a course on electronics theory, I thought it would be handy to show you how to work out the resistor values for LEDs using Ohms Law, as we'll be covering this again later.

As I mentioned, a typical LED will drop about 2V across it, although this varies according to color and type. This is called the forward voltage of the device or VLED.

The current required by an LED is around 10mA, again depending on its specification. We'll call this current flowing through the LED, ILED.

Essentially, the voltage across the resistor will be the supply voltage minus the voltage drop across the LED (for example,.2V). So, if we have a 12V supply (VS), the voltage across the resistor will be 10V (VS – VLED).

According to Ohms Law, the resistance R is the voltage across it divided by the current flowing through it: R = V / I. As we require 10mA flowing through it, with a voltage of 10V across it, the resistance required is 10V divided by 0.01A, which is 1,000 ohms or 1K.

In summary, R = (VS-VLED) / ILED.

Now, to turn the LED on and off: the GPIO pins are actually mapped as devices in the Linux file system, so using shell commands is easy, although there are many libraries available out there that allow you to control the GPIO using Python, for example. However, so that you don't have to learn a new language, we're going to do everything using shell commands.

The D0 pin that we are connected to is actually GPIO17 as far as the Raspberry Pi is concerned (take a look at the previous diagram for reference). The first thing we need to do is create file access to this GPIO pin. We do this with the following command:

$ sudo echo 17 > /sys/class/gpio/export

We then have to set the pin's direction to out:

$ sudo echo out > /sys/class/gpio/gpio17/direction

Next we can switch the pin on to turn the LED on:

$ sudo echo 1 > /sys/class/gpio/gpio17/value

To switch the LED off, we use this command:

$ sudo echo 0 > /sys/class/gpio/gpio17/value

Once we've finished with a GPIO port we can remove its file access:

$ sudo echo 17 > /sys/class/gpio/unexport

Getting flashy…

We can put these commands together in a single Bash script to create a flashing LED. To create the flashy script, create a new text file in nano or some other text editor. Or, as I usually do (don't forget that I'm quite lazy), create the text file on your laptop, and then copy it to the remote Pi using WinSCP (although, read my note in the box that follows if you want to prevent some heartache).

The following is the code listing for led-flash.sh:

#!/bin/bash
sudo echo 17 > /sys/class/gpio/export
sudo echo out > /sys/class/gpio/gpio17/direction
# loop forever
while true
do
  sudo echo 1 > /sys/class/gpio/gpio17/value
  sleep 0.5
  sudo echo 0 > /sys/class/gpio/gpio17/value
  sleep 0.5
done

Note

If you use Windows to create your files, remember to save your files with the end-of-line format being Linux (a single 0x0a or Line Feed character) rather than Windows (0x0a + 0x0d or Line Feed + Carriage Return characters), otherwise you might find that your Bash script does not run properly on the Raspberry Pi. Text editors on Windows, such as the excellent Notepad++, will convert your script line ends for you.

Run the script by calling led-flash.sh (assuming that's what you've called it). If you're in the same directory as the script, this can be done by typing the following:

$ sudo bash ./led-flash.sh

Since this is an endless loop with the LED flashing on and off at half second intervals, you'll need to break out of it by using CTRL + C to stop the script.

Don't forget to remove the GPIO pin from file access by using the following command:

$ sudo echo 17 > /sys/class/gpio/unexport

Otherwise, you'll see the error, echo: write error: Device or resource busy, if you re-run the script, as the first line tries to set GPIO17 for file access again.

Adding a switch

In this project, we'll see how to connect a switch to a GPIO input and write a shell script to read the state of the switch—that is, whether it's switched on or off.

Connect a switch to your Pi's GPIO27 pin, as shown in the following diagram:

Pulling yourself together

A really important thing to realize about GPIO inputs is that they are in what's called a floating state. This means that, as far as the operating system is concerned, it doesn't know what its reference state is unless it is presented with a known voltage.

This is where our resistor comes into play—it pulls up the GPIO pin to a known voltage of 3.3V, which gives it a default state of HIGH (or binary 1).

When the pushbutton switch is pressed, this takes the GPIO pin to 0V, which is a LOW state (or binary 0).

Here's the circuit diagram for our GPIO switch:

The detection script

Now that we've connected the switch to our Raspberry Pi, we need to write a little script that will detect when the switch has been pushed.

It's similar to the previous LED script shown, but this time we'll set the GPIO pin as an input and read its logic level.

In this project, we've connected our switch to D2, which is GPIO27 (again, refer to the earlier GPIO pin-out diagram). As before, we need to create file access for the pin by entering the following command:

$ sudo echo 27 > /sys/class/gpio/export

And now, set its direction to in:

$ sudo echo in > /sys/class/gpio/gpio27/direction

We're now ready to read its value, and we can do this with the following command:

$ sudo cat /sys/class/gpio/gpio17/value

You'll notice that it will have returned 1, or a high state. This is because of the pull-up resistor we were talking about earlier. This means that its default state, when the switch isn't pushed, is high.

When the switch is pushed, the value should be read as 0 or low. If you have more than two hands, you can try this by pushing the button and re-running the command. Or, we can just create a script to poll the switch state.

The code listing for poll-switch.sh is as follows:

#!/bin/bash
sudo echo 27 > /sys/class/gpio/export
sudo echo in > /sys/class/gpio/gpio27/direction

# loop forever
while true
do
  # read the switch state
  SWITCH=$(sudo cat /sys/class/gpio/gpio27/value)

  if [ $SWITCH == 1 ]; then
    #switch not pushed so wait for a second
    sleep 1
  else
    #switch was pushed
    echo "You've pushed my button"
  fi
done

When you run the script and then push the button, you should see You've pushed my button scrolling up the console screen until you stop pressing it.

Don't forget that, once we've finished with the GPIO port, we can remove its file access:

$ sudo echo 27 > /sys/class/gpio/unexport

We've now seen how to easily read a switch input, and the same circuit and script can be used to read other sensors, such as door contact switches, reed switches, or anything else that has an on and off state.