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

Wiring

Raspberry Pi Pico - Button - Debounce wiring diagram

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