Skip to content
Advertisement

Two-Button Menu Iteration

I’ve got a script that I’m adapting to micropython on a 2040, and I want to use two buttons to navigate the menu structure. I can’t figure out how to make the iterate loop in the multi-choice menus work right… here’s what I’ve got so far:

""" fit: a productivity logger """
import time
import sys
import os
import uhashlib
import machine

def final_print(sec,final_hash,final_survey):
    """ leaves the summary on the screen before shutting down """
    mins = sec // 60
    sec = sec % 60
    hours = mins // 60
    mins = mins % 60
    short_sec = int(sec)
    duration = (str(hours) + "/" + str(mins) + "/" + str(short_sec))
    print("> fit the",str(final_hash)," went ",str(final_survey)," lasted //",str(duration))

def timer_down(f_seconds,timer_focus):
    """ counts down for defined period """
    now = time.time()
    end = now + f_seconds
    while now < end:
        now = time.time()
        fit_progress(now,end,timer_focus,f_seconds)
        b1pressed = button1.value()
        time.sleep(0.01)
        if not b1pressed:
             print('Ended Manually!')
             break

def timer_up(timer_focus):
    """ counts up for indefinite period """
    now = time.time()
    while True:
         minutes = int((time.time() - now) / 60)
         print(str(timer_focus)," for ",str(minutes))
         b1pressed = button1.value()
         time.sleep(0.01)
         if not b1pressed:
             print('Ended Manually!')
             break

def fit_progress(now,end,timer_focus,f_seconds):
    """ tracks progress of a count-down fit and prints to screen """
    remain = end - now
    f_minutes = int((remain)/60)
    j = 1 - (remain / f_seconds)
    pct = int(100*j)
    print(str(timer_focus),str(f_minutes),str(pct))

def multi_choice(options):
    done = 0
    while done == 0:
        for i in options:
            b1pressed = button1.value()
            b2pressed = button2.value()
            time.sleep(.01)
            b1released = button1.value()
            b2released = button2.value()
            if b2pressed and not b1pressed:
                print(i," b2 pressed")
                continue
            if b1pressed and not b2pressed:
                print(i," b1 pressed")
                time.sleep(2)
                return i

button1 = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
button2 = machine.Pin(3, machine.Pin.IN, machine.Pin.PULL_UP)

print("format?")
fType = multi_choice(['30-minute fit','60-minute fit','indefinite fit'])
print(fType," selected")

print("focus?")
F_FOCUS = multi_choice(['personal fit','work fit','learn fit','admin fit'])
print(F_FOCUS," selected")

fStart = time.time()

if fType == "30-minute fit":
    timer_down(1800,F_FOCUS)
elif fType == "60-minute fit":
    timer_down(3600,F_FOCUS)
elif fType == "indefinite fit":
    timer_up(F_FOCUS)
else:
    sys.exit()

fEnd = time.time()

print("sentiment?")
F_SURVEY = multi_choice(['+','=','-'])
print(F_SURVEY," selected")

fDuration = fEnd - fStart

F_HASH = uhashlib.sha256(str(fEnd).encode('utf-8')).digest()
F_HASH_SHORT = F_HASH[0:3]

fitdb = open("data.csv","a")
fitdb.write(str(F_HASH)+","+str(fType)+","+str(F_FOCUS)+","+str(F_SURVEY)+","+str(fStart)+","+str(fEnd)+","+str(fDuration)+"n")
fitdb.close()

final_print(fDuration,F_HASH_SHORT,F_SURVEY)
print(F_HASH_SHORT," ",F_HASH)

In particular, this is the logic I’m wrangling with:

def multi_choice(options):
    done = 0
    while done == 0:
        for i in options:
            b1pressed = button1.value()
            b2pressed = button2.value()
            time.sleep(.01)
            b1released = button1.value()
            b2released = button2.value()
            if b2pressed and not b1pressed:
                print(i," b2 pressed")
                continue
            if b1pressed and not b2pressed:
                print(i," b1 pressed")
                time.sleep(2)
                return i

Here’s what I’m wanting to do:

For each item in the set,

  • Display the item, wait for button press
  • If button 1 is pressed, select that item, return the item.
  • If button 2 is pressed, display the next item, wait for button press.
  • (iterate until button 1 pressed to select item)

Again, this is micropython, so I don’t have all the modules you’d think available… woudl be best to do this in raw code.

Advertisement

Answer

0.01 second is way too short. The key is, after you detect “button down”, you need to wait for “button up”. You need something like:

def wait_for_btn_up(btn):
    count = 2
    while count > 0:
        if btn.value();
            count = 2
        else:
            count -= 1
        time.sleep(0.01)

    
def multi_choice(options):
    for i in options:
        print( "trying", i )
        # Wait for any button press.
        while 1:
            b1pressed = button1.value()
            b2pressed = button2.value()
            if b1pressed or b2pressed: 
                break
        if b1pressed:
            print( i, "chosen" )
            wait_for_btn_up(button1)
            return i
        # We know B2 was pressed.
        wait_for_btn_up(button2)
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement