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 component 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 Raspberry Pi’s GPIO 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 to keep 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 (between 50k-60k) that can be enabled via software.
Example of External Pull-up Resistors
If you prefer to use resistors in the circuit instead of internal ones (which is often a good idea), you can do it like this.
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 is connected 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 is connected to ground, reading a low value.
GPIO Pin ---- Button ---- GND
|
Resistor (10kΩ) ---- 3.3V
Programming the Button in Python
Once we have the button correctly connected, we can write a Python program to detect when it is pressed.
Let’s see an example using the RPi.GPIO library (which we saw in the previous post), with a Python code that reads the state of a 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.GPIOto control the GPIO pins andtimeto add pauses in the loop. - Pin configuration: We use
GPIO.setmode(GPIO.BCM)to use the BCM numbering for the GPIO pins. Then, we configure pin 17 as an input with a pull-down resistor usingGPIO.setup(). - Reading the state: In the
whileloop, we read the button state withGPIO.input(). If the state isGPIO.HIGH, it means the button is pressed. - Exception handling: We catch
KeyboardInterruptto 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 software debounce system.
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() configures 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, to turn 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()
