События малины Pi- GPIO в Python
Я использую контакты GPIO на моей малине Pi с датчиком PIR для обнаружения движения. Когда датчик обнаруживает движение, я хочу затем переместить программное обеспечение на другие функции.
В настоящий момент для обнаружения движения у меня постоянно работает моя программа в цикле, пока она ждет обнаружения движения. Хотя это работает в настоящий момент, для использования в будущем это будет невероятно неэффективно, и я надеюсь улучшить это, назначив его событию.
Можно ли связать мой вход GPIO с событием, которое обнаружено программой без ручного запуска цикла.
Вот мой текущий цикл для обнаружения движения:
var = 1
counter = 0
while var == 1:
if GPIO.input(7):
counter += 1
time.sleep(0.5)
else:
counter = 0
time.sleep(1)
if counter >= 3:
print "Movement!"
captureImage()
time.sleep(20)
Счетчик и обнаружение движения несколько раз используются для уменьшения количества ложных срабатываний, которые датчик поднимает.
Ответы
Ответ 1
Библиотека RPi.GPIO теперь поддерживает События, которые объясняются в Прерывания и Edge detection.
Итак, после обновления вашей малины Pi с sudo rpi-update
, чтобы получить последнюю версию библиотеки, вы можете изменить свой код на:
from time import sleep
import RPi.GPIO as GPIO
var=1
counter = 0
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def my_callback(channel):
if var == 1:
sleep(1.5) # confirm the movement by waiting 1.5 sec
if GPIO.input(7): # and check again the input
print("Movement!")
captureImage()
# stop detection for 20 sec
GPIO.remove_event_detect(7)
sleep(20)
GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
# you can continue doing other stuff here
while True:
pass
Я выбрал метод Threaded callbacks, потому что я предполагаю, что ваша программа выполняет некоторые другие действия параллельно, чтобы изменить значение var
.
Ответ 2
Теперь библиотека RPIO GPIO имеет встроенный управляемый GPIO-контроль, который может произойти в отдельных потоках, освобождающих ресурсы.
Вы можете прочитать следующее http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3
Ответ 3
Вы можете обернуть GPIO-код в свой собственный поток, и остальная часть вашей программы сделает что-то еще, пока GPIO ждет ввода. Ознакомьтесь с потоковым модулем
Сначала я бы превратил ваш код в функцию
def wait_input():
var=1
counter = 0
while var == 1:
if GPIO.input(7):
counter += 1
time.sleep(0.5)
else:
counter = 0
time.sleep(1)
if counter >= 3:
print "Movement!"
captureImage()
time.sleep(20)
И тогда в вашей основной программе вы могли бы что-то вроде этого
input_thread = threading.Thread(target = wait_input)
input_thread.start()
# do something in the meanwhile
input_thread.join()
На SO есть много вопросов относительно потоковой обработки python, поэтому вы можете их выкопать. Обратите внимание, что при использовании потоков также необходимо учитывать множество вопросов, особенно в python, который имеет глобальную блокировку интерпретатора (GIL), которая позволяет запускать только один процесс за раз. Возможно, было бы разумно проверить модуль многопроцессорности, с помощью которого можно маршрутизировать вокруг GIL.
Ответ 4
kapcom01 дает отличные идеи, но лучше сделать не много инструкций в прерывании.
Обычно вы помещаете флаг в 1, когда обратный вызов является вызовом, и вы делаете обработку в основной функции. В этом случае нет риска освобождения программы.
Такие вещи:
from time import sleep
import RPi.GPIO as GPIO
def init():
# make all your initialization here
flag_callback = False
# add an interrupt on pin number 7 on rising edge
GPIO.add_event_detect(7, GPIO.RISING, callback=my_callback, bouncetime=300)
def my_callback():
# callback = function which call when a signal rising edge on pin 7
flag_callback = True
def process_callback():
# TODO: make process here
print('something')
if __name__ == '__main__':
# your main function here
# 1- first call init function
init()
# 2- looping infinitely
while True:
#3- test if a callback happen
if flag_callback is True:
#4- call a particular function
process_callback()
#5- reset flagfor next interrupt
flag_callback = False
pass