The GPIO pins on a Raspberry Pi are a great way to interface physical devices like buttons and LEDs with the little Linux processor. If you’re a Python developer, there’s a sweet library called RPi.GPIO that handles interfacing with the pins. In just three lines of code, you can get an LED blinking on one of the GPIO pins.
Not sure if Raspberry Pi is right for you? Make:’s interactive Board Guide lets you dial into the field to find the best board for your needs.
Installation
The newest version of Raspbian has the RPi.GPIO library pre-installed. You’ll probably need to update your library, so using the command line, run:
sudo python
import RPi.GPIO as GPIO
GPIO.VERSION
The current version of RPi.GPIO is 0.5.4 If you need to update to a newer version, run:
sudo apt-get update
sudo apt-get upgrade
If you don’t have the RPi.GPIO library because you’re using an older version of Raspbian, there are great instructions on the Raspberry Pi Spy website on installing the package from scratch.
Using the RPi.GPIO Library
Now that you’ve got the package installed and updated, let’s take a look at some of the functions that come with it. Open the Leafpad text editor and save your sketch as “myInputSketch.py”. From this point forward, we’ll execute this script using the command line:
sudo python myInputSketch.py
All of the following code can be added to this same file. Remember to save before you run the above command. To exit the sketch and make changes, press Ctrl+C.
To add the GPIO library to a Python sketch, you must first import it:
import RPi.GPIO as GPIO
Then we need to declare the type of numbering system we’re going to use for our pins:
#set up GPIO using BCM numbering
GPIO.setmode(GPIO.BCM)
#setup GPIO using Board numbering
GPIO.setmode(GPIO.BOARD)
The main difference between these modes is that the BOARD option uses the pins exactly as they are laid out on the Pi. No matter what revision you’re using, these will always be the same. The BCM option uses the Broadcom SoC numbering, which differs between version 1 and version 2 of the Pi.
from Meltwater’s Raspberry Pi Hardware
In the image above, you’ll see that Pin 5 is GPIO01/03. This means that a v.1 Pi is GPIO 01, while a v.2 Pi is GPIO 03. The BCM numbering is what I’ll be using for the rest of this entry, because it’s universal across other programming languages.
Building a Circuit
Now we’re going to get into inputs and outputs. In the circuit shown below, two momentary switches are wired to GPIO pins 23 and 24 (pins 16 and 18 on the board). The switch on pin 23 is tied to 3.3V, while the switch on pin 24 is tied to ground. The reason for this is that the Raspberry Pi has internal pull-up and pull-down resistors that can be specified when the pin declarations are made.
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_UP)
This will enable a pull-down resistor on pin 23, and a pull-up resistor on pin 24. Now, let’s check to see if we can read them. The Pi is looking for a high voltage on Pin 23 and a low voltage on Pin 24. We’ll also need to put these inside of a loop, so that it is constantly checking the pin voltage. The code so far looks like this:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)
while True:
if(GPIO.input(23) ==1):
print(“Button 1 pressed”)
if(GPIO.input(24) == 0):
print(“Button 2 pressed”)
GPIO.cleanup()
The indents in Python are important when using loops, so be sure to include them. You also must run your script as “sudo” to access the GPIO pins. The GPIO.cleanup() command at the end is necessary to reset the status of any GPIO pins when you exit the program. If you don’t use this, then the GPIO pins will remain at whatever state they were last set to.
The Problem With Polling
This code works, but prints a line for each frame that the button is pressed. This is extremely inconvenient if you want to use that button to trigger an action or command only one time. Luckily, the GPIO library has built in a rising-edge and falling-edge function. A rising-edge is defined by the time the pin changes from low to high, but it only detects the change. Similarly, the falling-edge is the moment the pin changes from high to low. Using this definition, let’s change our code slightly:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)
while True:
GPIO.wait_for_edge(23, GPIO.RISING)
print(“Button 1 Pressed”)
GPIO.wait_for_edge(23, GPIO.FALLING)
print(“Button 1 Released”)
GPIO.wait_for_edge(24, GPIO.FALLING)
print(“Button 2 Pressed”)
GPIO.wait_for_edge(24, GPIO.RISING)
print(“Button 2 Released”)
GPIO.cleanup()
When you run this code, notice how the statement only runs after the edge detection occurs. This is because Python is waiting for this specific edge to occur before proceeding with the rest of the code. What happens if you try to press button 2 before you let go of button 1? What happens if you try to press button 1 twice without pressing button 2? Because the code is written sequentially, the edges must occur in exactly the order written.
Edge Detection is great if you need to wait for an input before continuing with the rest of the code. However, if you need to trigger a function using an input device, then events and callback functions are the best way to do that.
Events and Callback Functions
Let’s say you’ve got the Raspberry Pi camera module, and you’d like it to snap a photo when you press a button. However, you don’t want your code to poll that button constantly, and you certainly don’t want to wait for an edge because you may have other code running simultaneously.
The best way to execute this code is using a callback function. This is a function that is attached to a specific GPIO pin and run whenever that edge is detected. Let’s try one:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)
def printFunction(channel):
print(“Button 1 pressed!”)
print(“Note how the bouncetime affects the button press”)
GPIO.add_event_detect(23, GPIO.RISING, callback=printFunction, bouncetime=300)
while True:
GPIO.wait_for_edge(24, GPIO.FALLING)
print(“Button 2 Pressed”)
GPIO.wait_for_edge(24, GPIO.RISING)
print(“Button 2 Released”)
GPIO.cleanup()
You’ll notice here that button 1 will consistently trigger the printFunction, even while the main loop is waiting for an edge on button 2. This is because the callback function is in a separate thread. Threads are important in programming because they allow things to happen simultaneously without affecting other functions. Pressing button 1 will not affect what happens in our main loop.
Events are also great, because you can remove them from a pin just as easily as you can add them:
GPIO.remove_event_detect(23)
Now you’re free to add a different function to the same pin!
Adding Functionality
As convenient as callback functions are for the GPIO pins, it still doesn’t change the fact that the Raspberry Pi is just not ideal for analog inputs or PWM outputs. However, because the Pi has Tx and Rx pins (pins 8 and 10, GPIO 14 and 15), it can easily communicate with an Arduino. If I have a project that requires an analog sensor input, or smooth PWM output, simply writing commands to the serial port to the Arduino can make things seamless.
Hey Mark, I just wanted to know how you drew the Pi with the Breadboard, what software did you use?
*Looks like Fritzing.org
Maybe http://fritzing.org/home ??
Thanks for this tutorial Mark, I just started using my GPIO with that. So cool xD
Thank you mark
I had been confused as to how to start using the GPIO with python. Nice article!
SyntaxError: Non-ASCII character ‘xe2’ in file test.py on line 11, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
same here
make sure you fix any scarequotes into regular quotes.
for example: “ is not the same as “
How do you end the program out of the while loop? I’ve only found to ctr+c out and that doesn’t reach the cleanup command so I have to manually reset the pins
Jaime, have a look at KeyboardInterrupt in Python. It is raised when control-c is pressed.
try:
… Do some logic / processing here ….
except KeyboardInterrupt:
GPIO.cleanup()
A more robust way to do this would be:
try:
# Your code
except KeyboardInterrupt:
print('Program terminated.')
finally:
GPIO.cleanup() # Clean up regardless of how the try: block was terminated.
That way you can
1) cleanup after other exceptions in your code (the previous implementation won’t run GPIO.cleanup() if another exception occurs), and
2) have the option to exit the try: block without hitting an exception and still run the cleanup code.
If you want to terminate your program, you can structure the while loop like this:
running = True
while running:
# Do stuff
running = False
After you set the running variable to false, the next time round the while: loop the test condition will evaluate to false and so the loop won’t be executed.
One way is the break statement:
while 1:
(commands)
if (statement) == (something):
break
Thank you
pull_up_down = GPIO.PUD_DOWN
resolved a long time problem I had along with the example with ground button.
Please correct you picture. GPIO9 is MISO and not MOSO.
Master IN server OUT.
Schönes anschauliches Tutorial!
Für den neuen Banana Pi haben wir auch mal alle Pindefinitionen und Schnittstellen zusammengetragen: http://www.bananapi-kaufen.de/aufbau-und-pindefinitionen/
Hello , i executed this program and it worked , but the next day nothing works!!!! there is no compilation error but , there is no response from the button or bread board…i am worried that is there any problem with my button or board?? Please help!
In the terminal, type ” sudo idle “, and from there open your file.
how can i use this circuit for a wasd keys
how can i use this circuit for wasd keys
Hello everyone,
I’m just the beginner in raspberry and programming in phyton. Could You tell me where I should write the “myInputSketch.py” file in order to open it successfully in python? Can I use another text editor like vi or nano? Thanks in advance, Mark.
You don’t have to open a specific file, but instead in the terminal, type ” sudo idle “, and from there go to , , and write your program.
Hello everyone,
I am new to PI( currently i am using Raspberry Pi model B+), is it possible to pass the message/Communicate between two PI using GIPO serial communication? how ?
Please can you help me here
Thanks
Sindhu
Great lesson!
I followed it exactly, but I am getting “ghosts in the machine” as my Pi is registering button presses when none have occurred, and sometimes fails to see button releases. I have tried various pull up and pull down resistors, and the problem seems more pronounced when triggering the pull down pin. I have 3 Pi’s around the house and have tried the code with all of them and they all respond the same. By simply touching the wires on the breadboard between the switch and GPIO pins I get input triggers. Any suggestions would be greatly appreciated as I have re-entered the code and tried different components with only slightly different results, but none of them satisfactory. I am hoping to pole a set of contacts on my furnace so I can keep track of how long the furnace is firing, so I can calculate how much heating oil I have used (knowing that the unit consumes .75 gallons an hour, if I can keep track of the total run-time I would have a primitive flow meter of sorts)
I will keep tweaking it, but any clues would be helpful.
Thanks
hey mark, how to connect water level circuit to raspberry pi?
I did an automatic water level detector that started a pump to keep my basement dry, but I used a Digispark arduino with a relay. Powered by a standard USB charger it all fitted very nice in a remote switch housing.
Cheap and simple. But now I started with Raspberry Pi GPIO as an alternative.
Great write up Mark :)
Here is a serious question however. I’m currently on a project and I would like to capture a temp value from a user who only has a keypad membrane with 4 buttons (each button is connected to it’s own GPIO). I would like to use one of the buttons to scroll through a set or defined number values e.g. 1, 2,…, 50 and rotate back to 1 again once they hit the top value (I would also like to include letters and symbols but that’s easy I’m sure once I’ve got the basic number rotation working). The goal is to create a kind of like a next, next action until they find the desired value.
Please if you could point me in the right direction that would be awesome.
Thanks in advance
Brett
Good evening Mark.
in events and callback you have mentioned “remove event” for single pin.
any chance to give an example because i need a new event on same pin with a same push of the button.
sorry gor my english, i hope you understand whats my point.
thanks in advance
How could I use the pins to power a drive and run a motor?
Hi Mark, I am very new in programming. May I know if I need to add in 2 more GPIO pins how should to be the coding. Same function as your GPIO pin 24. Please help.
Thanks
Hi, friends would you please help me because I am very new in programming. May I know if I need to add in 2 more GPIO pins 17 & 18, same function with GPIO pin 24 , may I know how to write the coding. Please help.
Thanks
I think beginners would like/need to see the correct python spacing in the source code.
You mention connecting to an Arduino, perhaps an example of that too? Especially using the PWM and Analogue IO.
Whoops – just noticed that this is an old article….
I have RPi3 with recent Raspian and using built in Chromium. At the beginning of this article you say indenting is critical but there are no indents at all in the presented code. For example…
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)
while True:
if(GPIO.input(23) ==1):
print(“Button 1 pressed”)
if(GPIO.input(24) == 0):
just copied and pasted from above. This is the 4th tutorial that fails for beginners early on. Very sad.
Hi,
That is a typical problem with Python code appeaing on SItes.
Personally I dislike the use of using blanks as a block defintion. I would much prefer
for example the C Version of { block } of BEGIN blocd END
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)
while True:
if(GPIO.input(23) ==1):
print(“Button 1 pressed”)
if(GPIO.input(24) == 0):
(something missing here)
Please note – Waiting for keys to be pressed and then released is not optimal.
Have a look a GPIO interupts
Here is an excellent tutorial;
https://medium.com/@rxseger/interrupt-driven-i-o-on-raspberry-pi-3-with-leds-and-pushbuttons-rising-falling-edge-detection-36c14e640fef
Have fun!
NT
The indentation is fucked up
And Outputs…? You said you were going to “get into inputs and *outputs*…what happened?
Hey mark!!! I’m working on a project based on raspberry pi. The requirements for my project is that I need to trigger some specific GPIO pins at a particular time whilst the other GPIO pins are still running in the background. I needed your advice regarding this issue. So can you e-mail me so that I can talk about the project in private as I fear divulging of the project.
If you can provide me your e-mail address it would be a great help.
Thanks!!
ConfigureACCEPT
Privacy Overview
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.