Question:
Comment allumer / éteindre les LED en continu, tout en poursuivant l'exécution d'un script?
Stephen Lead
2015-03-25 03:53:15 UTC
view on stackexchange narkive permalink

J'ai connecté des LED rouges et vertes via GPIO et je peux les allumer / éteindre avec succès en utilisant RPi.GPIO - maintenant j'aimerais:

  • démarrer une led clignotante toutes les 1 seconde
  • faire continuer son exécution au script
  • arrêter la led de clignoter sur un autre signal

Un exemple similaire est le projet Raspberry Pi E-mail Notifier Using LED, sauf que dans ce cas, les LED sont allumées en continu et le script attend juste la prochaine vérification:

  if newmails > NEWMAIL_OFFSET: GPIO.output (GREEN_LED, True) GPIO.output (RED_LED, False) else: GPIO.output (GREEN_LED, False) GPIO.output (RED_LED, True) time.sleep (MAIL_CHECK_FREQ)  

Est-il possible de faire quelque chose comme ce pseudo-code?

  cont = TruePendant que cont: vérifier s'il y a un nouveau courrier: flashLed (vert) else: flashLed ( rouge) faire d'autres choses pendant que le voyant correspondant clignote (pas seulement time.sleep) def flashLed (couleur): arrêter de clignoter l'autre couleur commence à clignoter cette couleur retourne au programme appelant  

Pour que cela fonctionne, j'imagine que la fonction flashLed aurait besoin de démarrer le clignotement de la led correspondante, puis de retourner l'exécution au corps principal du script.

Est-ce possible avec Python? Existe-t-il une meilleure approche?

Cinq réponses:
Stephen Lead
2015-03-26 05:51:55 UTC
view on stackexchange narkive permalink

Merci à @ user451777 pour le conseil sur le filetage. J'ai modifié le script Signalisation entre les threads et j'ai trouvé ce qui suit:

  import threading, timefrom random import randintdef flashLed (e, t): "" "flash the led spécifié toutes les secondes "" "alors que ce n'est pas le cas e.isSet (): print (couleur) time.sleep (0.5) event_is_set = e.wait (t) if event_is_set: print ('stop led from flashing') else: print (' leds off ') time.sleep (0.5) color = "red" e = threading.Event () t = threading.Thread (name =' non-block ', target = flashLed, args = (e, 2)) t. start () for i in range (0, 10): # Attribuer aléatoirement rouge ou vert toutes les 10 secondes randomNumber = randint (0,10) print (randomNumber) if (randomNumber < 5): color = "green" else: color = "red" time.sleep (10) e.set ()  

Ceci simule l'allumage / extinction de la led correspondante dans un thread pendant que l'exécution du programme continue dans le thread principal. Surtout, la fonction flashLed ne verrouille pas l'exécution pendant que les voyants clignotent.

Le thread principal utilise une variable globale pour définir la couleur de la LED, avec l'autre thread utilisant le variable globale pour allumer la led correspondante. Je pense que les variables globales sont généralement mal vues, je serais donc intéressé d’entendre parler de meilleures approches.

Stephen merci d'avoir publié votre solution - extrêmement utile
`event_is_set = e.wait (t)` doit être remplacé par `event_is_set = e.is_set ()`. Sinon, vous ajoutez un délai de «t» pour chaque appel lorsque le drapeau est désactivé.
josxou15
2017-07-18 00:55:11 UTC
view on stackexchange narkive permalink

Je suis relativement nouveau dans Python, mais j'ai pu faire clignoter les LED tout en poursuivant l'exécution en utilisant la modulation de largeur d'impulsion (PWM) qui est intégrée au module RPi.GPIO. C'était à mon avis un moyen beaucoup plus facile et plus simple que le threading comme le suggèrent d'autres réponses, mais les deux méthodes fonctionneraient bien.

