2017-03-10 4 views
1

Ich möchte eine LED blinken lassen, während auf meinem Raspberry etwas gearbeitet wird. Ich verwende einen Thread für die LED in meinem Python-Skript.Eine Methode mehrmals mit mehreren Threads aufrufen

Der Anfangscode:

import RPi.GPIO 
import time 
import threading 

pinLED = 10 
pinButton = 12 

GPIO.setmode(GPIO.BOARD) 
GPIO.setup(pinLED, GPIO.OUT) 
GPIO.setup(pinButton, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 
GPIO.output(pinLED, 0) 

Verfahren zum Thema:

working = False 
def flash(): 
    status = 0 
    while working: 
     time.sleep(0.5) 
     if status == 0: 
      GPIO.output(pinLED, 1) 
      status = 1 
     else: 
      GPIO.output(pinLED, 0) 
      status = 0| 
    GPIO.output(pinLED, 0) 

Logic:

try: 
    while True: 
     time.sleep(0.02) #found out that 0.02 is a good value to get every tiny button push and save resources 

     if GPIO.input(pinButton) == 1: 
      t = threading.Thread(target=flash) 
      working = True 
      t.start() 

      time.sleep(5) #work would be here 
      working = False 
      t.join() 

except Exception as e: 
    print(e) 
finally: 
    GPIO.cleanup() 

Als ich das Skript starten und die Taste zum ersten Mal drücken, alles funktioniert und die LED blinkt. Aber wenn ich die Taste ein zweites Mal drücke, ohne das Skript neu zu starten, blinkt die LED nicht. Ich habe einige Debug-Nachrichten ausgedruckt und herausgefunden, dass t.start() aufgerufen wird, aber aus irgendeinem Grund tut es nichts, auch keine Exception wird ausgelöst. Wann blinkt die LED nicht jedes Mal, wenn ich die Taste erneut drücke?

Antwort

1

Ich fand keine Logik Fehler und ich bestätigen es funktioniert, aber verwendet, um die folgenden Änderungen:

  1. die main_thread Ausgehend von innen if __name__ == '__main__':.
    Ich schlage vor, auch alle GPIO Anrufe innerhalb dieser block zu bewegen.

Vermeiden Code platzieren, die außerhalb von if __name__ == '__main__':

Von der Dokumentation beim Start ausgeführt wird: Sicher Import von Hauptmodul Man sollte durch die Verwendung, wenn der „Einstiegspunkt“ des Programms schützen __name__ == '__main__':

  1. Added join() nach working = False, dies garantiert, dass der Thread beendet wurde, bevor er erneut gestartet wird.

    working = False 
    t.join() 
    

Ich würde vorschlagen, die def flash() an folgende Änderungen:
Mit threading.Event() anstelle eines global Instance und vorbei mit dem pinLED zusammen. Dies verallgemeinert die def flash(...) und erlaubt ihre Verwendung mit verschiedenen pinLED, sogar parallel. Definieren Sie status als threading.local() threadsafe, sodass die Werte der Instanz für separate Threads unterschiedlich sind.
Zum Beispiel:

def flash(pinLED, flashing): 
    status = threading.local() 
    status.LED = False 
    while flashing.is_set(): 
     status.LED = not status.LED 
     GPIO.output(pinLED, int(status.LED)) 
     time.sleep(0.5) 

    GPIO.output(pinLED, 0) 

Änderungen an die main_thread:

def main_thread(): 
    flashing = threading.Event() 
    flashing.clear() 

    try: 
     while True: 
      time.sleep(0.02) 
      if GPIO.input(pinButton) == 1: 
       t = threading.Thread(target=flash, args=(pinLED, flashing,)) 
       flashing.set() 
       t.start() 

       time.sleep(2) # work would be here 

       flashing.clear() 
       t.join() 
    ... 

mit Python Getestet: 3.4.2

+0

Ja, die if-Anweisung sollte innerhalb der while-Schleife liegen, ich habe sie korrigiert. Ich wollte nicht, dass der Thread die ganze Zeit aktiv ist, weil vielleicht einmal am Tag die Taste gedrückt wird und ich nicht die Ressourcen für den Thread die ganze Zeit verschwenden möchte. – no0by5

+0

Es funktioniert, vielen Dank! Hoffe, ich habe deine Antwort richtig als Arbeit angekreuzt, ich bin ziemlich neu in stackoverflow. Kommentiere nur, wenn ich es falsch gemacht habe. – no0by5