If you need reliable buttons for Raspberry Pi, the default concrete pick is the Omron B3F-1000 tactile switch paired with a 100nF (0.1µF) MLCC ceramic capacitor for hardware debouncing. This combination eliminates the phantom double-triggers that plague software-only debounce routines and survives millions of actuations without contact degradation. Below is the exact decision framework, wiring topology, and Pi 5-compatible Python code to get your input circuit running on the first try.

The Decision Path: Which Buttons for Raspberry Pi Should You Buy?

Not all switches behave the same way electrically. The right choice depends on your enclosure and actuation force requirements. Use this decision tree to select the correct component, terminating in the optimal default for standard bench and breadboard projects.

Use CaseSwitch TypeSpecific Pick (Part Number)Why This Wins
Panel Mount / ArcadeMicroswitchAdafruit 3485 (Sanwa D2LS clone)High actuation force, built-in LED, rugged spade terminals.
PCB / Breadboard DIYTactileOmron B3F-1000 (Default Pick)1.6mm travel, 160gf force, gold-plated contacts, standard 6x6mm footprint.
Mechanical Keyboard FeelKey SwitchGateron Red (Cherry MX compatible)Linear, 45gf, hot-swappable sockets available, zero tactile bump.
Heavy Industrial / E-StopPushbuttonSchneider XB4BA3122mm metal bezel, IP66 rated, NC/NO contacts for safety interlocks.

The Verdict: For 90% of embedded sensor triggers, escape rooms, and DIY controllers, buy the Omron B3F-1000. It fits standard breadboards, requires no 3D-printed mounts, and its internal contact geometry minimizes severe bounce compared to cheap unbranded 6x6mm switches.

Parts List and GPIO Pin Mapping

This build targets the Raspberry Pi 5 (8GB) running Raspberry Pi OS (Bookworm or later). The Pi 5 uses the RP1 southbridge chip for GPIO, which changes how pull-up resistors are handled at the silicon level compared to the Pi 4's BCM2711. We will use the Pi's internal pull-up resistor to simplify wiring, relying on the external capacitor to filter the noise.

Bill of Materials

  • Microcontroller: Raspberry Pi 5 (8GB) — ~$80.00
  • Switch: Omron B3F-1000 Tactile Switch (6x6x5mm) — ~$0.35
  • Capacitor: 100nF (0.1µF) 50V X7R MLCC Ceramic Capacitor — ~$0.05
  • Wiring: 22 AWG stranded silicone jumper wires (Dupont connectors) — ~$8.00/pack
  • Resistor: None required (using RP1 internal pull-up)

Pin Mapping Table

Component LeadPi 5 BCM GPIOPi 5 Physical PinWire ColorFunction
Switch Pin 1GPIO 17Pin 11YellowSignal (Active Low)
Switch Pin 2GNDPin 9BlackGround Reference
Capacitor Lead 1GPIO 17Pin 11(Soldered to Switch Pin 1)Filter High
Capacitor Lead 2GNDPin 9(Soldered to Switch Pin 2)Filter Low

Wiring the Hardware Debounce Circuit

Switch bounce occurs because the metal contacts physically vibrate when they collide, causing the GPIO pin to see rapid HIGH-LOW-HIGH transitions over a 1-5 millisecond window. While software can ignore this, a hardware RC (resistor-capacitor) low-pass filter absorbs the kinetic energy electrically. Since we are using the Pi's internal pull-up resistor (approx. 50kΩ), adding a 100nF capacitor creates an RC time constant of roughly 5ms, perfectly bridging the bounce gap.

Bench Tip: Do not rely on breadboard contact pressure for the capacitor. The momentary loss of contact on a breadboard will disconnect the cap, instantly reintroducing bounce. Solder the 100nF capacitor directly across the two diagonal legs of the Omron switch before inserting it into the breadboard.

  1. Prepare the Switch: Bend the 100nF capacitor leads so they sit flush against the Omron B3F-1000 switch pins. Solder one lead to Pin 1 and the other to Pin 2 (the diagonal pins that are internally isolated until pressed).
  2. Connect Ground: Insert a black 22 AWG jumper wire into the breadboard rail connected to the Pi's Physical Pin 9 (GND). Route the other end to the switch leg connected to the capacitor's ground side.
  3. Connect Signal: Insert a yellow 22 AWG jumper wire into Physical Pin 11 (GPIO 17). Route it to the opposite switch leg.
  4. Verify Polarity: Ceramic MLCC capacitors are non-polarized, so orientation does not matter. However, ensure no stray solder bridges are shorting the switch legs together, which would pull GPIO 17 permanently LOW.

