uasyncio - How detect the end task in another task.

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.
prem111
Posts: 97
Joined: Sun Feb 23, 2020 3:18 pm

uasyncio - How detect the end task in another task.

Post by prem111 » Wed Jun 17, 2020 6:28 pm

How to detect the end or „is running” of a task that is running in another task. How to detect termination or running task: some_function.run() ?

Code: Select all

async def service1():

    while True:
    ...
    ap_task = uasyncio.create_task(some_function.run())

    await uasyncio.sleep(0)

async def main():

    tasks = (service1, service2)
        res = await uasyncio.funcs.gather(*tasks, return_exceptions=False)

uasyncio.run(main())

kevinkk525
Posts: 781
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio - How detect the end task in another task.

Post by kevinkk525 » Wed Jun 17, 2020 6:30 pm

You currently can't because it is not implemented in the Task class.

But you can gather multiple tasks, that would show their termination.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

prem111
Posts: 97
Joined: Sun Feb 23, 2020 3:18 pm

Re: uasyncio - How detect the end task in another task.

Post by prem111 » Wed Jun 17, 2020 6:36 pm

How to do it ?

kevinkk525
Posts: 781
Joined: Sat Feb 03, 2018 7:02 pm

Re: uasyncio - How detect the end task in another task.

Post by kevinkk525 » Wed Jun 17, 2020 8:57 pm

it works just like in CPython but you can take a look here: https://github.com/peterhinch/micropyth ... UTORIAL.md
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

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

Re: uasyncio - How detect the end task in another task.

Post by pythoncoder » Thu Jun 18, 2020 5:13 am

prem111 wrote:
Wed Jun 17, 2020 6:28 pm

Code: Select all

        [code]res = await uasyncio.funcs.gather(*tasks, return_exceptions=False)
This line should read

Code: Select all

res = await uasyncio.gather(*tasks, return_exceptions=False)
Gather is described here.

I'm not entirely sure what you're trying to achieve, though. Consider the following:

Code: Select all

import uasyncio as asyncio

async def foo():
   for _ in range(5):
       # do something
       await asyncio.sleep_ms(100)  # slow coro

task = asyncio.create_task(foo())
async def bar():
   await asyncio.sleep(1)
   # You can await task if you want to pause until it's run
   # Or test its status as follows
   try:
       await asyncio.wait_for_ms(task, 1)
   except asyncio.TimeoutError:
       print('foo is running')
   else:
      print('foo has stopped')

asyncio.run(bar())
It's perhaps not ideal, but it works here on a Pyboard. See for reference
Peter Hinch

Primesty
Posts: 38
Joined: Sun Jun 28, 2020 11:06 pm

Re: uasyncio - How detect the end task in another task.

Post by Primesty » Tue Jul 21, 2020 12:19 am

Hello,

at the risk of posting this to the wrong topic, I'm looking for some

Code: Select all

uasyncio
help if possible - and I'm not able to create my own topic for some reason.

I have started working with micropython fairly recently, so please forgive my ignorance. I'm trying to implement something similar to matty trentini's uasyncio encoder example (https://gist.github.com/mattytrentini/1 ... b0a4284de9).

More precisely, I'd like to do the following:

1) Use an encoder to change and set (with button push) a specific temperature (let's call it target temperature)
2) Use a DHT22 (and later potentially a thermocouple) to monitor the current temp
3) Alert (either with led, buzzer, etc to the fact that the target temp was reached)
4) Display information on an OLED

I understand that the encoder function and the temperature measurements have to run simultaneously for this to work - this is where

Code: Select all

uasyncio
comes in.

Here is what I have so far

Code: Select all

import uasyncio
from machine import Pin, I2C
import machine
import time
from rotary_irq_esp import RotaryIRQ
import dht


sensor = dht.DHT22(Pin(14))

r = RotaryIRQ(pin_num_clk=12,
              pin_num_dt=13,
              min_val=0,
              max_val=60,
              reverse=True,
              range_mode=RotaryIRQ.RANGE_WRAP)


led = machine.Pin(2, Pin.OUT)

