Pytanie:
Jak stale migać diody LED, kontynuując wykonywanie skryptu?
Stephen Lead
2015-03-25 03:53:15 UTC
view on stackexchange narkive permalink

Połączyłem czerwone i zielone diody przez GPIO i mogę je z powodzeniem włączać / wyłączać za pomocą RPi.GPIO - teraz chciałbym:

  • włączanie / wyłączanie diody LED co 1 sekundę
  • kontynuowanie wykonywania skryptu
  • zatrzymanie migania diody LED przy innym sygnale

Podobnym przykładem jest projekt Raspberry Pi E-mail Notifier Using LEDs, z wyjątkiem tego przypadku, gdy diody świecą się solidnie, a skrypt tylko czeka do następnego sprawdzenia:

  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_FRE) > 

Czy można zrobić coś takiego jak ten pseudokod?

  cont = Truewhile cont: sprawdź pocztę, jeśli nowa poczta: flashLed (zielona) else: flashLed ( red) rób inne rzeczy, gdy odpowiednie światło miga (nie tylko czas. sen) def flashLed (color): przestań migać inny kolor zacznij migać powrót tego koloru do programu wywołującego  

Wyobrażam sobie, że aby to zadziałało, funkcja flashLed musiałaby rozpocząć odpowiednie miganie diody, a następnie powrócić główna treść skryptu.

Czy jest to możliwe przy użyciu Pythona? Czy jest lepsze podejście?

Pięć odpowiedzi:
#1
+5
Stephen Lead
2015-03-26 05:51:55 UTC
view on stackexchange narkive permalink

Podziękowania dla @ user451777 za wskazówkę dotyczącą gwintowania. Zmodyfikowałem skrypt Signaling Between Threads i wymyśliłem:

  importowanie wątków, czas z losowego importu randintdef flashLed (e, t): "" "flashowanie określona dioda co sekundę "" ", gdy nie e.isSet (): print (color) time.sleep (0.5) event_is_set = e.wait (t) if event_is_set: print ('przestań migać dioda led') else: print (' diody wyłączone ') time.sleep (0.5) color = "red" e = threading.Event () t = threading.Thread (name =' non-block ', target = flashLed, args = (e, 2)) t. start () for i w zakresie (0, 10): # Losowo przypisz czerwony lub zielony co 10 sekund randomNumber = randint (0,10) print (randomNumber) if (randomNumber < 5): color = "green" else: color = "red" time.sleep (10) e.set ()  

To symuluje włączenie / wyłączenie odpowiedniej diody LED w jednym wątku, podczas gdy wykonywanie programu jest kontynuowane w głównym wątku. Co najważniejsze, funkcja flashLed nie blokuje wykonywania, gdy diody migają.

Główny wątek używa zmiennej globalnej do ustawiania koloru diody, podczas gdy drugi wątek używa zmienna globalna, aby włączyć odpowiednią diodę LED. Uważam, że zmienne globalne są generalnie źle widziane, więc chciałbym usłyszeć o lepszych podejściach.

Stephen dziękuję za opublikowanie swojego rozwiązania - niezwykle pomocne
`event_is_set = e.wait (t)` należy zastąpić przez `event_is_set = e.is_set ()`. W przeciwnym razie dodajesz opóźnienie „t” dla każdego wywołania, gdy flaga jest wyłączona.
#2
+3
josxou15
2017-07-18 00:55:11 UTC
view on stackexchange narkive permalink

Jestem stosunkowo nowy w Pythonie, ale mogłem migać diodami LED, kontynuując wykonywanie, używając modulacji szerokości impulsu (PWM), która jest wbudowana w moduł RPi.GPIO. Moim zdaniem był to znacznie łatwiejszy i prostszy sposób niż wątkowanie, jak sugerują inni anwsers, jednak obie metody działałyby dobrze.

