machine.idle() during await uasyncio.sleep()?

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
User avatar
on4aa
Posts: 70
Joined: Sat Nov 11, 2017 8:41 pm
Location: Europe
Contact:

machine.idle() during await uasyncio.sleep()?

Post by on4aa » Sun Jan 21, 2018 4:34 pm

Here is a simple question:
When calling an await uasyncio.sleep(), does this put the MCU in idle?

Putting an explicit machine.idle() right above an await uasyncio.sleep() line will result in the latter never to be executed. So, that is not a solution to save some power.
Serge

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

Re: machine.idle() during await uasyncio.sleep()?

Post by pythoncoder » Mon Jan 22, 2018 5:33 am

No, the scheduler continues to run. If one task issues a sleep the presumption is that other tasks are also queued for scheduling and may be granted execution. For example another task's sleep may come to an end first.

A power-saving adaptation to uasyncio is an interesting proposition, but it would need some serious thought ;)

However if your application can sleep for extended periods you could design it so that the scheduler stops (run_until_complete), the unit goes to sleep, with wakeup restarting the scheduler.

[EDIT]
I've given a little thought to the idea of a power saving scheduler. One problem is the IORead mechanism. Pending coroutines are stored in a queue sorted on time due. So the task at the top of the queue is always the first to be scheduled. The scheduler checks the time due of the topmost task and waits for that period. However the method which does this waiting (EventLoop.wait) is handled by the PollEventLoop subclass which polls stream I/O devices. So the C code which does this (moduselect.c) would need to be adapted.

Alternatively if an application did not require the IORead mechanism EventLoop could be subclassed with a modified wait method which would use a low power mode.
Peter Hinch
Index to my micropython libraries.

User avatar
on4aa
Posts: 70
Joined: Sat Nov 11, 2017 8:41 pm
Location: Europe
Contact:

Re: machine.idle() during await uasyncio.sleep()?

Post by on4aa » Mon Jan 22, 2018 5:35 pm

pythoncoder wrote:
Mon Jan 22, 2018 5:33 am
However if your application can sleep for extended periods you could design it so that the scheduler stops (run_until_complete), the unit goes to sleep, with wakeup restarting the scheduler.
That would indeed be a more clever solution.
It is still very tricky, though. Having the Pyboard lingering in machine.idle() broke my USB connection without any opportunity to connect again using rshell.
Eventually, I had to put the Pyboard into safe mode.

As an absolute beginner, I am really missing seeing some more examples of uasyncio or threading loops for that matter.
Serge

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

Re: machine.idle() during await uasyncio.sleep()?

Post by pythoncoder » Tue Jan 23, 2018 9:05 am

on4aa wrote:
Mon Jan 22, 2018 5:35 pm
As an absolute beginner, I am really missing seeing some more examples of uasyncio or threading loops for that matter.
For a simple start with uasyncio try this script which flashes the four Pyboard LED's at arbitrary independent frequencies for a period, then quits.

Code: Select all

import pyb
import uasyncio as asyncio

async def killer(duration):
    await asyncio.sleep(duration)

async def toggle(objLED, time_ms):
    while True:
        await asyncio.sleep_ms(time_ms)
        objLED.toggle()

def test(duration):
    loop = asyncio.get_event_loop()
    duration = int(duration)
    if duration > 0:
        print("Flash LED's for {:3d} seconds".format(duration))
    leds = [pyb.LED(x) for x in range(1,5)]  # Initialise all four on board LED's
    for x, led in enumerate(leds):           # Create a coroutine for each LED
        t = int((0.2 + x/2) * 1000)
        loop.create_task(toggle(leds[x], t))
    loop.run_until_complete(killer(duration))
    loop.close()

test(10)
The point here is that the single coroutine toggle can be instantiated four times with each instance running "in parallel", providing an illusion of concurrency. This is trivially scalable to any number of LED's whereas a single synchronous loop would tend to become ever more complex. Note also the concurrent killer which causes the test to terminate.

I plan to update my tutorial to improve the beginners' section.

Incidentally the interactions between low power modes and USB communication are nothing to do with uasyncio. There is an introduction to the Pyboard's low power modes here.
Peter Hinch
Index to my micropython libraries.

gpson
Posts: 21
Joined: Sun Jul 31, 2016 6:55 am

Re: machine.idle() during await uasyncio.sleep()?

Post by gpson » Fri Mar 16, 2018 7:16 pm

I am trying tu run the latest asyncio library from PyPi with my pyboard v1.1 and get the error

Code: Select all

Traceback (most recent call last):
  File "main.py", line 24, in <module>
  File "main.py", line 13, in test
  File "uasyncio/core.py", line 224, in get_event_loop
  File "uasyncio/__init__.py", line 21, in __init__
  File "uasyncio/core.py", line 30, in __init__
AttributeError: 'module' object has no attribute 'deque'
MicroPython v1.9.3 on 2017-11-01; PYBv1.1 with STM32F405RG
Type "help()" for more information.
I found your note about the firmware version
The documentation and code in this repository are based on uasyncio version 2.0, which is the version on PyPi. This requires firmware dated 22nd Feb 2018 or later.
On the download page I can not find the 2018 year firmware version for the pyboard.

Where can download it?

gpson
Posts: 21
Joined: Sun Jul 31, 2016 6:55 am

Re: machine.idle() during await uasyncio.sleep()?

Post by gpson » Fri Mar 16, 2018 8:09 pm

nevermind. compiled the latest git firmware version and everything is working

Code: Select all

[INFO] boot.py
Flash LED's for  10 seconds
MicroPython v1.9.3-469-g5edce453 on 2018-03-16; PYBv1.1 with STM32F405RG
Type "help()" for more information.
>>>

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

Re: machine.idle() during await uasyncio.sleep()?

Post by pythoncoder » Sat Mar 17, 2018 5:48 am

The builds on the download page marked (latest) are daily builds so should work fine.
Peter Hinch
Index to my micropython libraries.

Post Reply