Skip to content

Commit

Permalink
Merge pull request #6 from martinwork/low-full
Browse files Browse the repository at this point in the history
Change terminology: deep sleep, power down and wake to low/full power
  • Loading branch information
martinwork authored Sep 6, 2021
2 parents f5c6adc + 531ab1c commit 43447bb
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 216 deletions.
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,62 @@
# Makecode Extension to enable power management on micro:bit (V2)

Use this extension to add all the blocks you will need to power the micro:bit on and off in your program when you are using the [latest micro:bit](https://microbit.org/new-microbit/).
Use this extension to add all the blocks you will need to use less power in your program when you are using the [latest micro:bit](https://microbit.org/new-microbit/).

This extension might be useful when you want to conserve battery power, such as during a data logging activity.


## Usage

### Put the micro:bit to sleep 💤
### Put the micro:bit to sleep in a low power mode 💤

To make the micro:bit sleep, you need to send a request to power it down. The ``||power.powerDownRequest||`` block will ask the micro:bit to power down at the next opportunity, such as when the current code operation has been allowed to complete.
The ``||power.lowPowerRequest||`` block will ask the micro:bit to switch to low power mode at the next opportunity, such as when the current code operation has been allowed to complete, or inside ``||basic.pause(ms)||``.

```blocks
input.onButtonPressed(Button.B, function () {
power.powerDownRequest()
power.lowPowerRequest()
})
```

You can also ask the micro:bit to enter a ``||power.deepSleep||`` where it will pause until a wake up event occurs and power down at the next opportunity.
You can send ``||power.lowPowerRequest(LowPowerMode.Wait)||``. Then micro:bit will also pause until a full power event occurs.

The ``||power.lowPowerPause(ms)||`` block will ask the micro:bit to sleep for a set interval in milliseconds.

The ``||power.deepSleepPause(ms)||`` block will also ask the micro:bit to sleep for a set interval in milliseconds.
In low power mode, the micro:bit is asleep, and your program is paused. When the micro:bit wakes up to full power mode, your program continues from the point it stopped.

You can also use the ``||PowerDown.prevent||`` and ``||PowerDown.allow||`` blocks to block a power down request until the code inside the two blocks has finished running. It is expected that you would use these blocks in pairs.
You can use the ``||power.lowPowerEnable(PowerDown.prevent)||`` and ``||power.lowPowerEnable(PowerDown.allow)||`` blocks to block low power requests until the code between the two blocks has finished running. It is expected that you would use these blocks in pairs.

```blocks
basic.forever(function () {
power.powerDownEnable(PowerDown.prevent)
power.lowPowerEnable(PowerDown.prevent)
led.plot(2, 2)
basic.pause(1000)
led.unplot(2, 2)
led.plot(2, 1)
basic.pause(1000)
led.unplot(2, 1)
power.powerDownEnable(PowerDown.allow)
power.powerDownRequest()
power.lowPowerEnable(PowerDown.allow)
power.lowPowerRequest()
})
```

### Wake the micro:bit from sleep
### Wake up the micro:bit to full power mode

In order to wake the micro:bit, you need to define an event to trigger the wake up call.
In order to wake up the micro:bit to full power mode, you need to define an event to trigger the wake up call.

You can wake the micro:bit when a button or pin is pressed. In this example, the micro:bit will wake up when Button A or Pin 0 has been pressed.

```blocks
power.wakeOnEnable(PowerWakeup.A)
power.wakeOnEnable(PowerWakeup.P0)
power.fullPowerOn(FullPowerSource.A)
power.fullPowerOn(FullPowerSource.P0)
```

You can also wake the micro:bit at a set time interval in milliseconds. In this example, the micro:bit will wake up every minute and show a smiley face on the screen

```blocks
power.wakeEvery(60000, function () {
power.fullPowerEvery(60000, function () {
basic.showIcon(IconNames.Happy)
basic.clearScreen()
power.lowPowerRequest()
})
```

Expand Down
189 changes: 113 additions & 76 deletions power.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,77 @@
#endif // MICROBIT_CODAL


enum class PowerWakeup {
enum class FullPowerSource {
//% block="button A"
A = MICROBIT_ID_BUTTON_A,
//% block="button B"
B = MICROBIT_ID_BUTTON_B,
//% block="pin P0"
P0 = MICROBIT_ID_IO_P0,
//% block="pin P1"
P1 = MICROBIT_ID_IO_P1,
//% block="pin P2"
P2 = MICROBIT_ID_IO_P2
};

enum class PowerDown {
prevent,
allow
enum class LowPowerMode {
//% block="continue"
Continue = 0,
//% block="wait"
Wait = 1
};

enum class LowPowerEnable {
//% block="prevent"
Prevent,
//% block="allow"
Allow
};


//% block="Power"
//% icon="\uf011"
//% color=#AA278D
namespace power {

#if MICROBIT_CODAL
int timerEventValue = 1;
#endif // MICROBIT_CODAL

/**
* Pause until a wake up event occurs, and request power down when idle.
*/
//%
void deepSleep() {
#if MICROBIT_CODAL
uBit.power.deepSleep();
#else
uBit.sleep(0);
#endif
}

void lowPowerRequest(LowPowerMode mode = LowPowerMode::Continue);

/**
* Request power down when idle, and return immediately.
* Request low power when the next idle
* @param mode If Continue, then return immediately; if Wait, then pause until a power-up event occurs
*/
//% help=power/low-power-request
//% group="micro:bit (V2)"
//% weight=700
//% block="request low power||and $mode"
//%
void powerDownRequest() {
void lowPowerRequest(LowPowerMode mode) {
#if MICROBIT_CODAL
uBit.power.deepSleepAsync();
if ( mode == LowPowerMode::Wait)
uBit.power.deepSleep();
else
uBit.power.deepSleepAsync();
#else
uBit.sleep(0);
#endif
}
}


/**
* Pause for a fixed interval, and request power down when idle.
* Pause for a fixed interval, and request low power when idle.
* @param interval The period of time to pause, in milliseconds.
*/
//% help=power/low-power-for
//% group="micro:bit (V2)"
//% weight=600
//% interval.shadow=longTimePicker
//% block="request low power for $interval ms"
//%
void deepSleepPause(unsigned interval) {
void lowPowerPause(int interval) {
#if MICROBIT_CODAL
uBit.power.deepSleep(interval);
#else
Expand All @@ -79,38 +98,23 @@ void deepSleepPause(unsigned interval) {


/**
* Do something repeatedy using a wake-up timer.
* @param interval time (in ms) for the timer.
* @param body code to execute
*/
//%
void wakeEvery(unsigned interval, Action body) {
#if MICROBIT_CODAL
registerWithDal( MICROBIT_ID_MAKECODE_POWER, timerEventValue, body);
// CODAL_TIMER_EVENT_FLAGS_WAKEUP makes the timer event trigger power up
system_timer_event_after( 0, MICROBIT_ID_MAKECODE_POWER, timerEventValue, CODAL_TIMER_EVENT_FLAGS_WAKEUP);
system_timer_event_every( interval, MICROBIT_ID_MAKECODE_POWER, timerEventValue++, CODAL_TIMER_EVENT_FLAGS_WAKEUP);
#else
target_panic(PANIC_VARIANT_NOT_SUPPORTED);
#endif
}


/**
* Prevent or allow power down during deepSleep.
* Prevent or allow low power.
* Prevent and allow requests should occur in pairs.
* The default is to allow.
*/
//% help=power/low-power-enable
//% weight=500
//% block="low power %enable"
//%
void powerDownEnable(PowerDown choice) {
void lowPowerEnable(LowPowerEnable enable) {
#if MICROBIT_CODAL
switch ( choice)
switch ( enable)
{
case PowerDown::prevent:
case LowPowerEnable::Prevent:
uBit.power.powerDownDisable();
break;

case PowerDown::allow:
case LowPowerEnable::Allow:
uBit.power.powerDownEnable();
break;

Expand All @@ -122,10 +126,11 @@ void powerDownEnable(PowerDown choice) {


/**
* Determine if power down during deepSleep is enabled
* Determine if low power is enabled
*/
//% help=power/low-power-is-enabled
//%
bool powerDownIsEnabled() {
bool lowPowerIsEnabled() {
#if MICROBIT_CODAL
return uBit.power.powerDownIsEnabled();
#else
Expand All @@ -135,29 +140,55 @@ bool powerDownIsEnabled() {


/**
* Set whether the source should trigger power save wake-up.
* Do something repeatedy with full power using a timer.
* @param interval the time (in ms) for the timer.
* @param code the code to execute
*/
//% help=power/full-power-every
//% group="micro:bit (V2)"
//% weight=800
//% blockAllowMultiple=1
//% interval.shadow=longTimePicker
//% afterOnStart=true
//% block="full power every $interval ms"
//%
void fullPowerEvery(int interval, Action code) {
#if MICROBIT_CODAL
registerWithDal( MICROBIT_ID_MAKECODE_POWER, timerEventValue, code);
// CODAL_TIMER_EVENT_FLAGS_WAKEUP makes the timer event trigger power up
system_timer_event_after( 0, MICROBIT_ID_MAKECODE_POWER, timerEventValue, CODAL_TIMER_EVENT_FLAGS_WAKEUP);
system_timer_event_every( interval, MICROBIT_ID_MAKECODE_POWER, timerEventValue++, CODAL_TIMER_EVENT_FLAGS_WAKEUP);
#else
target_panic(PANIC_VARIANT_NOT_SUPPORTED);
#endif
}


/**
* Set whether the source should trigger full power.
* @param source the source to set
* @param wake true to trigger wake-up or false for no wake-up
* @param enable true to trigger full power
*/
//% help=power/full-power-source-enable
//%
void wakeOn(PowerWakeup source, bool wake) {
void fullPowerSourceEnable(FullPowerSource source, bool enable) {
#if MICROBIT_CODAL
switch ( source)
{
case PowerWakeup::A:
uBit.buttonA.wakeOnActive(wake ? 1 : 0);
case FullPowerSource::A:
uBit.buttonA.wakeOnActive(enable ? 1 : 0);
break;

case PowerWakeup::B:
uBit.buttonB.wakeOnActive(wake ? 1 : 0);
case FullPowerSource::B:
uBit.buttonB.wakeOnActive(enable ? 1 : 0);
break;

case PowerWakeup::P0:
case PowerWakeup::P1:
case PowerWakeup::P2:
case FullPowerSource::P0:
case FullPowerSource::P1:
case FullPowerSource::P2:
{
MicroBitPin *pin = getPin((int)source);
pin->wakeOnActive(wake ? 1 : 0);
pin->wakeOnActive(enable ? 1 : 0);
break;
}
default:
Expand All @@ -168,35 +199,27 @@ void wakeOn(PowerWakeup source, bool wake) {


/**
* Set the source to trigger power save wake-up.
* @param source the source to set
*/
//%
void wakeOnEnable(PowerWakeup source) {
wakeOn(source, true);
}

/**
* Determine if the source will trigger power save wake-up.
* @param source the source to set
* @return true is wake-up is enabled
* Determine if the source will trigger full power.
* @param source the source to check
* @return true if the source will trigger full power
*/
//% help=power/full-power-source-is-enabled
//%
bool wakeOnIsEnabled(PowerWakeup source) {
bool fullPowerSourceIsEnabled(FullPowerSource source) {
#if MICROBIT_CODAL
switch ( source)
{
case PowerWakeup::A:
case FullPowerSource::A:
return uBit.buttonA.isWakeOnActive() ? true : false;
break;

case PowerWakeup::B:
case FullPowerSource::B:
return uBit.buttonB.isWakeOnActive() ? true : false;
break;

case PowerWakeup::P0:
case PowerWakeup::P1:
case PowerWakeup::P2:
case FullPowerSource::P0:
case FullPowerSource::P1:
case FullPowerSource::P2:
{
MicroBitPin *pin = getPin((int)source);
return pin->isWakeOnActive() ? true : false;
Expand All @@ -210,4 +233,18 @@ bool wakeOnIsEnabled(PowerWakeup source) {
}


/**
* Set the source to trigger full power.
* @param source the source to set
*/
//% help=power/full-power-on
//% group="micro:bit (V2)"
//% weight=900
//% block="full power on %source"
//%
void fullPowerOn(FullPowerSource source) {
fullPowerSourceEnable(source, true);
}


} // namespace power
Loading

0 comments on commit 43447bb

Please sign in to comment.