Skip to main content

Low Power

note

For an API reference, see API Reference/Low Power

The library also supports low power functionality. There are two modes in the low power module: power down and power save. In low power, any interrupt on the exposed GPIO Featherwing pins (most of the pins around the board) will wake up the device, as well as any interrupt on the buttons. These pins can be used as external wake-up sources.

caution

The low power module does not turn off the onboard temperature and light sensors. These have to be actively turned off before powering down.

Power Down Mode

The power down mode will power down the modem and the AVR CPU. This will thus disconnect the modem from the network and terminate all active connections. Since it powers down the modem and terminates all active connections (such as MQTT), there is a penalty with this mode in comparison with the power save mode that there will be increased network data usage as one has to reestablish for example the connection to an MQTT broker. If power save mode is available for your region and operator, consider using it if network data usage is of concern.

Configuration

The power down mode is configured by calling LowPower.configurePowerDown().

Use

The power down mode simply needs to be called with how long the modem and the AVR CPU should remain powered down. Note that the amount of time is specified in seconds. The modem will automatically be powered on and start connecting to the network after the power down, so there is no need to call Lte.begin() again.

Issuing the power down is done by calling LowPower.powerDown(<amount of seconds to power down>)

caution

If you have an active MQTT(S) or HTTP(S) connection, this will be terminated when LowPower.powerDown() is called.

Full example

In this example, we power down for 60 seconds and simulate doing work for 10 seconds. The light sensor and the temperature sensor are also turned off. The driver for the VEML3328 (light sensor) can be found here, whilst the driver for the MCP9808 (temperature sensor) can be found here.

#include <Arduino.h>
#include <led_ctrl.h>
#include <log.h>
#include <low_power.h>
#include <lte.h>
#include <mcp9808.h>
#include <veml3328.h>

#define SW0 PIN_PD2

static volatile bool woke_up_from_button = false;

void button_pressed_callback(void) {
if (PORTD.INTFLAGS & PIN2_bm) {
// Reset the interrupt flag so that we can process the next incoming
// interrupt
PORTD.INTFLAGS = PIN2_bm;

woke_up_from_button = true;
}
}

void setup() {
Log.begin(115200);

// Set up LED ctrl so that we can see on the blue LED when the device is connected to the network
LedCtrl.begin();
LedCtrl.startupCycle();

// Attach interrupt callback to detect if SW0 was pressed during sleep
pinConfigure(SW0, PIN_DIR_INPUT);
attachInterrupt(SW0, button_pressed_callback, FALLING);

// Now we configure the low power module for power down configuration, where
// the modem and the CPU will be powered down
LowPower.configurePowerDown();

// Make sure sensors are turned off
Veml3328.begin();
Mcp9808.begin();
Veml3328.shutdown();
Mcp9808.shutdown();

Lte.begin();
Log.infof("Connected to operator: %s\r\n", Lte.getOperator().c_str());
}

void loop() {

Log.info("Powering down...");

// Allow some time for the log message to be transmitted before we power
// down
delay(100);

// Power down for 60 seconds
LowPower.powerDown(60);

if (woke_up_from_button) {
Log.info("SW0 was pressed");
woke_up_from_button = false;
}

Log.info("Woke up!");

// Do work ...
Log.info("Doing work...");
delay(10000);
}

Expected results

You should see a similar current graph for the power down example:

With powering the sensors down, you should see a current consumption of around 70 µA whilst power saving (measured at the VMUX jumper).

Example of long-term results

The following graph shows the AVR-IoT Cellular Mini powered by an 860 mAh battery and operating on it for 58 days (yielding an average consumption of ~0.61 mA). In this test, the board woke up, gathered sensor data, and published an MQTT message every 30 minutes. In a typical setting where the board wakes up just a few times a day, a far longer timeframe is expected.

Power Save Mode

Power save mode is different from power down mode in the way that it will keep the modem actively connected to the network, but in a deep sleep state. This is convenient if one wants to keep connections active, such as for example to a MQTT broker. This mode has to be coordinated with the network operator, since the modem will be power saving periodically, and the network operator has to know about this.

caution

If MQTT is used with power save mode, the keep alive argument for the MQTT connection should be longer than the sleeping period (if possible). If this is not the case, the MQTT connection will cause the device to wake up prematurely.

Availability

Power save mode is not available for every operator. Check the table below to see if your operator is supported. Note that the operator the board is using can be queryed using Lte.getOperator() after connecting to the network.

Availability for different operators
CountryOperatorPSM available
ArgentinaTelefonica
ArgentinaPersonal
ArgentinaClaro✔️
AustraliaTelstra✔️
AustriaT-Mobile✔️
BelgiumOrange
BrazilClaro
CanadaBell✔️
CanadaRogers❌️
CanadaTelus
ChileClaro️❌
DenmarkTelia️❌
DenmarkTDC️✔️️
FinlandTelia️❌
FinlandElisa️✔️️
FranceOrange✔️️
FranceBouygues️❌
GermanyDeutsche Telekom✔️️
GermanyTelefonica️❌
GermanyVodafone DE✔️️️
HungaryT-Mobile️️❌ ️
IsraelPelephone✔️️️
IcelandSiminn✔️️️
JapanKDDI Corporation✔️️️
JapanNTT Docomo✔️️️
JapanSoftbank✔️️️
LatviaLv Lmt✔️️️
LiechtensteinSunrise❌ ️
LuxemburgPost✔️️️
MexicoAT&T️️❌ ️
MexicoPegaso (Moviestar)️️❌ ️
MexicoTelcel✔️️️
New ZealandSpark️️❌ ️
New ZealandVodafone️️❌ ️
NorwayTelenor✔️️️
NorwayTelia️️❌ ️
PhilippinesGlobe️️❌ ️
PolandOrange️️❌ ️
Puerto RicoAT&T✔️️
Puerto RicoClaro️️❌ ️
RomaniaOrange✔️️
SingaporeSingTel✔️️
South KoreaSK Telecom️️ ❌ ️
South KoreaKT Corporation✔️️
SpainOrange✔️️
SpainMoviestar✔️️
SwedenTelia❌ ️
SwitzerlandSwisscom✔️️
SwitzerlandSunrise️❌ ️
The NetherlandsKPN️❌ ️
The NetherlandsVodafone✔️️
Taiwan P.o.C.Chunghwa Telecom✔️️
TurkeyTurkcell✔️️
United KingdomTelefonica (O2)❌ ️
United StatesAT&T✔️️
United StatesT-Mobile❌ ️
United StatesVerizon❌ ️
UruguayAntel✔️️

How it works

We first tell the operator that we want to have a power save period of for example 60 seconds. This means that the modem will be active and talking to the operator for a period of these 60 seconds and sleeping for the remaining time. This loop of syncing up with the operator and sleeping for the remaining time of the period goes on as long as we tell it is okay for it to power save. Note that the modem is the one responsible for knowing where we are in this period. Thus, if we issue a power save in the middle of the period, it will only sleep for half the time before being woken up again. This is fine, and can for example happen if we do some operations on the CPU which takes a lot of time.

There are some rules from the operator we are connecting to regarding how long the period of the power save can be. They are defined in a way where you have a multiplier and a value (the maximum value is 31). For example if we have a multiplier of one hour and a value of 3, the power save period will be 3 hours in total.

Multipliers available

  • Two seconds
  • Thirty seconds
  • One minute
  • Ten minutes
  • One hour
  • Ten hours
info

Following this, the maximum amount the modem can be asleep in power save mode is ten hours multiplied with 31, which results in almost 13 days.

Configuration

For configuration we have to call LowPower.configurePowerSave(<multipier>, <value>)

Use

For power save mode we only have to call: LowPower.powerSave().

Example

#include <Arduino.h>
#include <led_ctrl.h>
#include <log.h>
#include <low_power.h>
#include <lte.h>
#include <mcp9808.h>
#include <veml3328.h>

#define SW0 PIN_PD2

static volatile bool woke_up_from_button = false;

