web-dev-qa-db-fra.com

Raspberry Pi- GPIO Evénements en Python

J'utilise les broches GPIO de mon Raspberry Pi avec un capteur PIR pour détecter les mouvements. Lorsque le capteur détecte un mouvement, je souhaite déplacer le logiciel vers d'autres fonctions.

Pour le moment, pour détecter un mouvement, mon programme tourne constamment en boucle pendant qu'il attend qu'un mouvement soit détecté. Bien que cela fonctionne pour le moment, pour une utilisation future, cela sera incroyablement inefficace et espère améliorer cela en l'attribuant à un événement.

Existe-t-il un moyen de lier mon entrée GPIO à un événement détecté par le programme sans exécuter manuellement une boucle.

Voici ma boucle actuelle pour le mouvement de détection:

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)

Le compteur et la détection du mouvement plusieurs fois permettent de réduire le nombre de faux positifs détectés par le capteur.

19
Stefoth

La bibliothèque Python RPi.GPIO prend désormais en charge Events, qui sont expliqués dans le paragraphe Interruptions et détection de bords paragraphe.

Ainsi, après avoir mis à jour votre Raspberry Pi avec Sudo rpi-update pour obtenir la dernière version de la bibliothèque, vous pouvez modifier votre code en:

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

J'ai choisi la méthode Threaded callbacks parce que je suppose que votre programme effectue d'autres opérations en parallèle pour modifier la valeur de var.

30
kapcom01

Maintenant, la bibliothèque RPi GPIO possède un contrôle GPIO intégré, piloté par des interruptions, qui peut se produire dans des threads séparés, libérant ainsi des ressources. Vous voudrez peut-être lire ce qui suit http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-

3
Nipun Batra

Vous pouvez envelopper le code GPIO dans son propre thread et demander au reste de votre programme de faire autre chose pendant que le GPIO attend une entrée. Découvrez le module de filetage

Je commencerais par envelopper votre code dans une fonction

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)

Et puis dans votre programme principal, vous pourriez quelque chose comme ça

input_thread = threading.Thread(target = wait_input)
input_thread.start()
# do something in the meanwhile
input_thread.join()

Il y a beaucoup de questions sur SO concernant les threads python, vous pouvez donc les creuser. Veuillez noter qu'il y a également de nombreux éléments à prendre en compte lors de l'utilisation de threads, en particulier en python qui dispose d'un verrou d'interpréteur global (GIL) qui ne permet l'exécution que d'un processus à la fois. Il peut également être judicieux de consulter le module de multitraitement avec lequel on peut acheminer le GIL.

1
msvalkon

kapcom01 donne quelques bonnes idées mais il est préférable de ne pas donner beaucoup d’instructions à l’interruption.

Habituellement, vous mettez un drapeau sur 1 lorsque le rappel est appelé et vous effectuez le traitement dans la fonction principale. De cette manière, il n’ya aucun risque de libérer le programme.

Des choses comme ça:

     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 __== '__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