[英]Using an IF statement in Python inside of a main() function
我正在嘗試創建一個程序,該程序檢測連接到Raspberry 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的建議,更新了代碼:
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
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
check_all_depressed()
def butTwo_callback(channel2):
print("Button 2 /n")
butTwo = True
check_all_depressed()
def butThree_callback(channel3):
print("Button 3 /n")
butThree = True
check_all_depressed()
def check_all_depressed():
if butOne and butTwo and butThree:
print("All Depressed")
GPIO.add_event_callback(19, butOne_callback)
GPIO.add_event_callback(20, butTwo_callback)
GPIO.add_event_callback(21, butThree_callback)
運行代碼並按下按鈕時收到錯誤:
追溯(最近一次通話最新):文件“ /home/pi/Downloads/GPIO_test_06.py”,在butTwo_callback中check21all_depressed()文件“ /home/pi/Downloads/GPIO_test_06.py”,行29,在check_all_depressed中,如果butOne和butTwo和butThree:NameError:未定義名稱“ butOne”
您的if
語句僅運行一次-首次啟動腳本時立即運行。 到那時,還沒有按下按鈕,因此似乎無法使用。
解決該問題的一種方法是將語句放入具有較小延遲的循環中,然后測試該循環中的條件。 就像是:
import time
while not condition:
time.sleep(1)
另一個問題是風格。 您可以寫下您的條件:
(butOne == True) and (butTwo == True) and (butThree == True)
就像這樣:
butOne and butTwo and butThree
因為它們都是布爾值開頭。 在Python中,您甚至可以編寫:
all([butOne, butTwo, butThree])
這並不短,但如果你有更多的條件,這將避免重復and
一次又一次。
最后,您已選擇創建一個運行主程序的主函數。 最好在其中包含函數定義上方的所有代碼。 畢竟,它們都是主程序的一部分,並且只能運行一次。 這樣,您還可以避免意外地在函數內部使用全局變量,這可能導致意外的行為(但在技術上正確)。
回答:
刪除if條件
添加一個函數check_all_depressed()
將函數添加到所有三個按鈕回調的末尾,如下所示
def butOne_callback(channel1):
global butOne
print("Button 1 /n")
butOne = True
check_all_depressed()
check_all_depressed看起來像這樣-
def check_all_depressed():
if butOne and butTwo and butThree:
print("All Depressed")
說明:因此,存在回調,並且存在常規程序流。 基本上python程序遵循事件發生的順序,即從上到下,回調發生在此流程之外。
從根本上講,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
的調用add_event_detect
main
並將其與add_event_callback
結合:
GPIO.add_event_detect(chan, GPIO.RISING, callback=...)
從編程的角度來看,我會使用這樣的事實,即所有通道都幾乎相同,並且僅定義一個回調。 實際上,設置中最重要的是通道號和通道名稱:
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
的嵌套函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.