Replies: 2 comments 36 replies
-
I do not know the details of your project, but if what you want is to mix an interrupt trigger and three async functions, then you might find the following script useful: import asyncio
from time import sleep, sleep_ms
from machine import Pin, disable_irq, enable_irq
value,state = True,None
go,counter = 0,-1
led = Pin(2, Pin.OUT)
led.value(0)
button = Pin(32,Pin.IN,Pin.PULL_DOWN)
def func(v):
global value,counter,go,state
state = disable_irq()
if go == 0:
counter+=1
go=counter%2+1
value = 0 if value else 1
enable_irq(state)
button.irq(trigger=Pin.IRQ_RISING, handler=func)
async def prog_1():
global go, state
while True:
if go==1:
print('program 1')
go=0
await asyncio.sleep(1)
async def prog_2():
global go, state
while True:
if go==2:
print('program 2')
go=0
await asyncio.sleep(1)
async def main():
global counter, value, go
while True:
led.value(value)
if counter>1000000: counter=-1
await asyncio.sleep(2)
asyncio.run(asyncio.gather(main(), prog_1(), prog_2())) The running log shows: MicroPython v1.23.0 on 2024-06-02; Generic ESP32 module with ESP32
Type "help()" for more information.
>>> import my_p15802
program 1
program 2
program 1
program 2
program 1
program 2
program 1
program 2
program 1
program 2
program 1
... |
Beta Was this translation helpful? Give feedback.
-
From my understanding of your use case, I believe it is easily achieved. However, whether you use asyncio or not, your needs require that prog1 and prog2 are written to stop themselves when asked. Note of clarification:
In either case, you need to write prog1 and prog2 to work cooperatively, eg. so that they will hear and accept a request to stop/pause. If you write an infinite loop into either, they are not working cooperatively. If you want it to work even when either prog behaves uncooperatively, you need a pre-emptive strategy (ie. one that forces a task to end or pause). You can use threads to achieve that (but it has traps for the inexperienced and limitations on interacting with hardware from both threads on some platforms). If your progs can work cooperatively and you really do want to launch you progs on each button press, a really simple non-asyncio solution can be: stop_prog: bool = False
def func(v):
global stop_prog
stop_prog = True
button.irq(trigger=Pin.IRQ_RISING, handler=func)
while True:
time.sleep_ms(100) # Switch debounce delay
stop_prog = False
prog1()
time.sleep_ms(100) # Switch debounce delay
stop_prog = False
prog2() You need to write your prog1 and prog2 to periodically check the while not stop_prog:
print("prog 1")
No. prog1 and prog2 run until they are stopped, but they may yield to each other whenever one makes an
Yes. If you want to be able to pre-emptively kill or pause a prog unconditionally, you will need something else, eg. threads or just a soft or hard reset. asyncio (and my solution above) rely on cooperation beteween the tasks. Unless you really have no control over the code for prog1 and/or prog2, it is much simpler just to use the non-asyncio method suggested above. If you need asyncio for other reasons, you can make that work too, but you need to be careful to ensure |
Beta Was this translation helpful? Give feedback.
-
Hi,
I started working on my project again. As a reminder, I want two independent programs to be able to be launched alternately each time a button is pressed..
The demo version works thanks to your help.
I added an Irq trigger to handle the push button
However, I wanted to go further and I'm stuck.
Demo version:
First question:
in this example, does prog_1 (or prog_2) run for the duration of the main coroutine's asyncio.sleep(2) wait, exit, and start again?
If so, this is not what I want
Second question:
If I run a program with an infinite loop, the button has no effect anymore
coroutine prog_1
program_1
Do you think what I want to do is possible?
Beta Was this translation helpful? Give feedback.
All reactions