Po prostu utwórz obiekt PWM z żądaną częstotliwością, a następnie wywołaj PWM.start (DC) i PWM.ChangeDutyCycle (DC), aby rozpocząć / zmienić cykl pracy LED. Kontynuuj wprowadzanie kodu, a następnie wywołaj PWM.stop (), aby zatrzymać diodę.

  #setup piny GPIO i zaimportuj moduł GPIO g = GPIO.PWM (pin1,1) r = GPIO. PWM (pin2,1) g.start (0) r.start (0) greenStatus = False redStatus = False def flashLED (color): global greenStatus, redStatus if color == 'green': if redStatus: r.ChangeDutyCycle (0 ) redStatus = False if not greenStatus: g.ChangeDutyCycle (50) greenStatus = True elif color == 'red': if greenStatus: g.ChangeDutyCycle (0) greenStatus = False if not redStatus: r.ChangeDutyCycle (50) redStatus = True try: while True: if newMail (): flashLED ('green') else: flashLED ('red') # zrobić tutaj inne rzeczy, a dioda LED będzie nadal migać z wyjątkiem KeyboardInterrupt: g.stop () r.stop () GPIO.cleanup ()  

Zasadniczo ten kod uruchamia obie diody z cyklem pracy równym 0, więc wyglądają na zgaszone. Za każdym razem, gdy wywoływana jest migająca dioda LED (kolor), sprawdza, czy przeciwna dioda LED jest wyłączona, jeśli nie, jej cykl pracy jest resetowany do 0. Następnie włącza drugą diodę LED, jeśli nie jest jeszcze włączona. Kod jest zawijany w try / z wyjątkiem tego, że na końcu oba obiekty PWM są zatrzymywane, a piny GPIO są czyszczone.

#3
+2
user451777
2015-03-25 09:11:08 UTC
view on stackexchange narkive permalink

Polecam wątkowanie. Nie użyłem go w Pythonie, aby podać przykład, ale utworzy kolejny wątek wykonania, który działa równolegle do głównego wątku wykonywania. Mamy nadzieję, że podamy Ci kilka przykładów kodu.

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

#4
+2
paddyg
2015-04-03 22:30:09 UTC
view on stackexchange narkive permalink

@Stephen Lead, czy pytasz o globalne. Czasami rzeczy takie jak funkcje wątkujące wydają się rozsądną opcją, ponieważ alternatywy mogą być bardziej skomplikowane. Jednak dobrym zwyczajem jest zawsze jawne deklarowanie ich jako globalnych

  def flashLed (e, t): "" "migają podaną diodę co sekundę" "" globalnym kolorem, a nie e.isSet ( ):  

ponieważ na pewnym etapie spróbujesz przypisać do zmiennej i będziesz miał trudności ze zrozumieniem, dlaczego nie wydaje się to mieć żadnego efektu.

Możesz przekazują argumenty do funkcji, które są zmieniane przez inne części twojego programu lub są zmieniane przez twoją funkcję, ale argumenty muszą być obiektami, które są modyfikowalne. Najłatwiejszym przykładem może być lista, wtedy otrzymasz, tylko trochę sztuczny:

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

Gdybyś miał obszerniejsze informacje do komunikacji między dwoma wątkami, lista mogłaby wydawać się bardziej logiczna. Kolejki są również dość proste w użyciu i warto je sprawdzić w dokumentacji.

#5
+1
developius
2015-03-25 16:22:02 UTC
view on stackexchange narkive permalink

Mógłbyś zrobić coś takiego:

  while True: if newMail (): # zwraca true if new mail, false if not flashLED ("green") else: flashLED ("red ") def flashLED (color): if color ==" red ": pin = 18 # zamień numer na numer GPIO if color ==" green ": pin = 24 # zamień numer na numer GPIO GPIO.output (pin, True) # zamień pin na numer GPIO time.sleep (1) GPIO.output (pin, False)  

Zaletą tego jest to, że nie ma tu żadnego wątku. Musiałbyś zbudować newMail () samodzielnie, chyba że w bibliotece jest dostępna podobna funkcja ( ta odpowiedź zawiera rozwiązanie dla Gmaila i POP)

Dzięki za wskazówkę. Ale jeśli się nie mylę, to tylko raz zamrugnie diody, a następnie wyjdzie z funkcji. Miałem nadzieję, że dioda LED zacznie migać, zacznie migać, gdy wykonuję inne zadania, a następnie przestanę migać na późniejszy sygnał. Wygląda na to, że może to faktycznie wymagać osobnego wątku
Ten kod sprawi, że dioda LED będzie migać raz za każdym razem, gdy wykonywana jest pętla. Jeśli chcesz wykonać inne zadania, po prostu umieść je po if / else.


To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...