User Tools

Site Tools


using_a_breakout_button_-_better_code_but_slightly_more_complex

Using a Breakout Button - Better Code

Jul 2026


Introduction


*** Warning *** You can lock yourself out of your Pi Pico if you don't have a method to break the code. Please think about if you want/need to do this!!!

Please read the section before this titled Using a Breakout Button as I am only covering the differences here.


This is our original traffic light build, but with an additional push button on pins GP16 and GND.


The Code


Below is the full code with all of the changes, there are two blocks that have been added. We will cover these in the next section below this code block.

| download
#Traffic light LEDs using an array
 
from machine import Pin
import time
 
#######################    ADD BREAKOUT BUTTON #############################
# Configure the button on GPIO16
# PULL_UP means the pin reads HIGH (1) until the button connects it to GND
button = Pin(16, Pin.IN, Pin.PULL_UP)
#######################    ADD BREAKOUT BUTTON #############################
 
 
# Define GPIO pins for the LEDs
RED = Pin(2, Pin.OUT)
AMBER = Pin(6, Pin.OUT)
GREEN = Pin(10, Pin.OUT)
 
# Put them in an array
lights = [RED, AMBER, GREEN]
 
# Helper function to turn all lights off
def all_off():
    for light in lights:
        light.off()
 
# checks to see if the button has been pressed.
def check_breakout():
    if button.value() == 0:   # Button pressed
        print("Button pressed — stopping program.")
        all_off()
        return True
    return False
 
# define a function wait_with_break. This function waits 1 second in 0.1s slices. If you pass
# it the value 3, it will wait 3 seconds in 30 x .1s slices. This is so it can check the
# button state every 0.1s rather than waiting 8 whole seconds.
def wait_with_break(seconds):
    for _ in range(int(seconds * 10)):  # 0.1s slices in a loop
        if check_breakout():
            return True
        time.sleep(0.1)
    return False
 
while True:
 
    # Red
    all_off()
    RED.on()
    # passes the value 3 to the function above causing a 3s second delay in 0.1s steps
    if wait_with_break(3): break
 
    # Red + Amber
    AMBER.on()
    # passes the value 1 to the function above causing a 1s second delay in 0.1s steps
    if wait_with_break(1): break
 
    # Green
    all_off()
    GREEN.on()
    # passes the value 3 to the function above causing a 3s second delay in 0.1s steps
    if wait_with_break(3): break
 
    # Amber
    all_off()
    AMBER.on()
    # passes the value 1 to the function above causing a 1s second delay in 0.1s steps
    if wait_with_break(1): break
 
# Code End



What Has Changed?


We have actually removed the long delay required when pressing the button. See below for how this was achieved.

Firstly, we have defined a function for the button press detection.

| download
# checks to see if the button has been pressed.
def check_breakout():                     # Define a function named 'check_breakout'
 
    if button.value() == 0:               # Read the button pin; 0 means the button is pressed
        print("Button pressed — stopping program.")  # Inform the user via the console
        all_off()                         # Turn off all LEDs (your own helper function)
        return True                       # Signal to the caller that the program should stop
    return False                          # Button not pressed → tell the caller to continue running

The code block above is a function.

In Python, a function is created using the def keyword, followed by:

  1. a name
  2. parentheses
  3. a colon
  4. an indented block of code

Next, we have a function that waits an amount of time depending on a value that is passed to it. It loops in 0.1s intervals, and in each loop it checks the button status. This makes button detection only 0.1s long.

| download
# define a function wait_with_break. This function waits 1 second in 0.1s slices. If you pass
# it the value 3, it will wait 3 seconds in 30 x .1s slices. This is so it can check the
# button state every 0.1s rather than waiting 8 whole seconds.
def wait_with_break(seconds):                 # Define a function named 'wait_with_break' that takes 'seconds' as an argument
 
    for _ in range(int(seconds * 10)):        # Loop 'seconds * 10' times → e.g. 1s = 10 loops, 3s = 30 loops (each loop = 0.1s)
        if check_breakout():                  # Call 'check_breakout()' to see if the button has been pressed
            return True                       # If the button is pressed, immediately return True to signal "stop"
        time.sleep(0.1)                       # Wait for 0.1 seconds before the next loop iteration
    return False                              # If the loop finishes with no button press, return False (no stop requested)

So if it is passed the value 3, it will loop 30×0.1s, and in that time check the button status 30 times. So when you press the breakout button, it will seem instant.

Lastly, in the section that sets the traffic light LED status, we call the wait_with_break function at each section, and we pass the delay to this function.

| download
# Red
    all_off()
    RED.on()
    # passes the value 3 to the function above causing a 3s second delay in 0.1s steps
    if wait_with_break(3): break
 
    # Red + Amber
    AMBER.on()
    # passes the value 1 to the function above causing a 1s second delay in 0.1s steps
    if wait_with_break(1): break
 
    # Green
    all_off()
    GREEN.on()
    # passes the value 3 to the function above causing a 3s second delay in 0.1s steps
    if wait_with_break(3): break
 
    # Amber
    all_off()
    AMBER.on()
    # passes the value 1 to the function above causing a 1s second delay in 0.1s steps
    if wait_with_break(1): break


So this line: if wait_with_break(3): break calls the function wait_with_break and asks for a delay of 3 seconds (in a 0.1s loop).

If the button is detected to have been pressed, we breakout of the code immediately.


Example


*Remember* - We must save this code to our Raspberry Pi Pico as a file called main.py.

This will enable to code to run on the Pico boot up.

Here is the button in action using the better code we just explored.


Using a button like this means you can never get you Pico stuck in a software loop with little to no way of recovery (without wiping it completely).


using_a_breakout_button_-_better_code_but_slightly_more_complex.txt · Last modified: by walkeradmin