void button_pressed_callback(void) {
if (PORTD.INTFLAGS & PIN2_bm) {
// Reset the interrupt flag so that we can process the next incoming
// interrupt
PORTD.INTFLAGS = PIN2_bm;

woke_up_from_button = true;
}
}

void setup() {
Log.begin(115200);

// Set up LED ctrl so that we can see on the blue LED when the device is connected to the network
LedCtrl.begin();
LedCtrl.startupCycle();

// Attach interrupt callback to detect if SW0 was pressed during sleep
pinConfigure(SW0, PIN_DIR_INPUT);
attachInterrupt(SW0, button_pressed_callback, FALLING);

// Here we say that we want to have a power save period of 30 seconds * 2 =
// 60 seconds.
LowPower.configurePeriodicPowerSave(
PowerSaveModePeriodMultiplier::THIRTY_SECONDS, 2);

// Make sure sensors are turned off
Veml3328.begin();
Mcp9808.begin();
Veml3328.shutdown();
Mcp9808.shutdown();

Lte.begin();
Log.infof("Connected to operator: %s\r\n", Lte.getOperator().c_str());
}

void loop() {
Log.raw("\r\n");
Log.info("Power saving...");
// Delay some to allow the log message to be transmitted before the device is going into power save mode
delay(100);

LowPower.powerSave();

if (woke_up_from_button) {
Log.info("SW0 was pressed");
woke_up_from_button = false;
}

Log.info("Woke up!");

// Do work ...
Log.info("Doing work...");
delay(10000);
}

Expected result

You should see a similar current consumption graph for the power save mode. Note that the whole period between the modem waking up here is 60 seconds, where it will not sleep for this whole period due to having to sync up with the operator.

Retrieving the current supply voltage

The LowPower module exposes a function for retrieving the supply voltage of the board: LowPower.getSupplyVoltage(). This is the supply voltage for the whole board, not just the microcontroller. When the board is plugged in, you should expect ~4.7V (this is due to a voltage drop across a diode, see the schematics for more information). When the board is powered by a battery, the function will retrieve the current voltage of the battery.

Example

#include <log.h>
#include <low_power.h>

void setup() {
Log.begin(115200);
}

void loop() {

float voltage = LowPower.getSupplyVoltage();

// Note that in order to print floats, you have to set printf support to
// full in the Arduino IDE. Go to Tools -> printf() -> Full
Log.infof("The voltage supplied is: %f\r\n", voltage);

delay(1000);
}

Live Editor (Power Down example)

Live Editor
#include <Arduino.h>
#include <led_ctrl.h>
#include <log.h>
#include <low_power.h>
#include <lte.h>
#include <mcp9808.h>
#include <veml3328.h>
#define SW0 PIN_PD2
static volatile bool woke_up_from_button = false;
void button_pressed_callback(void) {
if (PORTD.INTFLAGS & PIN2_bm) {
// Reset the interrupt flag so that we can process the next incoming
// interrupt
PORTD.INTFLAGS = PIN2_bm;
woke_up_from_button = true;
}
}
void setup() {
Log.begin(115200);
// Set up LED ctrl so that we can see on the blue LED when the device is connected to the network
LedCtrl.begin();
LedCtrl.startupCycle();
// Attach interrupt callback to detect if SW0 was pressed during sleep
pinConfigure(SW0, PIN_DIR_INPUT);
attachInterrupt(SW0, button_pressed_callback, FALLING);
// Now we configure the low power module for power down configuration, where
// the modem and the CPU will be powered down
LowPower.configurePowerDown();
// Make sure sensors are turned off
Veml3328.begin();
Mcp9808.begin();
Veml3328.shutdown();
Mcp9808.shutdown();
Lte.begin();
Log.infof("Connected to operator: %s\r\n", Lte.getOperator().c_str());
}
void loop() {
Log.info("Powering down...");
// Allow some time for the log message to be transmitted before we power
// down
delay(100);
// Power down for 60 seconds
LowPower.powerDown(60);
if (woke_up_from_button) {
Log.info("SW0 was pressed");
woke_up_from_button = false;
}
Log.info("Woke up!");
// Do work ...
Log.info("Doing work...");
delay(10000);
}
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
No action performed