uasyncio run cancel tasks interrupt

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
vahithosan
Posts: 19
Joined: Wed Jul 26, 2017 5:15 pm

uasyncio run cancel tasks interrupt

Post by vahithosan » Tue Jan 25, 2022 3:41 pm

Hi. I want to create a menu using uasyncio.

I want to write a separate function for each submenu.
When I press the button, I need to start the other task with the callback function.
however, the previous task must be stopped.
Here my codes
I get errors about cancel.
What should I do.

Code: Select all

MicroPython v1.18 on 2022-01-17; ESP32 module with ESP32

Code: Select all

>>> uasyncio.__version__
(3, 0, 0)

Code: Select all

import pcd8544_fb
from machine import Pin, SPI, Timer
from rotary_irq_esp import RotaryIRQ
import time
import uasyncio
from machine import Timer

a1 = None
m1 = None
m2 = None
t1 = None

r = RotaryIRQ(pin_num_clk=34,
            pin_num_dt=35,
            min_val=0,
            max_val=3,
            reverse=False,
            range_mode=RotaryIRQ.RANGE_WRAP)

spi = SPI(1)
spi.init(baudrate=2000000, polarity=0, phase=0)
cs = Pin(15)
dc = Pin(4)
rst = Pin(27)

lcd = pcd8544_fb.PCD8544_FB(spi, cs, dc, rst)
sw = Pin(39,Pin.IN)

async def menu1_as(r):
    print("Menu1 ok")
    sw.irq(handler=None)
    sw.irq(trigger=Pin.IRQ_RISING, handler=menu2)
    while True:
        if r.value()==0:
            lcd.fill(0)
            lcd.fill_rect(0,0,84,7,1)
            lcd.text("   MENU1  ", 0, 0, 0)
            lcd.show()
        await uasyncio.sleep_ms(50)

async def menu2_as(r):
    print("Menu2 ok")
    sw.irq(handler=None)
    sw.irq(trigger=Pin.IRQ_RISING, handler=menu1)
    while True:
        if r.value()==0:
            lcd.fill(0)
            lcd.fill_rect(0,0,84,7,1)
            lcd.text("   MENU2  ", 0, 0, 0)
            lcd.show()
        await uasyncio.sleep_ms(50)

async def ana_sayfa():
    sw.irq(trigger=Pin.IRQ_RISING, handler=menu1)
    while True:
        lcd.fill(0)
        lcd.fill_rect(0,0,84,7,1)
        lcd.text(" ANA SAYFA ", 0, 0, 0)
        lcd.show()
        await uasyncio.sleep_ms(50)

async def rotar(r):
    global val_old
    val_old = r.value()
    while True:
        global val_new
        val_new = r.value()
        if val_old != val_new:
            val_old = val_new
            print('result =', val_new)
            val_old = val_new
        await uasyncio.sleep_ms(10)

async def main():
    global a1
    global t1
    t1 = uasyncio.create_task(rotar(r))
    a1 = uasyncio.create_task(ana_sayfa())
    await uasyncio.gather(t1,a1)

def menu1(p):
    global m1
    print("menu1")
    m1 = uasyncio.create_task(menu1_as(r))
    print("olustur1")
    #uasyncio.run(m1)
    print("calistir1")
    a1.close()
    print("m1 kapat")

def menu2(p):
    global m2
    print("menu2")
    m2 = uasyncio.create_task(menu2_as(r))
    print("olustur2")
    #uasyncio.run(m2)
    print("calistir2")
    m1.close()
    print("m2 kapat")

uasyncio.run(main())
when I press the button

Code: Select all

Menu1 ok
menu2
olustur2
calistir2
Traceback (most recent call last):
  File "main.py", line 98, in menu2
AttributeError: 'Task' object has no attribute 'close'
Menu2 ok
menu1
olustur1
calistir1
Traceback (most recent call last):
  File "main.py", line 88, in menu1
AttributeError: 'Task' object has no attribute 'close'

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: uasyncio run cancel tasks interrupt

Post by pythoncoder » Wed Jan 26, 2022 7:01 pm

The clue is in the traceback - it speaks the truth.

A Task instance does not have a close() method - see the code. What are you actually trying to do? Do you want to cancel the task? If so, issue the cancel() method.
Peter Hinch
Index to my micropython libraries.

vahithosan
Posts: 19
Joined: Wed Jul 26, 2017 5:15 pm

Re: uasyncio run cancel tasks interrupt

Post by vahithosan » Thu Jan 27, 2022 7:28 pm

Sorry. I type wrong.

When I press the button, I want to stop the task and start another task.
I want to use callback for this.

Code: Select all

async def main():
    global a1
    global t1
    t1 = uasyncio.create_task(rotar(r))
    a1 = uasyncio.create_task(ana_sayfa())
    await uasyncio.gather(t1,a1)
first ana_sayfa() will start.

I call a function when I press the button.

Code: Select all

def menu1(p):
    global m1
    print("menu1")
    m1 = uasyncio.create_task(menu1_as(r))
    print("olustur1")
    #uasyncio.run(m1)
    print("calistir1")
    a1.cancel()
    print("m1 kapat")
    
sw.irq(trigger=Pin.IRQ_RISING, handler=menu1)
    
but when I press button I am getting runtime error

Code: Select all

RuntimeError: can't cancel self

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: uasyncio run cancel tasks interrupt

Post by pythoncoder » Fri Jan 28, 2022 5:02 pm

It's hard to debug this as there is missing code. There is no asyncio.run() statement, nor a listing for menu1_as().

It is usually a bad idea to use interrupts for pushbutton inputs. Creating and cancelling tasks in an interrupt handler is very likely to cause problems. There is also the problem of contact bounce.

For a solution see this doc and this one for a uasyncio solution using callbacks. These classes solve the problem of contact bounce and interface well with uasyncio tasks.
Peter Hinch
Index to my micropython libraries.

Post Reply