Raspberry Pi Debouncing a Button
Understand switch bounce - the rapid, unintended on/off chatter a mechanical button produces for a few milliseconds when pressed - and fix it with either a manual software delay or gpiozero's built-in bounce_time parameter.
What Is Switch Bounce?
Inside a mechanical push button, pressing it snaps two metal contacts together. Those contacts don't touch cleanly on the first try - they physically bounce apart and together several times in rapid succession before finally settling into a stable closed connection. This happens in a tiny window, typically somewhere between one and a few tens of milliseconds, but a Raspberry Pi reads GPIO state far faster than that, so it can easily register that single bounce sequence as several separate presses and releases rather than one clean press.
How Bounce Breaks Event-Driven Code
The problem becomes obvious as soon as you attach a counter to `when_pressed`. A single, deliberate press of the button can fire the callback two, three, or more times within a few milliseconds, because gpiozero is faithfully reporting every rapid HIGH/LOW transition the bouncing contacts produce - it has no way to know the difference between rapid switch chatter and someone pressing a button several times deliberately.
The bug: overcounting from bounce
from gpiozero import Button
from signal import pause
button = Button(2) # no debounce configured
count = 0
def on_press():
global count
count += 1
print(count) # a single physical press can print 2, 3, or more times here
button.when_pressed = on_press
pause()Fixing It Two Ways
There are two reliable ways to handle this. The manual approach records a timestamp the first time the button fires, and ignores any further presses that happen within a short window afterward - effectively treating rapid re-triggers as noise from the same physical press. The built-in approach lets gpiozero do this for you by passing a `bounce_time` value (in seconds) when creating the `Button`, which tells it to ignore any state changes that happen within that window after a detected edge.
Manual delay debounce with a timestamp
from gpiozero import Button
from time import monotonic
from signal import pause
button = Button(2)
count = 0
last_press = 0
MIN_INTERVAL = 0.2 # seconds - ignore repeats faster than this
def on_press():
global count, last_press
now = monotonic()
if now - last_press > MIN_INTERVAL:
count += 1
last_press = now
print(f"Press #{count}")
button.when_pressed = on_press
pause()Using gpiozero's built-in bounce_time
from gpiozero import Button
from signal import pause
button = Button(2, bounce_time=0.1) # ignore glitches within 0.1s of a detected edge
presses = 0
def count_press():
global presses
presses += 1
print(f"Press #{presses}")
button.when_pressed = count_press
pause()Exercise: Raspberry Pi Digital Input
What happens to a digital input pin's reading if it is left "floating" with no pull resistor connected?