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.
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
.
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-
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.
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