So, I've been working on an LED strip connected to my raspberry pi 4, and I've got TouchOSC working between the Pi and my phone. The current problem I'm having is when a toggle button I've pressed is turned off, the program it's designated to run continues running. I have a global variable that's supposed to determine if the "while" loop continues, but instead of setting the button state to zero and terminating the program, it continues to run until it's interrupted by a Ctrl C in the terminal. I was wondering if anyone would happen to know why the program doesn't stop when the button state is change.
def twinkleBtn(path, tags, args, source):
global twinkleState
twinkleState = int(args[0])
if twinkleState:
turnOff(strip)
while twinkleState:
twinkleTest(strip, False, 10)
if not twinkleState:
turnOff(strip)
This is triggered when the twinkle button is pressed, but the program continues to run when I toggle it back to zero. Below is the code to the function "twinkleTest"
def twinkleTest(strip, onlyOne, count, wait_ms=50):
setPixels(Color(0, 0, 0))
for i in range(count):
strip.setPixelColor(randint(0,LED_COUNT), Color(170, 180, 30))
strip.show()
time.sleep(wait_ms/250.0)
if (onlyOne):
setPixels(Color(0,0,0))
time.sleep(wait_ms/500.0)
I'm not sure if I'm just clueless or what exactly is being done wrong here. I'm pretty new to Python so it may not be the best. Thanks for any help!
CodePudding user response:
Here is a simple threading solution. A thread waits on a threading.Event
. twinkleTest
is called whenever the event is set. The GUI sets the event, and twinkling will happen in the background until the button is pressed a second time to stop the twinkling.
import threading
def twinkleTest(strip, onlyOne, count, wait_ms=50):
setPixels(Color(0, 0, 0))
for i in range(count):
strip.setPixelColor(randint(0,LED_COUNT), Color(170, 180, 30))
strip.show()
time.sleep(wait_ms/250.0)
if (onlyOne):
setPixels(Color(0,0,0))
time.sleep(wait_ms/500.0)
def twinkler(twinkleEvent):
"""Call twinkleTest whenever the given twinkleEvent event is set
and keeps calling until the event is cleared. Designed to be used in
a separate thread."""
while True:
twinkleEvent.wait()
twinkleTest(strip, False, 10)
def setup_twinkle_daemon_thread():
"""Creates a daemon thread to twinkle screen whenever an event is set.
Returns event, threadhandle"""
twinkleEvent = threading.Event()
twinkleThread = threading.Thread(target=twinker, args=tuple(twinkleEvent))
twinkleThread.daemon = True
twinkleThread.start()
return twinkleEvent, twinkleThread
# controls twinkler
twinkleEvent = twinkleThread = None
def twinkleBtn(path, tags, args, source):
global twinkleEvent, twinkleThread
if twinkleEvent is None:
# start daemon thread on first use
twinkleEvent, twinkleThread = setup_twinkle_daemon_thread()
if twinkleEvent.is_set():
twinkleEvent.clear()
else:
twinkleEvent.set()