microbit-foundation / micropython-microbit-v2

Temporary home for MicroPython for micro:bit v2 as we stablise it before pushing upstream
MIT License
41 stars 22 forks source link

Wake up from `power.deep_sleep()` via UART incoming data? #127

Closed microbit-carlos closed 1 year ago

microbit-carlos commented 1 year ago

The main way for CLI/Desktop tools/editors to interact with MicroPython is via serial REPL. When the board is asleep, it will stop responding to serial, so with a programme like this one, the only option is to reflash the micro:bit with MicroPython, as it won't respond to most tools or desktop editors from serial anymore:

import power
power.deep_sleep()

At the time of writing, due to issue #126, the programme above won't go to sleep, but to replicate we can simply add Button A as the only wake up source:

from microbit import *
import power

while True:
    power.deep_sleep(wake_on=button_a)
    display.show(Image.SURPRISED)
    sleep(500)

While this could be obvious for a small programme that basically sleeps, the same can be trigger with other "normal" programmes that might go to sleep for any amount of time, like with data logging.

Should the board wake up via serial?

If the answer is "yes", it could be: 1) implicitly configured and unchangeable 1) a new parameter with a default value, e.g. power.deep_sleep(serial_wake=True) 1) another argument option for the wake_on parameter, i.e. power.deep_sleep(wake_on=(pin1, serial))

@dpgeorge

microbit-carlos commented 1 year ago

@JohnVidler does CODAL support waking up from UART activity without losing any data?

JohnVidler commented 1 year ago

CODAL currently does not wake from UART events, but we should be able to work that in.

I'm struggling to imagine a situation where this wouldn't be desirable too, certainly for the USB/UART, and maybe for the edge connector as a toggleable option, so having this be enabled for the USB/UART by default would seem to be the correct course.

Comments maybe @finneyj ?

JohnVidler commented 1 year ago

Aaand now it does support it :) Pending the PR above merging into master.

dpgeorge commented 1 year ago

I would suggest that the default behaviour for deep_sleep() is that UART activity will wake it up, otherwise, as pointed out above, users can get the micro:bit into a state that's difficult to get out of.

another argument option for the wake_on parameter, i.e. power.deep_sleep(wake_on=(pin1, serial))

For consistency I think this is the right approach. But probably use uart instead of serial (because microbit.uart is already an object). The only thing is, it requires users to understand that UART==REPL (in most cases) and that they should usually always pass uart to the wake_on parameter. It makes the examples a bit more complicated though...

JohnVidler commented 1 year ago

While there some debate around what the default behaviour should be, as of the merged PR above, you can now configure this in codal.json via the MICROBIT_USB_SERIAL_WAKE parameter.

If set (to 1) USB serial events will wake the board from deep sleep.

JohnVidler commented 1 year ago

Released a new CODAL tag v0.2.43 which adds this support: https://github.com/lancaster-university/codal-microbit-v2/releases/tag/v0.2.43

microbit-carlos commented 1 year ago

But probably use uart instead of serial (because microbit.uart is already an object).

Yes, sorry, I'm meant to use the existing uart from microbit.uart here.

The only thing is, it requires users to understand that UART==REPL (in most cases) and that they should usually always pass uart to the wake_on parameter. It makes the examples a bit more complicated though...

Yeah, I think this is a very important point. It's probably not very clear to users why they might need to have to include uart in the wake_on arguments. Because of that I'm inclined to think it might be better as an additional parameter that can be changed if needed and ignored completely if not.

However, with the latest CODAL tag we could simply set the MICROBIT_USB_SERIAL_WAKE built time config, where it always wakes up via serial, and leave it as it is. We can always add an additional parameter in the future if needed?

microbit-carlos commented 1 year ago

As a side note, with the current 0.2.43 CODAL tag there are no getter/setter for enabling disabling wake up via serial, but the status flag can be modified directly: uBit.serial.status |= CODAL_SERIAL_STATUS_DEEPSLEEP;

JohnVidler commented 1 year ago

I'll roll a proper set call into the next release, but held off for *43 as we're reworking some of the IO interfaces and it'll all be in with that lot.

microbit-carlos commented 1 year ago

Okay, I think the best thing we can do for the v2.1.0 release is to have the "wake on serial" enabled by default, and if we need to, we can add a way to disable it in future releases.

dpgeorge commented 1 year ago

Okay, I think the best thing we can do for the v2.1.0 release is to have the "wake on serial" enabled by default, and if we need to, we can add a way to disable it in future releases

Yes I think that's a good idea. With CODAL v0.2.43 now used by MicroPython-on-micro:bit v2, this is now the behaviour.

microbit-carlos commented 1 year ago

Great, we can close this as implemented then, thanks everyone! 🎉