Toggle LED with Button on Raspberry Pi Pico using MicroPython

Mastering LED Toggling: Button Control on Raspberry Pi Pico with MicroPython

Want to add interactive control to your Raspberry Pi Pico projects? This guide shows you how to wire and code a push button to toggle an LED using MicroPython. You'll get the full schematic, non-blocking code, and essential troubleshooting tips.

The Circuit: Wiring Your Pico for Interaction

Our straightforward circuit enables LED (D1) control via a push button. As shown, the button connects to GP17, with its other side wired to ground. This setup requires an internal pull-up resistor on GP17 for a stable HIGH state when unpressed.

The LED (D1) connects to GP16. A 470 Ohm resistor (R1) is in series with the LED's anode (long leg) to limit current. The cathode (short leg) connects to ground. The LED illuminates when GP16 is HIGH. For more Pico setup details, see our interactive board guide.

Raspberry Pi Pico 2 LED with push button

MicroPython Code: Non-Blocking Button Toggle

The MicroPython code below implements a robust, non-blocking approach to toggle the LED. It uses "falling edge" detection, registering a button press only when the input transitions from HIGH (unpressed) to LOW (pressed), which inherently handles debouncing.

# ==========================================================
# Raspberry Pi Pico - Button & LED Toggle Program
# Target: Your exact schematic (GP16 = LED, GP17 = Button)
# Language: MicroPython
# ==========================================================

from machine import Pin
import time

# Pin Assignments matching your schematic
LED_PIN = 16
BUTTON_PIN = 17

# Hardware Configuration
led = Pin(LED_PIN, Pin.OUT)
# Enables internal pull-up so GP17 stays HIGH until button connects it to GND
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)

# State tracking variables
led_state = False
last_button_state = 1  # Starts at 1 (HIGH) because of the pull-up

print("Pico Simulation Started. Press the button to toggle the LED.")

# Explicitly ensure the LED starts turned OFF
led.value(0)

while True:
    # Read the current button value (1 = unpressed, 0 = pressed)
    current_button_state = button.value()
    
    # Detect falling edge: button goes from HIGH (1) to LOW (0)
    if current_button_state == 0 and last_button_state == 1:
        print("Button Press Detected! Toggling LED...")
        
        # Invert the tracking variable
        led_state = not led_state
        
        # Write the new state directly to the hardware pin
        led.value(1 if led_state else 0)
        
        # Debounce delay to prevent double-triggering in simulation/hardware
        time.sleep(0.2)
        
    # Update the historical state tracking for the next loop pass
    last_button_state = current_button_state
    
    # Tiny sleep window to keep the processor/simulation stable
    time.sleep(0.01)

Key code elements:

  • led = Pin(LED_PIN, Pin.OUT): Configures GP16 as an output.
  • button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP): Configures GP17 as an input with internal pull-up. This keeps GP17 HIGH (1) when unpressed, pulling LOW (0) when pressed to ground.
  • The while True loop continuously monitors button state.
  • if current_button_state == 0 and last_button_state == 1:: This falling edge detection toggles the LED once per press, detecting the HIGH to LOW transition.
  • led_state = not led_state & led.value(...): Inverts the LED's logical state and updates the physical LED.
  • time.sleep(0.2): A 200ms software debouncing delay after a press, preventing multiple toggles from mechanical button bounce.
  • time.sleep(0.01): A small loop delay for stability and efficient CPU usage.

Troubleshooting & Common Problems

Button Debouncing (Multiple Presses or Flickering LED)

Likely Cause: Mechanical buttons 'bounce', causing multiple rapid electrical contacts for a single physical press.

Solution:

  1. Implement software debouncing using a short time.sleep() delay (e.g., 50-200ms) after detecting a press.

In Practice: Our code's time.sleep(0.2) filters bounces, ensuring one toggle per press.

Floating Input Pin (Unpredictable Button Readings)

Likely Cause: Unconnected input pins pick up ambient electrical noise, leading to unpredictable readings.

Solution:

  1. Utilize Pico's internal pull-up/pull-down resistors by specifying Pin.PULL_UP or Pin.PULL_DOWN when initializing the button pin.
  2. Alternatively, add an external pull-up or pull-down resistor to the circuit.

Discussion: Our circuit uses Pin.PULL_UP for the button to ground connection, keeping the pin HIGH until pressed, providing a stable state.

Incorrect Pull-up/Pull-down Configuration

Likely Cause: Code's pull-up/pull-down setting mismatches the physical button wiring.

Solution:

  1. If the button connects the GPIO pin to ground when pressed (as in our schematic), use Pin.PULL_UP in your code.
  2. If the button connects the GPIO pin to 3.3V when pressed, use Pin.PULL_DOWN in your code.

Discussion: A mismatch prevents correct button registration. For our circuit, Pin.PULL_UP is essential.

Wiring Errors or Poor Connections

Likely Cause: Loose wires, incorrect component orientation (LED), wrong GPIO pins, or missing current-limiting resistor.

Solution:

  1. Carefully double-check all physical connections.
  2. Ensure wires are firm, LED polarity correct (long leg to resistor, short to ground).
  3. Verify the 470 Ohm resistor (R1) is in series with the LED.
  4. Confirm code pin assignments (GP16 LED, GP17 Button) match physical connections.

In Practice: R1 (470 Ohm) is vital; omitting it can damage the LED or Pico.

RP2350-E9 Chip Bug Affecting Internal Pull-Down Resistors (Pico 2 specific)

Likely Cause: Hardware bug (RP2350-E9) in some Pico 2 models causes internal pull-down resistors to behave unexpectedly.

Solution:

  1. If using an affected Raspberry Pi Pico 2, avoid using Pin.PULL_DOWN.
  2. Instead, use an external pull-down resistor (`Pin.PULL_NONE` in code).
  3. Alternatively, configure your button with Pin.PULL_UP by wiring it to pull the pin LOW when pressed (as in this guide).

Discussion: This bug can cause unpredictable pin readings. Our method using internal pull-up avoids it.

Conclusion

You've successfully wired and coded an LED and push button to your Raspberry Pi Pico with MicroPython. This interaction is a stepping stone for more complex projects, from auditory alerts to servo motor control. Keep experimenting!

Post a Comment

Previous Post Next Post