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.
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
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:
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 | +----------+------+------+--------+------+-------+
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
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.
All elements together create this simple testscript, which is pretty short and working like a charm:
#!/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...