Skip to content

lightsleep() not working properly Pi Pico WH v1.24.0 #16180

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
RYoder97 opened this issue Nov 7, 2024 · 16 comments
Open

lightsleep() not working properly Pi Pico WH v1.24.0 #16180

RYoder97 opened this issue Nov 7, 2024 · 16 comments

Comments

@RYoder97
Copy link

RYoder97 commented Nov 7, 2024

Port, board and/or hardware

Raspberry Pi Pico WH

MicroPython version

MicroPython v1.24.0 on 2024-10-25; Raspberry Pi Pico W with RP2040

Reproduction

Attempt following code, both with lightsleep() having no ms argument and one with:

import machine
from machine import Pin, deepsleep, lightsleep

def wake_up(pin):
    # Handle wake-up logic here
    led.toggle()
    print("Button pressed, waking up!")

# Configure buttons
button = Pin(11, Pin.IN, Pin.PULL_UP) # Example pin
led    = Pin(20, Pin.OUT)

led.on()

# Set up interrupt
button.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=wake_up)

# Go to sleep until a button is pressed
lightsleep()

Expected behaviour

Expect LED to react to button press when asleep and execute wake_up function. LED is on by default. LED should toggle/turn off when button is pressed down, both when machine is asleep and not asleep.

Observed behaviour

USB power tester indicates that the board sleeps only when NO MILLISECONDS ARGUMENT IS SPECIFIED.

When milliseconds ARE SPECIFIED, board does not appear to sleep as power consumption does not drop according to the USB tester. The board continues to work at full power, and the LED reacts to the button.

When NO MILLISECONDS ARE SPECIFIED, board appears to go to sleep (reducing power from >10ma to 0-1ma. But button does not do anything to LED.

Additional Information

I have tried adding the wake argument to button.irq, but Micropython says that extra keyword arguments are present.

I understand sleeping may have issues on the Pico W models. I have also tried turning off WiFi/setting the pin associated with Wifi to "low". That does not seem to have any impact whatsoever, since my code never explicitly turns Wifi on

https://forums.raspberrypi.com/viewtopic.php?p=2266590#p2266590

Code of Conduct

Yes, I agree

@RYoder97 RYoder97 added the bug label Nov 7, 2024
@jeanlucmongrain
Copy link

jeanlucmongrain commented Nov 8, 2024

@RYoder97

lightsleep do not work at all

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)

Which is much more simple use case, do not works. There is no sleep at all while executing machine.lightsleep(10000) it just loop immediately

tested on a Pico W and 1.24 and 1.25 latest snapshot

@jeanlucmongrain
Copy link

@RYoder97 I just tried Micropython 1.23.0 and lightspeed works as expected

@RYoder97
Copy link
Author

RYoder97 commented Nov 8, 2024

I'm sorry, forgive me because I'm new to Micropython still...
I've tried 2 Pico boards, but that example you posted just now... Does the sleeping need to happen in a loop?

@jeanlucmongrain
Copy link

jeanlucmongrain commented Nov 8, 2024

@RYoder97 this is just a proof of concept to reproduce the bug, it's to prove that on 1.24.0 and more recent lightsleep never do anything

@RYoder97
Copy link
Author

RYoder97 commented Nov 8, 2024

@RYoder97 this is just a proof of concept to reproduce the bug, it's to prove that on 1.24.0 and more recent lightsleep never do anything

Ah okay! So I'm not going crazy! I tried 1.22.2 and 1.23.0 and it works. However, you still need to specify a time otherwise the Pi Pico will be permanently asleep. This is less than ideal, but a workaround would be to set the time for a long time, or, set it for a long time and put it to sleep again after it wakes up. If a contributor is able to update the source code for the next release though, it would be greatly appreciated.

@ssotheremail
Copy link

I hit something similar before I saw this issue. For me its ok as is with 1.24.0 on pico 1. On a Pico 2 the 1st lightsleep does not work. if I comment out the time.sleep(0.1) in the example below, then both lightsleeps work fine. Hope this helps pin it down.

