Quiero que se encienda un LED, mientras se está trabajando en mi Raspberry. Estoy usando un Thread para el LED en mi script de Python.
El código inicial:
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)
Método para el hilo:
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)
Lógica:
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()
Cuando comienzo el guión y presiono el botón la primera vez, todo funciona y el led parpadea. Pero cuando presiono el botón por segunda vez, sin reiniciar el script, el led no parpadea. Imprimí algunos mensajes de depuración y descubrí que se llama a t.start (), pero por alguna razón no hace nada, tampoco se lanza una excepción. ¿No debe comenzar a parpadear el LED cada vez que presiono el botón nuevamente?
No encontré ningún fallo lógico y confirmo que funciona, pero usé los siguientes cambios:
main_thread
desde adentro if __name__ == '__main__':
GPIO
dentro de este block
. Evite colocar el código que se ejecuta en el inicio fuera de if __name__ == '__main__':
De la documentación: Importación segura del módulo principal Uno debería proteger el “punto de entrada” del progtwig utilizando si __name__ == ‘__main__’:
Se agregó join()
después de working = False
, esto garantizaba que el hilo había terminado antes de volver a iniciarlo.
working = False t.join()
Yo sugeriría cambiar el def flash()
, a lo siguiente:
Usar threading.Event()
lugar de una global Instance
y pasarlo junto con el pinLED
. Esto generaliza el def flash(...)
y permite su uso con diferentes pinLED
, incluso en paralelo. Defina el status
como threading.local()
threadsafe, por lo que los valores de la instancia serán diferentes para los hilos separados.
Por ejemplo:
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)
Cambios en el 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() ...
Probado con Python: 3.4.2