web-dev-qa-db-ja.com

PythonのRaspberry Pi- GPIOイベント

Raspberry PiのGPIOピンと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)

カウンターとモーションの検出を複数回使用して、センサーが検出する誤検知の数を減らします。

19
Stefoth

RPi.GPIOPythonライブラリはEvents、これは 割り込みとエッジ検出 段落で説明されています。

したがって、Raspberry 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

私はあなたのプログラムがvarの値を変更するために他の何かを並行して行うと思うので Threaded callbacks メソッドを選択しました。

30
kapcom01

RPi GPIOライブラリには、独立したスレッドで発生する可能性のある割り込み駆動GPIO制御が組み込まれているため、リソースが解放されます。以下を読むことをお勧めします http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-

3
Nipun Batra

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でスレッドを使用します。これは、一度に1つのプロセスのみを実行できるグローバルインタープリターロック(GIL)を持ちます。 multiprocessingモジュール を使用してGILを迂回できます。

1
msvalkon

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
0
Lemaitre Cedric