在main()函数内使用Python中的IF语句

2024-09-30 22:27:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个程序来检测三个不同按钮的状态,它们连接到树莓Pi上的GPIO管脚上,一旦三个按钮都处于高位,就会采取行动。现在,所有的按钮都通过回调函数单独工作,但是“main”函数中的if语句似乎没有运行。在

这是我第一次使用Python,所以如果在代码结构中发现其他逻辑错误,请告诉我。仍然在尝试掌握它,尤其是GPIO库函数。提前谢谢,我已经在下面发布了我的代码。在

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

butOne = False
butTwo = False
butThree = False

# Setup button inputs
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

GPIO.add_event_detect(19, GPIO.RISING)
GPIO.add_event_detect(20, GPIO.RISING)
GPIO.add_event_detect(21, GPIO.RISING)

def butOne_callback(channel1):
    print("Button 1 /n")
    butOne = True

def butTwo_callback(channel2):
    print("Button 2 /n")
    butTwo = True

def butThree_callback(channel3):
    print("Button 3 /n")
    butThree = True

def main():
    GPIO.add_event_callback(19, butOne_callback)
    GPIO.add_event_callback(20, butTwo_callback)
    GPIO.add_event_callback(21, butThree_callback)

    if (butOne == True) and (butTwo == True) and (butThree == True):
        print("All Depressed")
main()

根据Aditya Shankar的建议更新了代码:

^{pr2}$

运行代码并按下按钮时收到错误:

回溯(最近一次呼叫): 文件“/home/pi/Downloads/GPIO_test_06.py”,第21行,在butTwo_回调中 检查所有按下的() File“/home/pi/Downloads/GPIO_test_06.py”,第29行,check_all_depressed 如果布通、布托和布特里: 名称错误:未定义名称“butOne”


Tags: 代码eventaddfalsetruegpiomaindef
3条回答

您的if语句只运行一次-在脚本第一次启动时立即运行。到那时,按钮还没有按下,所以看起来好像不起作用。在

解决这个问题的一种方法是将语句放入一个具有小延迟的循环中,并在该循环中测试条件。比如:

import time

while not condition:
    time.sleep(1)

另一个问题是风格问题。你可以写下你的情况:

^{pr2}$

简单地说:

butOne and butTwo and butThree

因为它们一开始都是布尔值。在Python中,您甚至可以编写:

all([butOne, butTwo, butThree])

这并不短,但如果您有更多的条件,它将避免一次又一次地重复and。在

最后,您选择创建一个main函数,它运行主程序。将函数定义之上的所有代码也包含在其中可能是个好主意。毕竟,这都是你的主程序的一部分,它只运行一次。这样,还可以避免意外地在函数内部使用全局变量,这可能导致意外(但技术上正确)行为。在

从根本上说,GPIO包支持事件的方式是等待所选通道的上升沿和下降沿。这是在后台线程中完成的,而不管在主线程中发生了什么。您的if语句在配置按钮后立即运行一次,然后主线程结束。在

您可以实现两种类型的解决方案。一种是强制主线程等待状态的改变。另一个是响应回调中状态的变化。在

要强制main等待:

import RPi.GPIO as GPIO

channels = [19, 20, 21]

def main():
     GPIO.setmode(GPIO.BCM)
     for chan in channels:
         GPIO.setup(chan, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
     for chan in channels:
         GPIO.wait_for_edge(chan, GPIO.RISING)

     # Now all your buttons have been pressed

这可能是更有效的方法。最小的设置和没有显式的多线程。在

另一种方法是在单独的线程中侦听输入。您可以像使用add_event_callback那样配置回调以响应上升沿,但请记住,该函数主要用于设置多个回调。更简洁的方法是将对add_event_detect的调用移动到main中,并将它们与add_event_callback结合起来:

^{pr2}$

从编程的角度来看,我将使用这样一个事实:所有通道都被处理得几乎相同,并且只定义一个回调。事实上,设置中最重要的是频道编号和频道名称:

import RPi.GPIO as GPIO

channels = {19: 1, 20: 2, 21: 3}

class callback:
    def __init__(self):
         self.pressed = dict.fromkeys(channels, False)
    def __call__(self, channel):
         print(f'Button {channels[channel]} pressed')
         self.pressed[channel] = True
         if sum(self.pressed.values()) == len(self.pressed):
             # All buttons have been pressed

def main():
     GPIO.setmode(GPIO.BCM)
     cb = callback()
     for chan in channels:
         GPIO.setup(chan, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
         GPIO.add_event_detect(chan, GPIO.RISING, callback=cb)

注意,在这两个例子中,除了通道配置之外,我都避免了全局状态。第二种方法是将回调设置为可调用类的实例。另一种方法是将回调定义为main中的嵌套函数。在

回答:

移除if条件

添加一个功能检查_all\u depressed()

将函数添加到所有三个按钮回调的末尾,如下所示

def butOne_callback(channel1):
    global butOne
    print("Button 1 /n")
    butOne = True
    check_all_depressed()

检查你所有的郁闷看起来像这样-

^{pr2}$

说明: 因此,有回调和通用程序流。 基本上python程序遵循事件发生的顺序,即从上到下,回调发生在这个流之外。在

相关问题 更多 >