To use the PyBadge buttons, we will need a few pieces of code. Here's how the buttons function:

  • Pushing Up make the lights cycle faster
  • Pushing Down makes the lights cycle slower
  • Pushing Right makes the lights appear to move to the right
  • Pushing Left makes the buttons appear to move to the left
  • Pushing the B Button makes the lights dimmer
  • Pushing the A Button makes the light brighter

CircuitPython Button Code

BUTTON_LEFT = const(7)
BUTTON_UP = const(6)
BUTTON_DOWN = const(5)
BUTTON_RIGHT = const(4)
BUTTON_SEL = const(3)
BUTTON_START = const(2)
BUTTON_A = const(1)
BUTTON_B = const(0)

# Define Events and Shift Register
latest_event = Event()
last_event = Event()

pad = ShiftRegisterKeys(clock=board.BUTTON_CLOCK,
                   data=board.BUTTON_OUT,
                   latch=board.BUTTON_LATCH,
                   key_count=8,
                   value_when_pressed=True,
                   interval=0.1,
                   max_events=1)

def check_buttons(event):
    if event.key_number == BUTTON_RIGHT:
        settings["direction"] = -1
    elif event.key_number == BUTTON_LEFT:
        settings["direction"] = 1
    elif (event.key_number == BUTTON_UP) and settings["speed"] < 10:
        settings["speed"] += 1
    elif (event.key_number == BUTTON_DOWN) and settings["speed"] > 1:
        settings["speed"] -= 1
    elif (event.key_number == BUTTON_A) and settings["brightness"] < 0.5:
        settings["brightness"] += 0.025
    elif (event.key_number == BUTTON_B) and settings["brightness"] > 0.025:
        settings["brightness"] -= 0.025

current_buttons = pad.get_pressed()
last_read = 0
while True:
    for color in range(0, 360, speed):
        pad.events.get_into(latest_event)
        if latest_event.pressed and latest_event.key_number != last_event.key_number:
            check_buttons(latest_event)
            last_event = latest_event
            latest_event = Event(
                key_number=8
            )  # An imaginary key number that doesn't exist!

This code uses ShiftRegisterKeys, which allows reading the state of the buttons from the internal shift register. This means we need to detect when a button is pressed and released. We do this by monitoring the state of all the buttons and respond only when there is a change. Let's look at the code a little closer.

BUTTON_LEFT = const(7)
BUTTON_UP = const(6)
BUTTON_DOWN = const(5)
BUTTON_RIGHT = const(4)
BUTTON_SEL = const(3)
BUTTON_START = const(2)
BUTTON_A = const(1)
BUTTON_B = const(0)

There are eight buttons on the PyBadge and each corresponds to the position of a bit in the byte of data that is returned. In the first part, we define which button corresponds to the appropriate value. We do that by defining each of the buttons as bit masks. Bit masking works by defining which bits we want to look at and which we want to hide or "mask". For instance we have BUTTON_SEL defined as 3, which is bit 3 in an 8-bit array, so it looks for 0x00001000 in binary. 

If ShiftRegisterKeys gets back a value that is something like 0x01001000 then it knows that the BUTTON_SEL is being pressed at the same time as BUTTON_UP which is bit 7 or 0x01000000.

In the next segment of code we create a couple of Event objects and setup the ShiftRegisterKeys object and call it pad.

latest_event = Event()
last_event = Event()

pad = ShiftRegisterKeys(
    clock=board.BUTTON_CLOCK,
    data=board.BUTTON_OUT,
    latch=board.BUTTON_LATCH,
    key_count=8,
    value_when_pressed=True,
    interval=0.1,
    max_events=1,
)

We do that by passing the Clock, Latch, and Out pins of the built-in shift register to the module. This is an SN74HC165 Parallel-Load Shift Register, which works by first "latching" the current input values of the buttons being pressed. Then the Out pin is read and the data is shifted each time a Clock pulse is sent. This way we can get any combination of the eight inputs from the shift register. This is all handled in the background which makes it much easier to use.

The interval of 0.1, which is expressed in seconds, is important because it tells how CircuitPython how long to wait before reading the shift register. If it is read too frequently, then sometimes incorrect values are returned.

Next is the check_buttons() function. This function will read the event that is passed in to determine which buttons are being pressed and update the settings dictionary. By putting the checks in an else/if structure, it forces the code to only respond to one button press at a time.

def check_buttons(event):
    if event.key_number == BUTTON_RIGHT:
        settings["direction"] = -1
    elif event.key_number == BUTTON_LEFT:
        settings["direction"] = 1
    elif (event.key_number == BUTTON_UP) and settings["speed"] < 10:
        settings["speed"] += 1
    elif (event.key_number == BUTTON_DOWN) and settings["speed"] > 1:
        settings["speed"] -= 1
    elif (event.key_number == BUTTON_A) and settings["brightness"] < 0.5:
        settings["brightness"] += 0.025
    elif (event.key_number == BUTTON_B) and settings["brightness"] > 0.025:
        settings["brightness"] -= 0.025

Finally let's take a look at the button code in the main loop, which handles the button presses.

current_buttons = pad.get_pressed()
last_read = 0
while True:
    for color in range(0, 360, speed):
        pad.events.get_into(latest_event)
        if latest_event.pressed and latest_event.key_number != last_event.key_number:
            check_buttons(latest_event)
            last_event = latest_event
            latest_event = Event(
                key_number=8
            )  # An imaginary key number that doesn't exist!

We start by grabbing the current value of the buttons and setting the time of the last read to 0. After that, we have a for loop to cycle through all of the different colors. I have omitted that code so that we can focus on the button code only.

In the last bit, it waits until the button is no longer pressed so that the button press events aren't continuously fired off, which would make changing settings very difficult.

This guide was first published on May 28, 2019. It was last updated on May 28, 2019.

This page (PyBadge Buttons) was last updated on May 24, 2022.

Text editor powered by tinymce.