# async LED effects controller
# non standard primitives from Peter Hinch: https://github.com/peterhinch/micropython-async
# single click button press for next effect
# double-click button press to reset effects
# long button press to turn off effects
from machine import Pin
import uasyncio as asyncio
from pushbutton import Pushbutton
from queue import Queue
async def perm_toggle(led, delay):
print('perm_toggle', delay)
while True:
led.toggle()
await asyncio.sleep_ms(delay)
#funcs is a list of function names, with arguments to use when calling them
funcs = (
(perm_toggle, {"led": led1, "delay": 100}),
(perm_toggle, (led1, 100)),
(print, ('hello', 42))
)
#normal function call equivalents:
funcs[0][0](**funcs[0][1])
==
funcs[0][1](*funcs[1][1])
==
perm_toggle(led=led1, delay=300)
#print example:
funcs[2][1](*funcs[2][1])
OUTPUTS:
'hello 42'
async def led_controller(queue):
print("LED effects controller started...")
print("# single click button press for next effect\n# double-click button press to reset effects\n# long button press to turn off effects")
led1 = machine.Pin(25, machine.Pin.OUT)
funcs = ( # this could be any number of different functions performing NeoMatrix effects
(perm_toggle, {"led": led1, "delay": 100}),
(perm_toggle, {"led": led1, "delay": 300}),
(perm_toggle, {"led": led1, "delay": 650}),
(perm_toggle, {"led": led1, "delay": 1000}),
(perm_toggle, {"led": led1, "delay": 2000}),
(perm_toggle, {"led": led1, "delay": 4000}),
(perm_toggle, {"led": led1, "delay": 7000}),
)
imax = len(funcs) - 1
i = 0
effect = None #init
while True:
qitem = await queue.get()
print('qitem:', qitem)
if qitem == 'next':
if effect != None:
effect.cancel()
effect = asyncio.create_task(funcs[i][0](**funcs[i][1]))
if i == imax:
i = 0
else:
i += 1
elif qitem == 'reset':
if effect != None:
effect.cancel()
effect = asyncio.create_task(funcs[0][0](**funcs[0][1]))
i = 1
elif qitem == 'off':
if effect != None:
effect.cancel()
i = 0
else:
continue #unknown command handling
async def my_app():
queue = Queue()
pin = Pin(17, Pin.IN, Pin.PULL_UP)
pb = Pushbutton(pin)
pb.press_func(queue.put, ('next',)) #single click
pb.double_func(queue.put, ('reset',)) #double click
pb.long_func(queue.put, ('off',)) #long press
task = asyncio.create_task(led_controller(queue,))
while True:
await asyncio.sleep_ms(30000)
print('main still running') #get a command by Bluetooth or some other sensor instead?
asyncio.run(my_app()) # Run main application code