In this article, we will explore how to connect and program buttons and switches with a Raspberry Pi.
A button or switch is a mechanical switch that, when pressed, closes an electrical circuit, allowing current to flow. When released, the circuit opens again.
These components are widely used in electronics. We can use the GPIO of the Raspberry Pi to read their state and use them as input devices.
Connecting the Button to the Raspberry Pi
Connecting a button to the Raspberry Pi requires a simple circuit that includes a resistor that puts the pin in a known state when the switch is open.
The resistor can be configured in pull-up or pull-down mode, depending on how we want to interpret the button’s state.
The Raspberry Pi has internal pull-up and pull-down resistors (of between 50k-60k) that can be activated via software.
Expand to see an example of external pull-up resistors
If you prefer to use resistors in the circuit instead of internal resistors (which is often a good idea), you can do it this way.
Pull-down Resistor
In this schematic, the resistor is placed between the GPIO input pin and ground (GND). When the button is not pressed, the GPIO pin reads a low value (0V). When the button is pressed, the pin connects to 3.3V, reading a high value.
GPIO Pin ---- Button ---- 3.3V
|
Resistor (10kΩ) ---- GND
Pull-up Resistor
In this case, the resistor is placed between the GPIO input pin and 3.3V. When the button is not pressed, the GPIO pin reads a high value (3.3V). When the button is pressed, the pin connects to ground, reading a low value.
GPIO Pin ---- Button ---- GND
|
Resistor (10kΩ) ---- 3.3V
If you want to learn more about Pull-up and Pull-down resistors, check out,
Programming the Button in Python
Once we have the button properly connected, we can write a Python program to detect when it is pressed.
Let’s look at an example using the RPi.GPIO
library (which we covered in the previous entry), with a Python code that reads the state of the button connected to GPIO pin 17.
import RPi.GPIO as GPIO
import time
# GPIO pin configuration
BUTTON_PIN = 17
GPIO.setmode(GPIO.BCM) # Use BCM numbering
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # Set as input with pull-down
try:
while True:
# Read the button state
button_state = GPIO.input(BUTTON_PIN)
if button_state == GPIO.HIGH:
print("Button pressed")
else:
print("Button not pressed")
time.sleep(0.1) # Small pause to avoid rapid readings
except KeyboardInterrupt:
print("Program terminated")
finally:
GPIO.cleanup() # Clean up GPIO configuration
- Library import: We import
RPi.GPIO
to control the GPIO pins andtime
to add pauses in the loop. - Pin configuration: We use
GPIO.setmode(GPIO.BCM)
to use the BCM numbering of the GPIO pins. Then, we configure pin 17 as input with a pull-down resistor usingGPIO.setup()
. - State reading: In the
while
loop, we read the button state withGPIO.input()
. If the state isGPIO.HIGH
, it means the button is pressed. - Exception handling: We catch
KeyboardInterrupt
to allow the program to terminate cleanly when the user pressesCtrl+C
. Finally, we callGPIO.cleanup()
to reset the GPIO pins.
Debounce
Mechanical buttons can generate erroneous signals due to physical bouncing when pressed or released. To avoid this, we can implement a debounce system in software.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
DEBOUNCE_TIME = 0.2 # Debounce time in seconds
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
last_state = GPIO.LOW
last_time = 0
try:
while True:
current_state = GPIO.input(BUTTON_PIN)
current_time = time.time()
if current_state != last_state:
last_time = current_time
if current_time - last_time > DEBOUNCE_TIME:
if current_state != last_state:
last_state = current_state
if current_state == GPIO.HIGH:
print("Button pressed")
else:
print("Button released")
time.sleep(0.01)
except KeyboardInterrupt:
print("Program terminated")
finally:
GPIO.cleanup()
Using Interrupts
Instead of constantly reading the button state, we can also use interrupts to detect state changes.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
def button_callback(channel):
if GPIO.input(channel) == GPIO.HIGH:
print("Button pressed")
else:
print("Button released")
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(BUTTON_PIN, GPIO.BOTH, callback=button_callback, bouncetime=200)
try:
while True:
time.sleep(1) # Keep the program running
except KeyboardInterrupt:
print("Program terminated")
finally:
GPIO.cleanup()
In this example, GPIO.add_event_detect()
sets up an interrupt that calls button_callback()
every time the button state changes.
If you want to learn more about interrupts, check out,
Practical Examples
LED Control
We can use a button to control an LED connected to another GPIO pin. For example, turning the LED on and off each time the button is pressed.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
LED_PIN = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(LED_PIN, GPIO.OUT)
try:
while True:
if GPIO.input(BUTTON_PIN) == GPIO.HIGH:
GPIO.output(LED_PIN, GPIO.HIGH) # Turn on LED
else:
GPIO.output(LED_PIN, GPIO.LOW) # Turn off LED
time.sleep(0.1)
except KeyboardInterrupt:
print("Program terminated")
finally:
GPIO.cleanup()
Press Counter
This example counts how many times the button has been pressed and displays the result in the console.
import RPi.GPIO as GPIO
import time
BUTTON_PIN = 17
counter = 0
def button_callback(channel):
global counter
counter += 1
print(f"Presses: {counter}")
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(BUTTON_PIN, GPIO.RISING, callback=button_callback, bouncetime=200)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Program terminated")
finally:
GPIO.cleanup()