Skip to content

lightsleep on Pico W regression for 1.24.0 #16181

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

Open
jeanlucmongrain opened this issue Nov 8, 2024 · 7 comments
Open

lightsleep on Pico W regression for 1.24.0 #16181

jeanlucmongrain opened this issue Nov 8, 2024 · 7 comments

Comments

@jeanlucmongrain
Copy link

Port, board and/or hardware

PICO W

MicroPython version

Micropython 1.24.0

Reproduction

Micropython 1.23.0 can run that code:

import machine
import time

led = machine.Pin("LED", machine.Pin.OUT)
led.off()

while True:
    print("Loop instance")
    led.on()
    time.sleep(0.1)   
    led.off()
    machine.lightsleep(10000)

it will sleep for 10s.

if you try the same with 1.24.0 there is absolutely no sleep at all. the string Loop instance just appears every 0.1 seconds

Expected behaviour

machine.lightsleep to do something on 1.24.0

Observed behaviour

machine.lightsleep do something on 1.23.0 but not 1.24.0

Additional Information

No, I've provided everything above.

Code of Conduct

Yes, I agree

@jeanlucmongrain
Copy link
Author

related to #16180 16180

@CrabbyPete
Copy link

I got the same result using a regular PICO. Works on 1.23, not on 1.24.1

@scruss
Copy link
Contributor

scruss commented Dec 9, 2024

  • expected behaviour seen on three different Raspberry Pi Pico (RP2040, RP2-B0, RP2-B1 and RP2-B2, no wifi) running v1.24.1
  • observed behaviour seen on a Raspberry Pi Pico W (RP2040, RP2-B2, with wifi) running v1.24.1

@scruss
Copy link
Contributor

scruss commented Dec 9, 2024

I got the same result using a regular PICO. Works on 1.23, not on 1.24.1

Does your Pico say RP2-B1 on the chip, or RP2-B2?

@projectgus
Copy link
Contributor

I posted some explanation of this in one of the linked PRs that's since closed, but here's what is happening (mostly copied from #16431):

lightsleep() behaviour has always been to "sleep for the allotted time unless woken by an interrupt first". This issue was introduced in 74fb42a (#13329) when we switched away from the pico-sdk alarm pool for soft timers and unintentionally made soft timer expiry a wakeup source.

Before 74fb42a (including V1.23), both the pico-sdk alarm pool and the lightsleep wakeup timer use alarm 3. The lightsleep timer would quietly clobber alarm 3's timeout, meaning softtimer events wouldn't wake the chip from lightsleep.

After 74fb42a (including V1.24), soft timer wakeup happens on timer alarm 2 so this interrupt can wake the chip from light sleep. On PICO-W builds this happens every lwIP tick (64ms), which is unexpected and prevents lightsleep from sleeping more than 64ms.

We could change the code back so that soft timer isn't a wakeup source, or make this configurable. However, I think the happy path for most users will be to stop the the lwIP tick (or timers) when there aren't any active network interfaces. That would mean lightsleep+wifi would work (lightsleep stills exit earlier, but wifi stays up with minimal power consumption), however if you instead disconnect wifi then lightsleep would run until something else woke it up or it hits the timeout.

This work has gotten intertwined with some related pico-sdk sleep problems, but now those are approaching resolution (see #16454) then it's probably a good time to revisit it.

@madozu
Copy link

madozu commented Apr 30, 2025

I consider the proposal from @projectgus to be a really good solution:

However, I think the happy path for most users will be to stop the the lwIP tick (or timers) when there aren't any active network interfaces. That would mean lightsleep+wifi would work (lightsleep stills exit earlier, but wifi stays up with minimal power consumption), however if you instead disconnect wifi then lightsleep would run until something else woke it up or it hits the timeout.

This would bring back the possibility to lightsleep for >64ms (with WiFi turned off) as it was with <=1.23.0. The Pico_W guys can go back to 1.23 ... but for the Pico2_W there is currently no solution, so this proposal is even more important for those wanting to use a Pico2_W in low power-consumption scenario.

Is there any work going on to stop the the lwIP tick/timers when there aren't any active network interfaces?

@cpottle9
Copy link
Contributor

I will weigh-in on @projectgus and @madozu recent comments.

I don't seem much point in calling lightsleep() while the wifi radio is active.
The wifi radio consumes much more power than lightsleep saves.

When I run the following fragment on a RPI Pico W power consumption (measured on USB)
jumps from 19.2 milli-amps eventually stabilizing at 52.2 milli-amps.

from network import WLAN, STA_IF
from rp2 import country
from time import sleep_ms
country('ca')
wlan=WLAN(STA_IF)
wlan.active(True)
wlan.connect('my_ssid', 'my_password')
sleep_ms(10000)

Running on a RPI Pico (where lightsleep works) I measure a power consumption drop
of from 19.9 milli-amps to 4.96 milli-amps.

For an application running from battery it makes sense to shutdown WIFI and the CYW43 chip first.
Only after that call lightsleep.

Having said that, I agree with @projectgus about the 'happy path'.

@dpgeorge dpgeorge added this to the release-1.26.0 milestone May 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
8 participants