问题
I want a LED to flash, while some work is beeing done on my Raspberry. I am using a Thread for the LED in my Python script.
The initial code:
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)
Method for the Thread:
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()
When I start the script and press the button the first time, everything is working and the led is flashing. But when i press the button a second time, without restarting the script, the led isn't flashing. I printed some debug messages and found out, that t.start() is called, but for some reason it's doing nothing, also no Exception is thrown. Shouln't the LED start flashing every time I press the button again?
回答1:
I found no logic fault and i confirm it works, but used the following changes:
- Starting the
main_threadfrom insideif __name__ == '__main__':.
I suggest to move also allGPIOcalls inside thisblock.
Avoid placing code that is executed on startup outside of if __name__ == '__main__':
From the docs: Safe importing of main module One should protect the “entry point” of the program by using if __name__ == '__main__':
Added
join()afterworking = False, this guaranteed the thread has terminated befor starting it again.working = False t.join()
I would suggest to change the def flash(), to the following:
Using threading.Event() instead of a global Instance and passing it together with the pinLED.
This generalizes the def flash(...) and allow its use with different pinLED, even parallel.
Define status as threading.local() threadsafe, so instance’s values will be different for separate threads.
For instance:
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)
Changes to the 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()
...
Tested with Python:3.4.2
来源:https://stackoverflow.com/questions/42723636/calling-a-method-several-times-with-several-threads