diff --git a/docs/index.rst b/docs/index.rst index 68e778c25..eec1dcd3e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -90,6 +90,7 @@ Projects related to MicroPython on the BBC micro:bit include: neopixel.rst os.rst pin.rst + power.rst radio.rst random.rst speaker.rst diff --git a/docs/power-mcus.png b/docs/power-mcus.png new file mode 100644 index 000000000..ca28fada5 Binary files /dev/null and b/docs/power-mcus.png differ diff --git a/docs/power.rst b/docs/power.rst new file mode 100644 index 000000000..cef13ac44 --- /dev/null +++ b/docs/power.rst @@ -0,0 +1,162 @@ +Power Management **V2** +*********************** + +.. py:module:: power + +This module lets you manage the power modes of the micro:bit V2. + +There are two low power modes that can be requested from MicroPython: + +- **Deep Sleep**: Low power mode where the board can be woken up via + multiple sources (pins, button presses, or a timer) and resume + operation. +- **Off**: The power mode with the lowest power consumption, the only way to + wake up the board is via the reset button, or by plugging the USB cable while + on battery power. + When the board wakes up it will restart and execute your programme from the + beginning. + +The micro:bit board contains two microcontrollers (MCUs), which can be +independently awake or asleep: + +- **Target MCU** - Where MicroPython and your code run +- **Interface MCU** - A secondary microcontroller that provides the USB + functionality, like the ``MICROBIT`` USB drive, and the USB serial interface + +.. image:: power-mcus.png + +As the each microcontrollers can go into a low power mode independently, +the Python code can request a "board power mode", which will set the Target +MCU into the desired state, but the Interface MCU state will depend on the +micro:bit power source, i.e. if it's powered via USB or battery. + ++------------------+---------------+--------------------+ +| .. centered:: USB Powered (Interface always awake) | ++------------------+---------------+--------------------+ +| Board Power mode | Target state | Interface state | ++==================+===============+====================+ +| **Deep Sleep** | 💤 Sleep | ⏰ Awake | ++------------------+---------------+--------------------+ +| **Off** | 📴 Power Down | ⏰ Awake | +| | | (red LED blinking) | ++------------------+---------------+--------------------+ + ++------------------+---------------+------------------+ +| .. centered:: Battery Powered | ++------------------+---------------+------------------+ +| Board Power mode | Target state | Interface state | ++==================+===============+==================+ +| **Deep Sleep** | 💤 Sleep | 💤 Sleep | ++------------------+---------------+------------------+ +| **Off** | 📴 Power Down | 📴 Power Down | ++------------------+---------------+------------------+ + +Functions +========= + +.. py:function:: off() + + Power down the board to the lowest possible power mode. + + The Target MCU will go into sleep mode. + + This is the equivalent to press the reset button for a few second, to set + the board in "off mode". + + The state of the Interface MCU will depend on the power source. + If it is connected to a PC via USB it will stay awake to maintain the USB + connection, if powered via battery it will go to sleep as well. + + The micro:bit will only wake if the reset button is pressed, or if on + battery power, when a USB cable is connected. + + The the board wakes up it will start for a reset state, so your programme + will start running from the beginning. + + +.. py:function:: deep_sleep() + + Set the micro:bit into the Deep Sleep mode. + + The programme state is preserved and on wake it will resume operation + where it left off. + + The wake up sources are configured with the ``wake_source()`` function. + If no wake up sources have been configured it will sleep indefinitely. + +.. py:function:: wake_source(pins=None, buttons=None, ms=None, run_every=False) + + Configure the "deep sleep" wake-up sources. + + These wake-up source will not work for the ``off`` mode. + + :param pins: A single instance or a tuple of pins, e.g. + ``wake_source(pins=(pin0, pin2))``. + :param buttons: A single instance or a tuple of buttons, e.g. + ``wake_source(buttons=button_a)``. + :param ms: A time in milliseconds to wait before it wakes up. + :param run_every: Set to ``True`` to wake up with each + ``microbit.run_every`` scheduled run. + + +Examples +======== + +Example programme showing the power management API:: + + """ + Shows a silly face on the display every 20 seconds. + When button B is pressed it goes into Deep Sleep mode, and wakes 5 minutes later. + When button A is pressed it goes into to Off mode. + """ + from microbit import * + + @run_every(s=20) + def silly_face(): + display.show(Image.SILLY) + sleep(500) + + while True: + if button_a.is_pressed(): + display.scroll("Off") + # In this mode the micro:bit can only wake up via the reset button + power.off() + # This line of code will never be executed, as waking up from this + # mode starts the programme from the beginning + display.show(Image.SURPRISED) + elif button_b.is_pressed(): + display.scroll("Sleep") + # First let's configure the wake up sources for deep sleep + power.wake_source( + pins=(pin0, pin1), + buttons=button_a + ms=5*60*1000 # In 5 minutes it wakes up anyway + run_every=False # Blocks run_every from waking up the board + ) + # Now let's go to sleep + power.deep_sleep() + # When the micro:bit wakes up will it continue running from here + display.show(Image.ASLEEP) + sleep(1000) + display.show(Image.HAPPY) + sleep(200) + + +Example using data logging:: + + from microbit import * + import log + + # Log the temperature every 5 minutes + @run_every(min=5) + def log_temperature(): + log.add(temp=temperature()) + + # Configure the wake up sources to wake up with run_every & button A + power.wake_source(buttons=button_a, run_every=True) + + while True: + if button_a.is_pressed(): + # Display the temperature when button A is pressed + display.scroll(temperature()) + power.deep_sleep()