Подтвердить что ты не робот

События малины 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)

Счетчик и обнаружение движения несколько раз используются для уменьшения количества ложных срабатываний, которые датчик поднимает.

4b9b3361

Ответ 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.

Ответ 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