-1

我有另一个关于迭代菜单逻辑的问题,问题变成了按钮逻辑,所以我把它们分开了,因为原来的问题已经真正解决了。

我的代码如下:

""" fit: a productivity logger """
import time
import sys
import os
import uhashlib
import machine
import framebuf
from ssd1306 import SSD1306_I2C

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))
    oled_show("> fit the"+str(final_hash),str(final_survey),"//"+str(duration))
    time.sleep(30)
    oled_blank()

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)
        time.sleep(0.01)
#        if button1.value() == 0:
#             oled_show("","Ended Manually!","")
#             time.sleep(2)
#             break

def timer_up(timer_focus):
    """ counts up for indefinite period """
    now = time.time()
    while True:
        minutes = int((time.time() - now) / 60)
        oled_show(str(timer_focus)," for ",str(minutes))
        time.sleep(0.01)
#         if button1.value() == 0:
#             oled_show("","Ended Manually!","")
#             time.sleep(2)
#             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)
    oled_show(str(timer_focus),str(f_minutes)+" min",str(pct)+"%")

def debounce(btn):
    """ some debounce control """
    count = 2
    while count > 0:
        if btn.value():
            count = 2
        else:
            count -= 1
        time.sleep(0.01)

def multi_choice(options):
    """ provides multi-choice menus for two-button navigation """
    for i in options:
        oled_show("> fit",i,"1:yes  2:next")
        # Wait for any button press.
        while 1:
            b1pressed = button1.value()
            b2pressed = button2.value()
            if b1pressed or b2pressed:
                break
        if b1pressed:
            print( i, "chosen" )
            debounce(button1)
            return i
        # We know B2 was pressed.
        debounce(button2)

def oled_show(message1,message2,message3):
    """ displays a three line message """
    oled.fill(0) # clear the display
    oled.text(message1,5,5)
    oled.text(message2,5,15)
    oled.text(message3,5,25)
    oled.show()

def oled_blank():
    """ blanks the oled display to avoid burn in """
    oled.fill(0)
    oled.show()

sda = machine.Pin(4)
scl = machine.Pin(5)
i2c = machine.I2C(0,sda=sda, scl=scl, freq=400000)
oled = SSD1306_I2C(128, 32, i2c)

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

F_TYPE = multi_choice(['30-minute fit','60-minute fit','indefinite fit'])

F_FOCUS = multi_choice(['personal fit','work fit','learn fit','admin fit'])

fStart = time.time()

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

fEnd = time.time()

F_SURVEY = multi_choice(['went well','went ok','went poorly'])

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(F_TYPE)+","+str(F_FOCUS)+","+str(F_SURVEY)+","+str(fStart)+","+str(fEnd)+","+str(fDuration)+"\n")
fitdb.close()

final_print(fDuration,F_HASH_SHORT,F_SURVEY)

特别是,您可以看到我定义了两个按钮:

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

它们主要用于从具有多种选择的菜单中进行选择:

def debounce(btn):
    """ some debounce control """
    count = 2
    while count > 0:
        if btn.value():
            count = 2
        else:
            count -= 1
        time.sleep(0.01)

def multi_choice(options):
    """ provides multi-choice menus for two-button navigation """
    for i in options:
        oled_show("> fit",i,"1:yes  2:next")
        # Wait for any button press.
        while 1:
            b1pressed = button1.value()
            b2pressed = button2.value()
            if b1pressed or b2pressed:
                break
        if b1pressed:
            print( i, "chosen" )
            debounce(button1)
            return i
        # We know B2 was pressed.
        debounce(button2)

但是,我遇到了一个问题,即只能交替按下按钮。也就是说,当 multi_choice 功能开始时,我可以按 button1 选择第一个选项,或者我可以按 button2 滚动到下一个选项,但是,如果我按 button2,例如,它不会注册第二次按下 (选择第二个选项),然后我只能按下按钮 1 ...如果我这样做,我只能接下来按下按钮 2。

我确定这只是我没有看到的逻辑问题。

这些按钮是 GPIO 引脚 2 和 3 上的普通瞬时关闭 Cherry MX 开关。它们确实可靠地工作,但这种逻辑有些不稳定。

以下测试工作得很好,所以它不是按钮......

import machine
import time

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

