If you have ever pressed a button once and had your code register two or three presses, you have met chattering. A mechanical button does not switch cleanly from LOW to HIGH; it bounces between the two states for a few milliseconds before settling. This tutorial shows the Raspberry Pi behavior with and without debounce, so you can see the problem and fix it with a simple time check in Python.
The full tutorial, with every detail and the line-by-line code explanation, is on our site: Raspberry Pi - Button - Debounce
What you need
- Raspberry Pi 5
- Breadboard-mount Button with Cap
- Breadboard-mount Button Kit
- Panel-mount Push Button
- Push Button Module
- Breadboard
- Jumper Wires
- Screw Terminal Block Shield for Raspberry Pi
- Raspberry Pi Prototyping Base Plate & Breadboard Kit
- DIYables Sensor Kit (18 sensors/displays)
- DIYables USB Type-A to Type-B Cable
Wiring
A button connects to a GPIO pin and to ground. When you use several buttons at once, wiring them directly on a breadboard gets messy, so the tutorial recommends a Screw Terminal Block Shield for Raspberry Pi for the multi-button version, which keeps each wire clamped down and clearly labeled instead of relying on loose jumper wires.
How it works
When the button's metal contacts touch, they physically bounce for a short time, so the GPIO pin briefly flickers between LOW and HIGH before settling on its final state. If your code reacts to every change, it sees that flickering as several presses instead of one. Debounce means telling your code to ignore any state changes that happen too soon after the last one, so only the real, settled press or release gets counted.
Code
The first script, button_without_debounce.py, reads the GPIO pin with RPi.GPIO and reports every change it sees, which is where you can watch chattering happen in the terminal. The second script, button_debounce.py, adds a check against elapsed time before accepting a new state, so a single press and release shows up as exactly one event. Both run as normal Python scripts over SSH after installing the RPi.GPIO library.
raspberry-pi-button-debounce.py
"""
This Raspberry Pi code was developed by newbiely.com
This Raspberry Pi code is made available for public use without any restriction
For comprehensive instructions and wiring diagrams, please visit:
https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-button-debounce
"""
import RPi.GPIO as GPIO
import time
# Set the GPIO mode to BCM
GPIO.setmode(GPIO.BCM)
# Define the GPIO pin for your button
BUTTON_PIN = 16
# Set the initial state and pull-up resistor for the button
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# Initialize the button state
button_state = GPIO.input(BUTTON_PIN)
try:
# Main loop
while True:
# Read the current button state
current_state = GPIO.input(BUTTON_PIN)
# Check if the button state has changed and print when it does
if current_state != button_state:
if current_state == GPIO.HIGH:
print("Button released")
else:
print("Button pressed")
button_state = current_state
time.sleep(0.1) # Adjust the sleep time as needed
except KeyboardInterrupt:
# Clean up GPIO on exit
GPIO.cleanup()
Things that go wrong
If you run the non-debounced script and press the button once, watch for multiple press or release lines appearing in the terminal from a single action, that is chattering, not a wiring fault. If the debounced version still shows extra events, double check that the debounce logic is actually comparing against the current time rather than a fixed value, and that each GPIO pin used for a button is wired correctly, especially when you scale up to multiple buttons with the screw terminal shield.
Full tutorial
The complete tutorial - wiring diagram, code explanation and troubleshooting - is here: https://newbiely.com/tutorials/raspberry-pi/raspberry-pi-button-debounce

Top comments (0)