0

I'm working with code that looks something like this:

from time import sleep

from gpipozero import Button

BUTTONS = {
    'start': Button(21),
    'choice_1': Button(1),
    'choice_2': Button(7),
}

CHOICE = 0


def do_stuff():
    global CHOICE
    # wait for user to make a choice
    while CHOICE == 0:
        sleep(0.2)

    if CHOICE == 1:
        # do variant a
    elif CHOICE == 2:
        # do variant b

    CHOICE = 0


def assign_choice_1():
    global CHOICE
    print("chose 1")
    CHOICE = 1


def assign_choice_2():
    global CHOICE
    print("chose 2")
    CHOICE = 2


BUTTONS['start'].when_pressed = do_stuff
BUTTONS['choice_1'].when_pressed = assign_choice_1
BUTTONS['choice_2'].when_pressed = assign_choice_2

What I observe is that the assign_choice_x functions don't seem to be working. There is no printout, and the script does not continue.

My questions:

  1. What's the reason this doesn't work.

  2. Regardless of 1, I feel like this approach is an ugly hack. What's a better way to achieve what I want. That is, user initiates routine with a button press, then proceeds to make a choice with another button press. That choice is stored and used in the rest of the routine.

0
  1. You have a loop which only contains sleep... [sorry, this is wrong]

  2. I would do:

Button.action = None

start_btn = Button(21)
choice_1_btn = Button(1)
choice_2_btn = Button(7)

def choice_1_action():
    print("Choice 1 action")

def choice_2_action():
    print("Choice 2 action")

def no_choice_action():
   print("No choice yet")

def choose(btn):
    start_btn.action = btn.action

start_btn.action = no_choice_action
choice_1_btn.action = choice_1_action
choice_2_btn.action = choice_2_action

choice_1_btn.when_pressed = choose
choice_2_btn.when_pressed = choose
start_btn.when_pressed = start_btn.action

When a when_pressed callback is called, the button that called it is passed in to the callback function, so you can have multiple buttons with the same callback but doing different things based on their own data. Here I embedded the function reference in the object by creating a new attribute on the class.

If you want to be able to let them press the start button first, then wait for a choice:

Button.action = None

start_btn = Button(21)
choice_1_btn = Button(1)
choice_2_btn = Button(7)

def choice_1_action():
    print("Choice 1 action")
    start_btn.action = None

def choice_2_action():
    print("Choice 2 action")
    start_btn.action = None

def choose(btn):
    start_btn.action = btn.action

def wait_for_choice():
    while start_btn.action is None:
        sleep(0.1)
    start_btn.action()

choice_1_btn.action = choice_1_action
choice_2_btn.action = choice_2_action

choice_1_btn.when_pressed = choose
choice_2_btn.when_pressed = choose
start_btn.when_pressed = wait_for_choice
5
  • thanks for jumping in. On 1 is that right? Presumably in your variant, when CHOICE changes to 1 or 2, the code within will execute, then we'll exit the loop. In my variant, it's the same. sleep will execute and if CHOICE has changed in the meantime, the loop will exit and the script will move on. In my actual code I use sleep interleaved with led.on, led.off to let the user know the device is waiting for input. – Alexander Soare Dec 1 '20 at 14:33
  • Oh I see, yeah you're right. I'll take another look. Have updated with 2 though :) – ben_nuttall Dec 1 '20 at 14:46
  • Thanks. It makes sense, although now I can't press the start button, wait for a choice then let the script continue. I have to press a choice, then I have to press start. – Alexander Soare Dec 1 '20 at 15:37
  • Oh I see. Updated - does that help? – ben_nuttall Dec 1 '20 at 15:59
  • this bring us back to the initial problem I believe. That is, the fact that other button presses are not registered while in the initial button callback. In any case, I've decided to drop this and go with the option of making a choice first, then pressing the start button. So don't worry about it, and thanks for your tips! – Alexander Soare Dec 1 '20 at 17:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.