while True:
    b1pressed = button1.value()
    b2pressed = button2.value()
    time.sleep(0.01)
    b1released = button1.value()
    b2released = button2.value()
    if b1pressed and not b1released:
        print('Button1 pressed!')
    if b2pressed and not b2released:
        print('Button2 pressed!')
    if not b2pressed and b2released:
        print('Button2 released!')
    elif not b1pressed and b1released:
        print('Button1 released!')

我添加了一些打印语句来调试它,我可以看到按钮获取和保存值。我觉得我需要调整人工重置,也许这​​是我可以在去抖动中做的事情?我尝试了一些事情,但到目前为止我没有取得进展。

def debounce(btn):
    """ some debounce control """
    count = 2
    while count > 0:
        if btn.value():
            count = 2
        else:
            count -= 1
        time.sleep(0.01)

def multi_choice(options):
    """ provides multi-choice menus for two-button navigation """
    for i in options:
        print("below for")
        print("button 1 below for",button1.value())
        print("button 2 below for",button2.value())
        oled_show("      fit",i,"1:sel    2:next")
        while 1:
            print("below while")
            print("button 1 below while",button1.value())
            print("button 2 below while",button2.value())
            b1pressed = button1.value()
            b2pressed = button2.value()
            if b1pressed or b2pressed:
                print("below first if")
                print("button 1 first if",button1.value())
                print("button 2 first if",button2.value())
                break
        if b1pressed:
            print("below second if")
            print("button 1 second if",button1.value())
            print("button 2 second if",button2.value())
            debounce(button1)
            return i
        debounce(button2)

以及上述调试打印的输出:

>>> %Run -c $EDITOR_CONTENT
below for
button 1 below for 0
button 2 below for 1
below while
button 1 below while 0
button 2 below while 1
below first if
button 1 first if 0
button 2 first if 1
below for
button 1 below for 1
button 2 below for 0
below while
button 1 below while 1
button 2 below while 0
below first if
button 1 first if 1
button 2 first if 0
below second if
button 1 second if 1
button 2 second if 0
below for
button 1 below for 0
button 2 below for 1
below while
button 1 below while 0
button 2 below while 1
below first if
button 1 first if 0
button 2 first if 1
below for
button 1 below for 1
button 2 below for 0
below while
button 1 below while 1
button 2 below while 0
below first if
button 1 first if 1
button 2 first if 0
below second if
button 1 second if 1
button 2 second if 0
4

2 回答 2

1

将两个按钮都接地,并使用 PULL_UP 代码就是:

import machine

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

while True:
    print('Button1 down!') if not button1.value() else print('Button1 up!') 
    print('Button2 down!') if not button2.value() else print('Button2 up!')

逻辑很简单。你的按钮一端被绑在地上,另一端被拉起。当您按下该按钮时,它会将 MCU 的引脚接地。按下按钮value()时为 0,松开value()时为 1。如果您想value()在按下按钮时保持积极状态,则需要将按钮连接到 Vcc 导轨并PULL_DOWN在 MCU 引脚上使用。

所有这些去抖动的代码可能甚至都不是必需的,即使有必要创建一个循环来处理它也不是答案。如果您的按钮不弹跳怎么办〜现在您只是陷入了循环。如果您担心弹跳,请获取 74HC14 或制作一个简单的 RC 网络。将所有这些任意值分配给按钮状态并将按钮粘贴在阻止其他按钮的循环中只是一堆噪音。这很简单:你有一个问题要问两次。“这个按钮被按下了吗?”~所以只需“问”两次这个问题,然后继续。不需要 20 行代码就可以确定某个值是 1 还是 0。

旁白:您没有单独的“GND”。您所有的“GND”引脚都连接到相同的“GND”。你只有一个电源吗?嗯,一个就是一个。将一个蛋糕切成 8 块并不会给你 8 个蛋糕。

于 2021-04-05T09:51:37.187 回答
0

好的,在大家的帮助下,我想通了。只需要添加一点睡眠以避免前一个while循环中的按键溢出。

def multi_choice(options):
    """ provides multi-choice menus for two-button navigation """
    for i in options:
        oled_show("      fit",i,"1:sel    2:next")
        time.sleep(0.5)
        while 1:
            if not button1.value():
                return i
            if not button2.value():
                break

谢谢大家!

于 2021-04-05T22:01:08.123 回答