Compilable Python Code for Raspberry Pi 5

The following script uses gpiozero, the officially supported Python library for Raspberry Pi. Legacy libraries like RPi.GPIO are deprecated on the Pi 5 due to the RP1 chip architecture. This code includes robust error handling and graceful exit routines.

import sys
import time
from gpiozero import Button
from signal import pause

# Target Board: Raspberry Pi 5 (8GB)
# Target OS: Raspberry Pi OS (Bookworm 64-bit)
# Wiring: Switch between GPIO 17 and GND. 100nF cap in parallel.

BUTTON_PIN = 17

try:
    # pull_up=True enables the RP1 internal 50k pull-up resistor.
    # The pin reads HIGH (3.3V) normally, and LOW (0V) when pressed.
    # bounce_time=0.05 acts as a software failsafe in case the hardware cap fails.
    btn = Button(BUTTON_PIN, pull_up=True, bounce_time=0.05)

    def on_press():
        # Using monotonic time for precise event logging
        print(f'[{time.monotonic():.4f}] Button PRESSED on GPIO {BUTTON_PIN}')

    def on_release():
        print(f'[{time.monotonic():.4f}] Button RELEASED on GPIO {BUTTON_PIN}')

    # Bind the callback functions
    btn.when_pressed = on_press
    btn.when_released = on_release

    print(f'Listening for button presses on GPIO {BUTTON_PIN}. Press Ctrl+C to exit.')
    
    # pause() keeps the script alive without consuming CPU cycles
    pause()

except KeyboardInterrupt:
    print('\nCtrl+C detected. Exiting gracefully.')
    sys.exit(0)
except Exception as e:
    print(f'Critical GPIO Error: {e}')
    sys.exit(1)

Debugging: RP1 GPIO Errors and Switch Bounce

When migrating to the Pi 5 or dealing with physical wiring, you will likely hit one of three specific errors. Here is the exact decision path to resolve them.

Error 1: RuntimeError: Not running on a RPi!

Cause: You are trying to import the legacy RPi.GPIO library on a Raspberry Pi 5. The RP1 southbridge chip does not map memory the same way as the BCM2711, causing the legacy library to fail its hardware check.

Fix: Rewrite your code to use gpiozero (as shown above). If you absolutely must use a legacy script, install the compatibility shim via terminal: sudo apt install python3-rpi-lgpio. For new projects, always default to gpiozero (gpiozero official docs).

Error 2: gpiozero.exc.GPIOPinInUse

Cause: Another process (like a background daemon, Node-RED, or a previously crashed Python script) has claimed GPIO 17 and failed to release it.

Fix: Run sudo killall python3 to clear hung scripts. If the pin is claimed by the system, check your /boot/firmware/config.txt for gpio=17=op,dh directives and remove them.

Error 3: Phantom Double-Triggers (Switch Bounce)

If your console logs two 'PRESSED' events within 20 milliseconds of a single physical push, your hardware debounce has failed. The first three things to check:

  1. Capacitor Connection: Measure the capacitance across the switch legs with a multimeter. If it reads open-loop (OL), your solder joint is cold or the breadboard contact is loose.
  2. Wire Length: Are your jumper wires longer than 8 inches? Long unshielded wires act as antennas, picking up EMI from the Pi 5's switching power supply. Keep GPIO wires under 6 inches.
  3. Software Failsafe: Ensure bounce_time=0.05 is explicitly defined in the Button() initialization. Without it, gpiozero defaults to software debouncing that may be too fast for degraded mechanical contacts.

Extending and Simplifying the Build

If your project requires more than four or five buttons—such as a custom macro pad or an industrial control panel—wiring each directly to the Pi's GPIO header becomes a cable management nightmare and exhausts the available pins.

To scale up: Use an MCP23017 I2C GPIO Expander. This $2.50 chip connects to the Pi's I2C bus (Physical Pins 3 and 5) and provides 16 additional interrupt-capable GPIO pins. You can daisy-chain up to eight MCP23017 chips on a single bus, giving you 128 button inputs while only using two Pi GPIO pins. The gpiozero library supports the MCP23017 natively via the MCP23017 class, requiring only a change in the pin definition, not the core logic.

To simplify: If you are building a consumer-facing product and want to eliminate soldering entirely, swap the Omron B3F and breadboard for a Pimoroni Button SHIM (PIM354). It friction-fits directly over the Pi's GPIO header and includes five pre-debounced tactile switches with onboard pull-ups, reducing your wiring complexity to zero. For pure reliability and lowest component cost on a custom PCB, however, stick with the Omron B3F-1000 and the 100nF capacitor topology detailed above (All About Circuits switch bounce guide).