Créez simplement un objet PWM avec la fréquence souhaitée, puis appelez PWM.start (DC) et PWM.ChangeDutyCycle (DC) pour démarrer / modifier le cycle de service des LED. Continuez avec votre code puis appelez PWM.stop () pour arrêter la LED.

  #setup GPIO pins et importez le module GPIO g = GPIO.PWM (pin1,1) r = GPIO. PWM (pin2,1) g.start (0) r.start (0) greenStatus = False redStatus = False def flashLED (couleur): global greenStatus, redStatus if color == 'green': if redStatus: r.ChangeDutyCycle (0 ) redStatus = False sinon greenStatus: g.ChangeDutyCycle (50) greenStatus = True elif color == 'red': if greenStatus: g.ChangeDutyCycle (0) greenStatus = False sinon redStatus: r.ChangeDutyCycle (50) redStatus = True essayez: while True: if newMail (): flashLED ('green') else: flashLED ('red') #do faites d'autres choses ici et la LED continuera à clignoter sauf KeyboardInterrupt: g.stop () r.stop () GPIO.cleanup ()  

Fondamentalement, ce code démarre les deux LED avec un cycle de service de 0 pour qu'elles apparaissent éteintes. Chaque fois que flashLED (couleur) est appelé, il vérifie que la LED opposée est éteinte, si ce n'est pas le cas, son cycle de service est remis à 0. Ensuite, il allume l'autre LED si elle n'est pas déjà allumée. Le code est enveloppé dans un try / sauf pour qu'à la fin les deux objets PWM soient arrêtés et les broches GPIO nettoyées.

user451777
2015-03-25 09:11:08 UTC
view on stackexchange narkive permalink

Je recommanderais le filetage. Je ne l'ai pas utilisé en Python pour donner l'exemple, mais cela créera un autre thread d'exécution qui sera parallèle au thread principal d'exécution. J'espère que quelques exemples de code suivront pour vous.

http://pymotw.com/2/threading/

paddyg
2015-04-03 22:30:09 UTC
view on stackexchange narkive permalink

@Stephen Lead, vous avez des questions sur les globaux. Parfois, avec des choses comme les fonctions de threading, les globaux semblent être des options raisonnables car les alternatives peuvent être plus compliquées. Cependant, c'est une bonne habitude de toujours les déclarer explicitement comme globales

  def flashLed (e, t): "" "clignote la led spécifiée toutes les secondes" "" couleur globale sans e.isSet ( ):  

car à un moment donné, vous essaierez d'assigner la variable et vous aurez du mal à comprendre pourquoi elle ne semble pas avoir d'effet.

Vous pouvez passez des arguments à la fonction qui sont modifiés par d'autres parties de votre programme ou qui sont modifiés par votre fonction mais les arguments doivent être des objets mutables. L'exemple le plus simple serait une liste, puis vous vous retrouvez avec la, à peine artificielle:

  def flashLed (e, t, color): ... print (color [0]) color = ["red"] e = threading.Event () t = threading.Thread (name = 'non-block', target = flashLed, args = (e, 2, color)) ... if (randomNumber < 5) : color [0] = "green"  

Si vous aviez des informations plus complètes à communiquer entre les deux threads, une liste pourrait sembler plus logique. Les files d'attente sont également assez simples à utiliser et méritent d'être vérifiées dans la documentation.

developius
2015-03-25 16:22:02 UTC
view on stackexchange narkive permalink

Vous pouvez faire quelque chose comme ceci:

  while True: if newMail (): # renvoie true si nouveau mail, false sinon flashLED ("green") else: flashLED ("red ") def flashLED (color): if color ==" red ": pin = 18 # remplace le numéro par le numéro GPIO si color ==" green ": pin = 24 # remplace le numéro par le GPIO number GPIO.output (pin, True) # remplace le pin par le numéro GPIO time.sleep (1) GPIO.output (pin, False)  

L'avantage de ceci est qu'il n'y a pas de threading impliqué. Vous devriez construire newMail () vous-même, sauf si une fonction similaire est disponible dans une bibliothèque ( cette réponse fournit une solution pour Gmail et POP)

Merci pour le conseil. Mais à moins que je ne me trompe, cela ne fera clignoter les voyants qu'une seule fois, puis quittera la fonction. J'espérais commencer le clignotement de la LED, la maintenir à clignoter pendant que j'effectuais d'autres tâches, puis arrêter le clignotement à un signal ultérieur. Il semble que cela peut nécessiter un thread séparé
Ce code maintiendra le voyant LED clignotant, une fois à chaque exécution de la boucle. Si vous souhaitez effectuer d'autres tâches, placez-les simplement après le if / else.


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...