diff --git a/docs/index.rst b/docs/index.rst index 1d8a85153..687ac4c1c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -91,6 +91,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..ea64e54d3 --- /dev/null +++ b/docs/power.rst @@ -0,0 +1,126 @@ +Power Management **V2** +*********************** + +.. py:module:: power + +This module lets you manage the power modes of the micro:bit V2. + +There are two micro:bit board 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. + +More information on how these low power modes work can be found in the +`Detailed Information section <#detailed-information>`_. + +Functions +========= + +.. py:function:: off() + + Power down the board to the lowest possible power mode. + + This is the equivalent to pressing the reset button for a few second, + to set the board in "Off mode". + + The micro:bit will only wake up if the reset button is pressed or, + if on battery power, when a USB cable is connected. + + When the board wakes up it will start for a reset state, so your programme + will start running from the beginning. + + +.. py:function:: deep_sleep(ms=None, wake_on=None, run_every=False) + + Set the micro:bit into a low power mode where it can wake up and continue + operation. + + The programme state is preserved and when it wakes up it will resume + operation where it left off. + + Deep Sleep mode will consume more battery power than Off mode. + + The wake up sources are configured via arguments. + + If no wake up sources have been configured it will sleep until the reset + button is pressed (which resets the board) or, in battery power, + when the USB cable is inserted. + + :param ms: A time in milliseconds to wait before it wakes up. + :param wake_on: A single instance or a tuple of pins and/or buttons to + wake up the board, e.g. ``deep_sleep(wake_on=button_a)`` or + ``deep_sleep(wake_on=(pin0, pin2, button_b))``. + :param run_every: Set to ``True`` to wake up with each + ``microbit.run_every`` scheduled run. + +Examples +======== + +Example programme showing the power management API: + +.. include:: ../examples/low-power.py + :code: python + + +Example using data logging: + +.. include:: ../examples/datalog-sleep.py + :code: python + + +Detailed Information +==================== + +The micro:bit board has two microcontrollers (MCUs), which can be +independently asleep or awake: + +- **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 + +Each MCU can be in one of these "MCU power modes": + +- **Awake**: Running normally. +- **Sleep**: A low power mode where the MCU can be woken up from different + sources and continue operation. +- **Power Down**: The lowest power mode for an individual MCU, when it wakes up + it will start from reset. + +The Python code can request a "board power mode", in this case **Deep Sleep** +or **Off**, which will set the Target into a specific "MCU power mode", +but the Interface MCU mode will depend on the micro:bit power source, +i.e. if it's powered via USB (connector to a computer) or battery. + +In essence, on battery power the Interface MCU can go into a low power mode, +but when it is connected to a computer via USB, it will stay awake to maintain +the USB connection. + ++------------------+-----------------+--------------------+ +| .. centered:: USB Powered (Interface always awake) | ++------------------+-----------------+--------------------+ +| Board Power Mode | Target MCU Mode | Interface MCU mode | ++==================+=================+====================+ +| **Deep Sleep** | 💤 Sleep | ⏰ Awake | ++------------------+-----------------+--------------------+ +| **Off** | 📴 Power Down | ⏰ Awake | +| | | (red LED blinking) | ++------------------+-----------------+--------------------+ + ++------------------+-----------------+--------------------+ +| .. centered:: Battery Powered | ++------------------+-----------------+--------------------+ +| Board Power Mode | Target MCU Mode | Interface MCU mode | ++==================+=================+====================+ +| **Deep Sleep** | 💤 Sleep | 💤 Sleep | ++------------------+-----------------+--------------------+ +| **Off** | 📴 Power Down | 📴 Power Down | ++------------------+-----------------+--------------------+ diff --git a/examples/datalog-sleep.py b/examples/datalog-sleep.py new file mode 100644 index 000000000..c0f3ac3d3 --- /dev/null +++ b/examples/datalog-sleep.py @@ -0,0 +1,15 @@ +from microbit import * +import power +import log + +# Log the temperature every 5 minutes +@run_every(s=5) +def log_temperature(): + log.add(temp=temperature()) + +while True: + if button_a.is_pressed(): + # Display the temperature when button A is pressed + display.scroll(temperature()) + # To go sleep and wake up with run_every or button A + power.deep_sleep(wake_on=button_a, run_every=True) diff --git a/examples/low-power.py b/examples/low-power.py new file mode 100644 index 000000000..1f6f710c6 --- /dev/null +++ b/examples/low-power.py @@ -0,0 +1,36 @@ +""" +Shows a silly face on the display every 10 seconds. +When button A is pressed it goes into Deep Sleep mode, and wakes 30 minutes later, +or by pressing button A again. +When button B is pressed it goes into to Off mode. +""" +from microbit import * +import power + +@run_every(s=10) +def silly_face(): + display.show(Image.SILLY) + sleep(400) + +while True: + if button_b.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_a.is_pressed(): + display.show(Image.ASLEEP) + sleep(300) + # Go into Deep Sleep with multiple wake up sources + power.deep_sleep( + wake_on=(pin0, pin1, button_a), + ms=30*1000, # In 30 seconds it wakes up anyway + run_every=False, # Stops run_every from waking up the board + ) + # When the micro:bit wakes up will it continue running from here + # Blink a few times to show you are waking up + display.show([Image("99099:09090:99099:09990"), Image.ASLEEP] * 3, 250) + display.show(Image.HAPPY) + sleep(200)