-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Third sleep option: RAM-preserving "deep" sleep #9521
Comments
Have you tested anything of this? For a POC, this could be tested without an API change just to see if it is worth it. If you have any code to test, I would be happy to give it a try. As a side note: there are currently a few issues open regarding sleep-modes (e.g. #9464 or #8977) so IMHO it would make more sense to fix the existing issues first with the existing sleep-modes before comparing results with a new third one. |
The original light-sleep/deep-sleep distinction was based on a misinterpretation of what was preserved in Espressif light sleep. In retrospect, we might have just dropped light sleep. As you mentioned, "Light sleep promises to keep background tasks such as WIFI, BLE, audio playback, etc alive.", which is not necessarily all that useful. So redefining light sleep as RAM-preserving, but not activity-preserving, might be worthwhile. I am not sure that many people even use light sleep now, as it's not that useful. |
I also agree with this proposal. |
My concern with making a light sleep that doesn't preserve activity is that some object state won't be preserved across the light sleep. This will be confusing and it won't be clear what is impacted. If light sleep was smarter, then user code could shut down wifi and audio itself before sleeping and then restart it afterwards. That'd be clearer and fit in the existing API. |
@dhalbert : I am using it in all my battery-based projects, at least for RP2040-based boards replacing Light-sleep is currently not fully activity preserving. One thing I noticed is that driving a ST7789 with backlight set to 0.7 fails during light-sleep, presumably because of the PWM not working as expected. |
@tannewt If I understand correctly, your preferred solution would be such that light sleep automatically determines the most power conserving, ram retaining sleep mode that is possible, given the ongoing background tasks. E.g. on an esp32, if nothing is going on in the background, actual light sleep could be used and if WiFi is still active the current behaviour would be used. Is that correct? As far as I can tell, this would be a valid solution of this issue. |
Yup!
It isn't easy to implement but gives a consistent API across all ports. I'd ignore this complexity first though and just make sure you are getting the power savings you are hoping for. Once you confirm that, then add in things like wifi and ble. You'll probably want a function call
I think it's a matter of whether the light sleep will cause the used peripheral to lose state. If it does, then it should be deinit first by user code so that it is reinit after sleep. Or you could do this automatically. I2C and SPI APIs are blocking so I bet they are fine. pulseio, countio, frequencyio all take data in asynchronously so they'd need to be disabled to sleep if the peripheral is turned off. |
Makes sense 👍 One last thought: While this ensures a consistent API, the actual power consumption achieved by light sleep would become somewhat inconsistent (entering light sleep at different points in the code might result in different power consumptions). And forgetting to deinit a certain peripheral could result in an unexpected higher power consumption. Debugging this could become rather challenging. |
Ya, I think this is a good point. However, I'm not exactly sure how to define when to raise an exception or warning. I always think that folks optimizing power should use a PPK2 to check they are getting the consumption they need. Lots of things on a board (like neopixels) can have a big impact too. Maybe we could add an attribute of "expected light sleep current" that could indicate how low it thinks we can go. Or may an "active power users" list. Some way to know what will impact power without raising an error or warning. That's even more tracking and API though. |
There could be a verbose/debug bool option that before actually entering sleep lists the things that will be disabled and the estimated current use.
But it would be a bit of a pain to estimate the draw of each thing. |
I like that idea but don't think the core code should do it. Storing strings is expensive and printing from within a library is weird. Instead, we could add state that python-level code could read to determine this. |
Yes, all we'd really need is some attr bools in the alarm module to implement this. |
This sounds pretty straightforward. Essentially this would be a python API that internally just accesses the bitmap used in
I'm not sure I understand the idea. To me, e.g. |
|
Yup, then you can introspect relevant state. A library can even verify sleep for you if needed. |
CircuitPython currently supports two sleep modes: Light sleep and deep sleep. Given the specification of the two existing sleep modes, and the capabilities of many microcontrollers supported by CP, I think there is room for one more sleep mode, which would have a clear benefit. Here is my rationale:
But (as far as i can tell) all non-esp microcontrollers that are supported by CP and have the alarm module implemented, have options to preserve RAM contents during deep sleep at the cost of at most a few microamps. Some ports even preserve RAM contents during deep sleep today, but add an artificial reset upon wake. Below is an attempt to summarize the current state of CP regarding this topic.
The benefit would be instant wake, since python code would not have to be re-interpreted after wake. IMO, slow start and wake times are one of the most annoying drawbacks of micropython/circuitpython, and this could be solved by the proposed change.
There are a few options for how the API could look, e.g.:
alarm.deep_sleep_until_alarms()
(in contrast toalarm.exit_and_deep_sleep_until_alarms()
).alarm.exit_and_deep_sleep_until_alarms(skip_reset=True)
Current state of CP and proposed behaviour in the new sleep mode (for all ports that currently implement the
alarm
module):HAL_PWR_EnterSTANDYMode()
HAL_PWR_EnterSTOPMode()
PM_SLEEPCFG_SLEEPMODE_BACKUP
PM_SLEEPCFG_SLEEPMODE_STANDBY
esp_deep_sleep_start()
esp_light_sleep_start()
orNotImplementedError
If there is interest in such a feature, I would be willling to implement it (at least for nordic, raspi and esp, as those are the ones I'm personally interested in).
*Note: I think the new RP2350 series also has low power ram retaining sleep, and could therefore also benefit from this feature.
Similar Issue: #8771
The text was updated successfully, but these errors were encountered: