MicroPython中的按钮(GPIO)按下逻辑

MicroPython中的按钮(GPIO)按下逻辑,python,raspberry-pi,micropython,raspberry-pi-pico,Python,Raspberry Pi,Micropython,Raspberry Pi Pico,我还有一个关于迭代菜单逻辑的问题,这个问题演变成了按钮逻辑,所以我把它们分开,因为原来的问题已经解决了 我的代码如下: """ fit: a productivity logger """ import time import sys import os import uhashlib import machine import framebuf from ssd1306 import SSD1306_I2C def final_pr

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

我的代码如下:

""" 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)
它们主要用于从具有多个选项的菜单中进行选择:

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)
然而,我遇到一个问题,即按钮只能交替按下。也就是说,当多选项功能开始时,我可以按button1选择第一个选项,也可以按button2滚动到下一个选项,但是,如果我按button2,例如,它将不会注册第二次按(选择第二个选项),我只能按button1。。。如果我这样做,我只能按下按钮2下一步

我肯定这只是一个逻辑问题,我没有看到

按钮是GPIO引脚2和3上的普通瞬时闭合樱桃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!')
我添加了一些print语句来调试它,我可以看到按钮获取和保存值。我觉得我需要调整一个人工重置,也许这是我可以在debounce中做的事情?我尝试了一些事情,但到目前为止还没有取得进展

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

两个按钮都固定在地上,使用上拉按钮,代码如下:

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()
将为零,松开按钮时,
value()
将为一。如果按下按钮时希望
value()
为正值,则需要将按钮系在Vcc导轨上,并在MCU引脚上使用
下拉

所有这些去抖动代码可能都不是必需的,即使有必要创建一个循环来处理它也不是答案。如果你的按钮没有弹起~现在你只是陷入了一个循环。如果你担心反弹,买一个74HC14或者做一个简单的RC网络。将所有这些任意值指定给按钮状态,并将按钮粘贴在循环中,从而阻止其他按钮,这只是一堆噪音。很简单:你有一个问题想问两次。“这个按钮按下了吗”~所以只要“问”这个问题两次,然后继续。不需要20行代码就可以确定是1还是0

旁白:
您没有单独的“GND”。您所有的“GND”引脚都连接到同一个“GND”。你只有一个电源,对吗?嗯,一对一。把一块蛋糕切成8块并不能得到8块蛋糕。

好的,在大家的帮助下,我找到了答案。只需要添加一点睡眠,以避免上一个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

谢谢大家

我不确定你是否想把车停下来。当按钮未按下时,您希望信号低飘浮,这将是下拉。啊,接得好,让我试试。Tim,你真是太棒了,谢谢你在这方面的帮助。有趣的是,下拉会导致两个开关在这个Pico(2040)设备上都不起作用。切换回上拉,它恢复正常。您是否尝试过一个循环,您只需执行打印操作(button1.value(),button2.value()/
sleep(0.01)
即可实时观察发生了什么?(在主帖子中编辑以响应,因为我无法在此处插入代码,但是的,尝试过,预期结果)因此,这在真空中工作得很好,就像另一个一样,但我需要帮助如何将此逻辑应用于双按钮菜单系统(一个按钮用于选择,另一个按钮用于下一个)。
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