import machine
import time

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

while True:
led.on()
time.sleep(0.1)
machine.lightsleep(10000)
led.off()
machine.lightsleep(10000)

@cgm999
Copy link

cgm999 commented Nov 11, 2024

I am seeing same issue on Rpi PICO-W (rp2040) .. lightsleep is broken starting with 1.24 up to latest commit (tested a few days ago so not sure if something got fixed since then)

@cpottle9
Copy link
Contributor

cpottle9 commented Dec 12, 2024

I did some investigation into this and reported my findings in discussion https://github.com/orgs/micropython/discussions/12573.

The main point I noted there is the micropython documentation for machine.lightsleep() is clear that it can return early.
https://docs.micropython.org/en/latest/library/machine.html

If time_ms is specified then this will be the maximum time in milliseconds that the sleep will last for. 
...
With or without a timeout, execution may resume at any time if there are events that require processing.

Between 1.23.0 and 1.24.0 commit 74fb42a added use of rp2040 hardware timer 2.

When hardware timer 2 expires lightsleep() will return.
Based on the documentation, the 1.24.0 behavior is not a bug.

My testing, as I reported in the discussion indicates lightsleep() average sleep is about 60 milliseconds.

Users who need to sleep for an exact amount of time need to call lightsleep() in a loop.
Something like:

from time import ticks_ms, ticks_diff
from machine import lightsleep

def my_lightsleep(time_ms) :
    before_tick = ticks_ms()
    after_tick = before_tick
    sleep_ms = time_ms
    while sleep_ms > 0 :
        sleep_ms = time_ms - ticks_diff(after_tick, before_tick)
        if sleep_ms > 0 :
            lightsleep(sleep_ms)        
            after_tick = ticks_ms()

@ssotheremail
Copy link

ssotheremail commented Dec 13, 2024

Thanks for looking into it, cpottle9, and everyone else too for their time considering these issues. The work by cpottle9 raises some interesting questions. I do not know as much as others do about the code but, sticking to the original issue on the pico w :

  1. Are we suggesting that pre 1.24.0 lightsleep was not giving correct results or has the documentation changed for 1.24.0?

  2. Unless I am mistaken/misinterpreting (please forgive me if so), elsewhere I have seen references to the non W pico with 1.24.0 behaving like it does with 1.23.0 e.g. scruss:

I'm surprised that you're seeing this on a regular non-wireless RP2040 Pico. I can only make the example code on the issue #16181 fail on a Pico W, not on a Pico

He also highlighted:

a lot has changed in lightsleep, seemingly mostly to allow for the wifi to sleep gracefully and any USB devices to be dealt with.

So are we suggesting that lightsleep is/will be intentionally different for a Pico and a PicoW?

  1. The next bit of the document for lightsleep says:

Such events, or wake sources, should be configured before sleeping, like Pin change or RTC timeout.

To me, this suggests that you can voluntarily set up such things if you want to interrupt the sleep, if you don't it will wake up when you asked it.

  1. What are the timer changes in 74fb42a meant to do , why were they introduced in 1.24.0 and are they working correctly? Was it intentional to change lightsleep behaviour?

There seems to me to be some overlapping issues here that are making even understanding the implications of the differences between different hardware and different software versions more difficult. Obviously, sorry if I am missing something and wasting peoples time.

@cpottle9
Copy link
Contributor

cpottle9 commented Dec 13, 2024

@ssotheremail, first I am a user of micropython and PICO W like you.
I did submit one minor change to micropython a little over a year ago, so I have some limited understanding of micropython internals. I have loads of experience coding in C.
I have an interest in reducing the power consumed by PICO so my applications can run from battery for a longer time.
That is why I've looked at lightsleep in the past.

