Press a mechanical button once and your Raspberry Pi Pico might report several presses instead of one. The metal contacts inside the button physically bounce for a few milliseconds before settling, and a fast microcontroller loop catches every bounce as a separate press or release. This is called chattering, and debouncing is how you filter it out in software so your code reacts to what the human actually did.
The full tutorial, with every detail and the line-by-line code explanation, is on our site: Raspberry Pi Pico - Button - Debounce
What you need
- Raspberry Pi Pico W
- Raspberry Pi Pico
- Micro USB Cable
- Breadboard-mount Button with Cap
- Breadboard-mount Button Kit
- Panel-mount Push Button
- Push Button Module
- Breadboard
- Jumper Wires
- DIYables Sensor Kit (18 sensors/displays)
Wiring
The button connects to GP0 on the Pico. The code configures this pin as an input with the internal pull-up resistor enabled, so the pin reads high when the button is untouched and reads low when it's pressed and pulls the pin to ground. Using the internal pull-up means you don't need an external resistor on the breadboard for this wiring.
How it works
A button isn't a clean digital switch, it's a physical contact, and physical contacts bounce. When you press or release it, the connection flickers between open and closed several times in the space of a few milliseconds before it stabilizes. A microcontroller loop runs fast enough to see each of those flickers as its own press or release event, which is why an unfiltered read of the pin produces duplicate messages for a single press.
Code
The basic version without debounce just reads button.value() every loop and compares it to the previous reading, printing a message whenever the state changes from pressed to released or back. This is enough to show the chattering problem. The debounced version adds a short pause with utime.sleep_ms() after a state change is detected, giving the contacts time to settle before the next read, so one physical press produces exactly one printed message. Later examples show a non-blocking version and one built on the DIYables_MicroPython_Button library for handling several buttons at once.
raspberry-pi-pico-button-debounce.py
"""
This Raspberry Pi Pico MicroPython code was developed by newbiely.com
This Raspberry Pi Pico code is made available for public use without any restriction
For comprehensive instructions and wiring diagrams, please visit:
https://newbiely.com/tutorials/raspberry-pico/raspberry-pi-pico-button-debounce
"""
from machine import Pin
import time
BUTTON_PIN = 0 # The Raspberry Pi Pico pin connected to the button (GP0)
# Setup the button pin. The Pin.PULL_UP enables the internal pull-up resistor.
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# Initialize the previous state of the button
prev_button_state = 1 # Assuming the button is unpressed initially
while True:
# Read the current state of the button
button_state = button.value()
# Check if button was released
if prev_button_state == 0 and button_state == 1:
print("The button is released")
# Check if button was pressed
if prev_button_state == 1 and button_state == 0:
print("The button is pressed")
# Save the current state as the previous state for the next loop iteration
prev_button_state = button_state
Things that go wrong
If you skip debouncing, watch for a single press printing multiple 'pressed' and 'released' lines in Thonny's shell, that's chattering, not a wiring fault. The utime.sleep_ms() debounce approach blocks the whole program during the sleep, so if your Pico needs to do other work while waiting on the button, use the non-blocking version instead. Also confirm the interpreter in Thonny is set to MicroPython (Raspberry Pi Pico) before running any of the scripts.
Full tutorial
The complete tutorial - wiring diagram, code explanation and troubleshooting - is here: https://newbiely.com/tutorials/raspberry-pico/raspberry-pi-pico-button-debounce

Top comments (0)