Setting up the arduino BLE board for low power applications [Compilation]

Hi there,

As we may know, the arduino BLE is a powerful board based on the nRF52840 microcontroller, which is intended for IoT applications due to its low power consumption and powerful BLE integrations.

Unfortunately, as some of us experienced, it draws a high ammout of current on its default mode. So, in order to achieve a decent power consumption for our projects, we need to do some hardware/software modifications. After some research made, this is what I found.

First of all, our friend @pert discovered this:

BareMinimum sketch:

void setup() {}

void loop() {}



with USB power: 17.4 mA

BareMinimum sketch with 3.3 V jumper cut, powered via the 3.3 V pin: 9.49 mA [A 3.3V voltage supply is now needed, you can use the 3.3V output of an Arduino UNO]

![|500x281](https://user-images.githubusercontent.com/25133882/74822083-dd89ed80-5304-11ea-9c20-994b79534dfd.png)
[img source](https://github.com/arduino-libraries/ArduinoBLE/pull/15#issuecomment-588129509)

"ON" LED turned off:



void setup() {
  digitalWrite(LED_PWR, LOW);
}
void loop() {}



7.6 mA

1 minute sleep per loop:


void setup() {
  digitalWrite(LED_PWR, LOW);
}
void loop() {
  delay(60 * 1000);
}



1.747 mA

PIN_ENABLE_SENSORS_3V3 set to LOW:


void setup() {
  digitalWrite(LED_PWR, LOW);
  digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW);
}
void loop() {
  delay(60 * 1000);
}



1.741 mA

PIN_ENABLE_I2C_PULLUP set to LOW:


void setup() {
digitalWrite(LED_PWR, LOW);
digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW);
digitalWrite(PIN_ENABLE_I2C_PULLUP, LOW);
}

void loop() {
delay(60 * 1000);
}



1.738 mA

Unplug USB cable: 1.240 mA

If you cut the 3.3v [SJ4] jumper, you can still use serial communication to read/send information on the serial monitor and keep uploading new sketches, you just will need to atach a 3.3V supply to the 3.3V pin (make sure to keep the input voltage always below 3.6V, otherwise, your BLE board will be burned), and connect both grounds (source-arduino) together.

If you won't be using serial communication on your project, our friend @farome, showed us here how to remove the USB CDC feature to save even more power:

555µA by disabling USB CDC feature:
Warning: This interferes the USB communication with the arduino board. You will need to press reset twice to be able to upload a new sketch.

//Override the default main function to remove USB CDC feature - @farome contribution

int main(void)
{
  init();
  initVariant();

//Remove USB CDC feature
//#if defined(SERIAL_CDC)
//  PluggableUSBD().begin();
//  SerialUSB.begin(115200);
//#endif

setup();

for (;:wink: {
    loop();
    if (arduino::serialEventRun) arduino::serialEventRun();
  }

return 0;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_PWR, LOW); // turn off power LED
  digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW); // turn off sensors
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(5000); // 5s for easier current measurment
  digitalWrite(LED_BUILTIN, LOW);
  delay(5000);
}

Also our friend @Steen_Petersen found this command, which allows us to shut down the main CPU and achieve a very low power consumption.

I have been able to reproduce your results almost exactly but 0.9 ma is still way too much for the project so I needed to bring it even further down. I have done this by putting the board into

NRF_POWER->SYSTEMOFF = 1;

While in this state I have been able to see the board get as low as +-30 µa which is way more in line with what I would expect when the system is off.

The main problem with this command is that you will need an external interruption or press reset button to wake up the MCU and be able to use it again.

So, if you want to be able to get a decent low power consumption without disabling the CPU, here is what i found.

//Disabling UART0 (saves around 300-500µA) - @Jul10199555 contribution
NRF_UART0->TASKS_STOPTX = 1;
NRF_UART0->TASKS_STOPRX = 1;
NRF_UART0->ENABLE = 0;

*(volatile uint32_t *)0x40002FFC = 0;
*(volatile uint32_t *)0x40002FFC;
*(volatile uint32_t *)0x40002FFC = 1; //Setting up UART registers again due to a library issue

with this sequence, you can disable the UART0 port and save around 300-500µA. Just note that if you disable this or the CDC USB feature, you won't be able to use serial communications on any of your projects.


Summarizing, here's a very low power version of the blink example, without shutting down the main CPU (up to 11µA with all LEDs off - 4mA with power LED on).

//Ultra Low Power blink example. Tested on Arduino nano 33 BLE board and nRF528x (Mbed OS) V1.1.6 core

//Override the default main function to remove USB CDC feature - @farome contribution
int main(void){
init();
initVariant();

//Disabling UART0 (saves around 300-500µA) - @Jul10199555 contribution
NRF_UART0->TASKS_STOPTX = 1;
NRF_UART0->TASKS_STOPRX = 1;
NRF_UART0->ENABLE = 0;

*(volatile uint32_t *)0x40002FFC = 0;
*(volatile uint32_t *)0x40002FFC;
*(volatile uint32_t *)0x40002FFC = 1; //Setting up UART registers again due to a library issue

//Removing USB CDC feature
//#if defined(SERIAL_CDC)
//  PluggableUSBD().begin();
//  SerialUSB.begin(115200);
//#endif

  setup();
  for(;;){
    loop();
//If you won't be using serial communication comment next line
//    if(arduino::serialEventRun) arduino::serialEventRun();
  }
  return 0;
}

void setup(){
//pinMode(pin, OUTPUT) is already set for these 3 pins on variants.cpp
  digitalWrite(LED_PWR, LOW); // @pert contribution
//Pins are currently swapped. Lower current achieved if setting both pins to HIGH
  digitalWrite(PIN_ENABLE_SENSORS_3V3, HIGH); //PIN_ENABLE_I2C_PULLUP - @pert contribution
  digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); //PIN_ENABLE_SENSORS_3V3 - @pert contribution
}

void loop(){
  delay(60*1000); //22µA USB cable, 11 µA USB cable unplugged
  digitalWrite(LED_PWR, HIGH);
  delay(5*1000);
  digitalWrite(LED_PWR, LOW);
}

And finally, here's how to get even a even lower power consumption by shuttiing down the CPU unit (up to 5µA with all LEDs off - 4mA with power LED on)..

//Ultra Low Power blink example. Tested on Arduino nano 33 BLE board and nRF528x (Mbed OS) V1.1.6 core

//Override the default main function to remove USB CDC feature - @farome contribution
int main(void){
init();
initVariant();

//Disabling UART0 (saves around 300-500µA) - @Jul10199555 contribution
NRF_UART0->TASKS_STOPTX = 1;
NRF_UART0->TASKS_STOPRX = 1;
NRF_UART0->ENABLE = 0;

*(volatile uint32_t *)0x40002FFC = 0;
*(volatile uint32_t *)0x40002FFC;
*(volatile uint32_t *)0x40002FFC = 1; //Setting up UART registers again due to a library issue

//Removing USB CDC feature
//#if defined(SERIAL_CDC)
//  PluggableUSBD().begin();
//  SerialUSB.begin(115200);
//#endif

  setup();
  for(;;){
    loop();
//If you won't be using serial communication comment next line
//    if(arduino::serialEventRun) arduino::serialEventRun();
  }
  return 0;
}

void setup(){
//pinMode(pin, OUTPUT) is already set for these 3 pins on variants.cpp
  digitalWrite(LED_PWR, LOW); // @pert contribution
//Pins are currently swapped. Lower current achieved if setting both pins to HIGH
  digitalWrite(PIN_ENABLE_SENSORS_3V3, HIGH); //PIN_ENABLE_I2C_PULLUP - @pert contribution
  digitalWrite(PIN_ENABLE_I2C_PULLUP, HIGH); //PIN_ENABLE_SENSORS_3V3 - @pert contribution
}

void loop(){
  delay(60*1000); //22µA USB cable, 11 µA USB cable unplugged
  digitalWrite(LED_PWR, HIGH);
  delay(5*1000);
  digitalWrite(LED_PWR, LOW);
// Shutting down CPU as soon as first loop ends
  NRF_POWER->SYSTEMOFF = 1; //15µA USB cable plugged, 5µA USB cable unplugged - @Steen_Petersen contribution 
}

That's it for today guys, hope this post can be helpful for you all. I'll try to keep it updated with new findings and discoveries reported.

1 Like

Hi and thanks for this guide, one question:

.........and connect both grounds (source-arduino) together.

How to understand that part........?

So should both grounds be wired together to battery, etc.?!?!??!

Klaus

Hi there,
I followed this, and in my scirpt I in setup take angle and temperature measuments and in loop meassue some sound, and as I kill by BLE.end, IMU.end, PDM.end HTS.end after use and then reset BLE33 sense in end of loop, I get the follwing power consumption:

2 sec = 6mA (LED on + temp + angle).
30 sec = 3,3 mA (Loop sound detection).
180 sec = 1,32 mA (deep sleep, no serial and no USB, sensors off, etc.).

Hence, I get an avange of 1,65mA ~ hence if 700mah LiFePO4 battery, I should get 17 days run?

Thank you jul10199555 for the detailed post, I followed it and got very low power consumption for the blink sketch. However, I would like to use the NANO BLE for what it was built for, i.e. BLE. Once I activate the BLE functionality by calling BLE.begin(), the current consumption jumps from few µA to ~1ma, even when just advertising with an interval is few seconds.
looking at at Nordic website Link, I saw this:

Most BLE examples in the SDK will include the power_manage call in the main function. This call uses the sd_app_event_wait() softdevice call (or power_manage()) which enables the System On low power mode, which keeps current consumption to a minimum.

Any ideas how to do this in the Arduino framework ?