По сути, пакет 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
:
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
.