Page 1 of 6

uasyncio - How detect the end task in another task.

Posted: Wed Jun 17, 2020 6:28 pm
by prem111
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())

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

Posted: Wed Jun 17, 2020 6:30 pm
by kevinkk525
You currently can't because it is not implemented in the Task class.

But you can gather multiple tasks, that would show their termination.

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

Posted: Wed Jun 17, 2020 6:36 pm
by prem111
How to do it ?

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

Posted: Wed Jun 17, 2020 8:57 pm
by kevinkk525
it works just like in CPython but you can take a look here: https://github.com/peterhinch/micropyth ... UTORIAL.md

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

Posted: Thu Jun 18, 2020 5:13 am
by pythoncoder
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

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

Posted: Tue Jul 21, 2020 12:19 am
by Primesty
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!

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

Posted: Tue Jul 21, 2020 5:08 am
by jimmo
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.

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

Posted: Tue Jul 21, 2020 9:37 pm
by Primesty
@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!!

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

Posted: Wed Jul 22, 2020 7:40 am
by pythoncoder
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.

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

Posted: Wed Jul 22, 2020 1:14 pm
by Primesty
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!