I will do my best to answer you questions. @projectgus would provide better answers.
He submitted 74fb42a and made changes to lightsleep to fix issues when USB is active.

  1. No, I am not suggesting lightsleep() in 1.23.0 was incorrect. From the documentation lightsleep() can return early or it can return on time. If it returned late that would be a bug.
  2. I can't comment on non-W PICO behavior. I only have PICO W. Having said that, I did turn off the WIFI block and I still see lightsleep() returning early. Also, I do not have an PICO2 boards.
  3. You raise a good point. This section does imply that only events configured in micropython code are of concern. The code in 74fb42a is written in C and the event is handled in C.
  4. No, I do not think the changes in 74fb42a were intended to change lightsleep behavior. But that is a guess on my part. I still assert the new behavior is not a bug.

@cpottle9
Copy link
Contributor

Quick update. I submitted a pull request to issue #16181 that addresses the problem of lightsleep returning early.
That pull request does nothing to help with Pin interrupts waking lightsleep.

I posted on the raspberry pi forum https://forums.raspberrypi.com/viewtopic.php?t=380979 expressing my opinions about lightsleep on PICO.
Take a look.

@projectgus
Copy link
Contributor

projectgus commented Dec 17, 2024

Apologies, I missed this issue when it was opened. Thanks @cpottle9 for the investigation and the heads-up.

There's a more detailed explanation in the PR, but one of the root causes here is that before v1.24 the MicroPython soft timer expiring did not wake the rp2 from lightsleep. Commit 74fb42a (released in V1.24) accidentally changed this so that soft timer did wake the rp2 from lightsleep, and on the PICO_W board there is a wakeup for lwIP every 64ms. So, effectively, this limited the max lightsleep time to 64ms. Draft PR with the fix, so soft timer doesn't wake from lightsleep any more, is #16431.

I don't expect that PR will resolve everything reported here, in particular a pin irq not waking from machine.lightsleep() seems like something else.

@projectgus
Copy link
Contributor

projectgus commented Dec 18, 2024

When NO MILLISECONDS ARE SPECIFIED, board appears to go to sleep (reducing power from >10ma to 0-1ma. But button does not do anything to LED.

There is an older issue tracking this at #7035 . I've just left a comment there and opened another draft PR.

I think the still-open issues #16181 and #7035 are tracking everything reported in this issue. Does that seem correct? (EDIT: Rephrased this.)

@ssotheremail
Copy link

Thanks for all this work. Just had a quick check with RPI_PICO2-20241218-v1.25.0-preview.125.gd10cda66d.uf2 in case the fixes have come through and the same versions for pico and pico w (cant see previews for pico 2 w).
Pico - lightsleep(5000) still ok
Pico W lightsleep(5000) 64ms
Pico 2 lightsleep(5000) ok, except when preceeded by a sleep(nn). e.g. sleep(5)
If the fixes are not in RPI_PICO2-20241218-v1.25.0-preview.125.gd10cda66d.uf2 etc can you say when it will be worth retesting, please?

@ssotheremail
Copy link

ok, as its nearly Christmas, I have finally put the effort into fixing my micropython build problems on my pi 5 (I still cant do pico2W but never mind for now.....) I have managed to build 1.25.0.preview130 for the others so now:
Pico - lightsleep(5000) still ok
Pico W lightsleep(5000) 64ms
Pico 2 loaded to 2(led flashes) and 2W(led does not flash) lightsleep(5000) ok, except when preceeded by a sleep(nn). e.g. sleep(5) - not sure whether 2W result is useful.
Am I still too early to test?

Child to Adult: How many sleeps till Christmas?
Adult: Who knows? They are lightsleeps on a Pico.......

Sorry.

@projectgus
Copy link
Contributor

If the fixes are not in RPI_PICO2-20241218-v1.25.0-preview.125.gd10cda66d.uf2 etc can you say when it will be worth retesting, please?

Sorry for the confusing messaging, I've edited my previous post to clarify what I meant. At the moment no fixes have been merged, so the preview builds won't be any different.

If you care in particular about lightsleep with a timeout then I suggest watching #16181. When that issue closes then the next preview build after that should have the relevant fix in it.

@jonnor jonnor added the port-rp2 label Mar 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants