User Tools

Site Tools


interrupts

Using RaspberryPi with interrupts

Very often people talk about “turn something on/off” with a RaspberryPi, but you can only very rarely find something useful about reading inputs from other systems. So whenever you want to read an input a lot solutions in the web explain ways how to read a GPIO-pin of the RaspberryPi by using a loop (like while (true)), always reading one single pin every few milliseconds and if the state suddenly changes, an event is triggered.

But by using interrupts, there are a lot more possibilities and nicer code as I would like to explain here in the next stepts. I used the python GPIO-lib to activate and react on interrupts on one pin in a short python script.

I also install the wiringPi lib, because that makes live way easier to verify and test on port-pins of the Pi, but the lib is not neccessary for running interrupts on the RaspberryPi.

Prerequisites

First install wiringPi, it's not neccessary for the usage of interrupts, but offers a very good set of functions for further development and is also a fine tool for finding errors. It has to be installed from github within having better all other things beeing up to date too:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-core

wiringPi

If that's done, grab or even better clone the newest build of the lib to the RaspberryPi:

git clone git://git.drogon.net/wiringPi
cd wiringPi
git pull origin

This last command will fetch an updated version (if not just cloned) then the build script below could be run.

Next steps are easy, too and it's built:

./build

Testing the installtion is easily done by firing a version request:

pi@RaspberryPi ~ $ gpio -v
gpio version: 2.13
Copyright (c) 2012-2013 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty

This Raspberry Pi is a revision 2 board.

If that is already successful, read all I/Os and the result might somehow look like this:

pi@RaspberryPi ~ $ gpio readall
+----------+-Rev2-+------+--------+------+-------+
| wiringPi | GPIO | Phys | Name   | Mode | Value |
+----------+------+------+--------+------+-------+
|      0   |  17  |  11  | GPIO 0 | OUT  | Low   |
|      1   |  18  |  12  | GPIO 1 | OUT  | Low   |
|      2   |  27  |  13  | GPIO 2 | OUT  | Low   |
|      3   |  22  |  15  | GPIO 3 | IN   | Low   |
|      4   |  23  |  16  | GPIO 4 | IN   | Low   |
|      5   |  24  |  18  | GPIO 5 | IN   | Low   |
|      6   |  25  |  22  | GPIO 6 | IN   | High  |
|      7   |   4  |   7  | GPIO 7 | IN   | High  |
|      8   |   2  |   3  | SDA    | ALT0 | High  |
|      9   |   3  |   5  | SCL    | ALT0 | High  |
|     10   |   8  |  24  | CE0    | IN   | High  |
|     11   |   7  |  26  | CE1    | IN   | High  |
|     12   |  10  |  19  | MOSI   | IN   | Low   |
|     13   |   9  |  21  | MISO   | IN   | Low   |
|     14   |  11  |  23  | SCLK   | IN   | Low   |
|     15   |  14  |   8  | TxD    | ALT0 | High  |
|     16   |  15  |  10  | RxD    | ALT0 | High  |
|     17   |  28  |   3  | GPIO 8 | IN   | Low   |
|     18   |  29  |   4  | GPIO 9 | IN   | Low   |
|     19   |  30  |   5  | GPIO10 | IN   | Low   |
|     20   |  31  |   6  | GPIO11 | IN   | Low   |
+----------+------+------+--------+------+-------+

Python GPIO

Assuming python is already installed; python has to learn how to modify GPIOs to e.g. set the internal pull-up or pull-down resistors, which are going to be used for the later interrupt handling, so the following package has to be installed:

sudo apt-get install python-rpi.gpio



Describing the Elements

When all prerequisites are fulfilled a simple python script can set a pin of my choice to either low or high by activating the internal pull-up (or pull-down) resistors. In the following example GPIO pin 25 is chosen (remind: GPIO pin 25 equals pin 22 physically on the plug and equals the official name GPIO 6!), it's turned into direction IN and the pull-up resistor is activated:

#!/usr/bin/python
import RPi.GPIO as GPIO
 
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP)

The intention here is to permanently pull the pin to a high level, so whenever something will turn this pin to ground, the interrupt shall be triggert at a later point.

Probably also the mode should be explained, here GPIO.BCM is used. The GPIO.BCM option means that the setup is referring to the pins by the “Broadcom SOC channel” number, these are the numbers of the “GPIO” and not the physical PIN numbers.

The alternative GPIO.BOARD option specifies that the setup is referring to the pins by the number of the pin of the plug - i.e the numbers printed on the board (e.g. P1).

In a next step, a function has to be created, which is triggered, whenever an interrupt is released and in addition an eventhandler has to be activated, that is watching for falling signals:

# Interrupt Routine, beeing called, when interrupt happens
def interrupt_routine(callback):
    print "Interrupt triggered"
    #put your code here
 
 
# Init Interrupt-Callback-Function
GPIO.add_event_detect(25, GPIO.FALLING, callback=interrupt_routine)

The observed pin 25 is currently on high, as the internal pull-up resistor is activated. Whenever this pin is turned to ground there is a falling slope from high to low. Whenever this happens, the interrupt routine “interrupt_routine” is called.

If the grounding is removed again, the pullup resistors pulls the pin back to high level and nothing happens until the pins is pulled down to ground again.

Simple Testscript

All elements together create this simple testscript, which is pretty short and working like a charm:

interrupt-test.py
#!/usr/bin/python
import RPi.GPIO as GPIO
import sys
import time
 
# Init GPIOs
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP)
 
# Interrupt routine, beeing called, when interrupt happens
def interrupt_routine(callback):
    print "Interrupt triggered!"
    #Add your own code here
 
 
# Init Interrupt-Callback-Function --> register the interrupt trigger
GPIO.add_event_detect(25, GPIO.FALLING, callback=interrupt_routine)
 
# Simple init to abort program later with Ctrl+C in an exception
runProgram = True
 
#Run usual script
while runProgram:
    try:
	print time.strftime("%d.%m.%Y %H:%M:%S"), "Just doing nothing, awaiting an interrupt..."
 
	#Put your main program's code in here
 
	# Sleeping 5 seconds top make it readable
	time.sleep(5)
    except:
	print "Exception thrown -> Abort"
	runProgram = False
 
 
# Final cleanup
GPIO.cleanup()

While the simple testscript is running, just pull pin 25 to ground and see the interrupt beeing triggert in between of the usal main programs execution:

The output will look like this:

pi@RaspberryPi ~ $ sudo python interrupttest.py 
14.12.2014 16:44:11 Just doing nothing, awaiting an interrupt...
14.12.2014 16:44:16 Just doing nothing, awaiting an interrupt...
14.12.2014 16:44:21 Just doing nothing, awaiting an interrupt...
14.12.2014 16:44:26 Just doing nothing, awaiting an interrupt...
Interrupt triggered!
14.12.2014 16:44:31 Just doing nothing, awaiting an interrupt...
interrupts.txt · Last modified: 04.01.2015 18:04 by andreas