async def blink(led):
    while True:
        led.on()
        await uasyncio.sleep(1)
        led.off()
        await uasyncio.sleep(1)

async def encoder(r):
   val_old = r.value()*0.5
   while True:
    val_new = r.value()*(0.5)
    if val_old != val_new:
            val_old = val_new
            print('result =', val_new)
    await uasyncio.sleep_ms(50)

async def sensor_measure(sensor):
  while True:
      sensor.measure()
      temp = sensor.temperature()
      print('Temperature: %3.1f C' %temp)

      await uasyncio.sleep(5)

loop = uasyncio.get_event_loop()
loop.create_task(blink(led))
loop.create_task(encoder(r))
loop.create_task(sensor_measure(sensor))

# this is now all running at the same time!!! progress!!

loop.run_forever()
Display is not implemented yet. It seems to work BUT everything is running on an endless loop and the editor is showing me an infinite loop of constant temp measurements, which can be interrupted by turning the encoder. What I would like to happen is for the temperature measurements to happen and then when I turn the encoder the value shows up. Do I have to save the temp measurements in a list or variable to be able to compare to the target temperature?

Any help would be greatly appreciated here!

User avatar
jimmo
Posts: 2009
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: uasyncio - How detect the end task in another task.

Post by jimmo » Tue Jul 21, 2020 5:08 am

Primesty wrote:
Tue Jul 21, 2020 12:19 am
What I would like to happen is for the temperature measurements to happen and then when I turn the encoder the value shows up. Do I have to save the temp measurements in a list or variable to be able to compare to the target temperature?
Yep! You need pretty much exactly that.

Think of each of your async tasks as running completely independently. If you want to share data between them then you need some sort of shared variable to contain that data.

A list of measurements that sensor_measure() appends to, then encoder() can access (and reset) when it needs to sounds like a good start.

Primesty
Posts: 38
Joined: Sun Jun 28, 2020 11:06 pm

Re: uasyncio - How detect the end task in another task.

Post by Primesty » Tue Jul 21, 2020 9:37 pm

@jimmo thanks for the quick answer! I'll definitely give that a try. What I don't understand yet is how I break the endless loop I have right now...

Conceptually, it seems the steps should be this:

1) Set target temperature with encoder and commit it to list by pushing button (show on OLED)
2) Run temp measurements (like every 5 seconds) and write into a list (show on OLED)
3) Check target temperature against current temperature from sensor (maybe also every 5 seconds)
4) Once target >= current - sound the alarm (in whatever form; led, buzzer, http, etc.) - maybe also OLED alert

Does that sound logical? For step four, how can I interrupt the ongoing processes and then maybe reset with the push of a button (or maybe simply by turning the encoder to change/set new target temp?)

Please let me know your thoughts and I will post my new attempts here as well.

Thanks a lot!!

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

Re: uasyncio - How detect the end task in another task.

Post by pythoncoder » Wed Jul 22, 2020 7:40 am

I'm not sure why you want to break the endless loop. It's commonplace in firmware applications to have a number of concurrent continuously running loops. For your application I would define a class with data being shared by means of class variables. The coroutines would be methods. One would monitor temperature and control the alarm. One would monitor the encoder. One would debounce the pushbutton (or use the Pushbutton class). Another would control the display.

All these would run forever with suitable asyncio.sleep or asyncio.sleep_ms calls.

You can stop tasks, either by testing a flag or by using the task's cancel method but so far in your explanation of the application I'm unclear why you'd want to do this.
Peter Hinch

Primesty
Posts: 38
Joined: Sun Jun 28, 2020 11:06 pm

Re: uasyncio - How detect the end task in another task.

Post by Primesty » Wed Jul 22, 2020 1:14 pm

Hey Peter,

Thanks for your thorough explanation! I'm new to programming, in micropython especially, and wasn't aware that having processes run on endless loops is common practice :)

Thanks also for your insights of how to structure the app and where to put variables and co-routines! I'll try to implement it that way on the weekend. I assume class variables are 'globally' accessible whereas method variables are only accessible to the function/method, correct?

The way I understand it, there is no real reason to stop the concurrent tasks at all.

Thanks again!

Post Reply