Skip to content

extmod/uasyncio/core.py: Support alternative timebase. #8771

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

peterhinch
Copy link
Contributor

The aim is to support power reduction on STM and possibly other platforms.

The script below, when run on ESP32-S2, reduces current consumption by an order of magnitude compared with pure uasyncio code. In practice the lightsleep time may be changed dynamically to trade off latency against power consumption.

Unfortunately this does not work on STM because during lightsleep the uasyncio timebase stops. In my fork of uasyncio V2 I solved this by conditionally importing a timebase which used the RTC as a timing source. The change in this PR copies this approach.

Demo code:

import uasyncio as asyncio
from machine import lightsleep, Pin
blue_led = Pin(13, Pin.OUT)

async def save_power():
    while True:
        await asyncio.sleep_ms(0)
        lightsleep(50)  # Could be variable

async def flash():
    blue_led(1)
    await asyncio.sleep_ms(20)  # In practice duration is the lightsleep time
    blue_led(0)

async def main():
    asyncio.create_task(save_power())
    while True:
        await flash()
        await asyncio.sleep(3)

try:
    asyncio.run(main())
finally:
    asyncio.new_event_loop()

Current, when powered from a LiPo, reduces from ~22mA to ~2mA.

@peterhinch
Copy link
Contributor Author

I have mixed feelings about this PR: the ideal solution is for lightsleep to keep the ticks_ms timer going as per ESP32-S2 and RP2 (#8832). Is this possible on STM?

There may be other applications for alternative timebases such as high precision timebases for long duration scheduling.

@dpgeorge
Copy link
Member

Is this possible on STM?

Yes, if upon waking from lightsleep the system adds the correct amount of time that has elapsed to ticks_ms.

@dpgeorge
Copy link
Member

Unfortunately this won't work with the C version of Task implemented in moduasyncio.c, because that code is hard-coded to use mp_hal_ticks_ms().

Also, it would be better if IOQueue.wait_io_event() did the actual lightsleep, because it's the point at which all waiting decisions are made. The call self.poller.ipoll(dt) is the crux of uasyncio. You could override this by monkey patching this wait_io_event(), maybe like this (untested):

def wait_io_event_low_power(self, dt):
    machine.lightsleep(10)
    return self.wait_io_event_orig(dt)
import uasyncio
uasyncio.IOQueue.wait_io_event_orig = uasyncio.IOQueue.wait_io_event
uasyncio.IOQueue.wait_io_event = wait_io_event_low_power

(Eventually a more sophisticated uevent module will replace this ipoll(dt) code and hopefully be able to do a lightsleep while waiting for IO events.)

@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Jun 29, 2022
@peterhinch
Copy link
Contributor Author

Closing as it clearly won't work owing to C version of Task.

@peterhinch peterhinch closed this Jul 15, 2022
@peterhinch peterhinch deleted the uasyncio_timebase branch July 15, 2022 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extmod Relates to extmod/ directory in source
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy