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]  [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 (; {
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.