How to get proper low power with nano 33 ble and mbed

Hello List,
As claimed in the blog about using mbed on the nano 33 ble it should be possible to get the quiescent current down to a few microAmperes per the spec of the NINO-B306.
The best I get is of the order of 250 microAmpere.

I get this by using a custom main function where I remove the USB CDC feature, setting some GPIO's to LOW and use wait_ms from mbed_wait_api.h
I use the following example.

#include <mbed.h>
#include <mbed_wait_api.h>

//  0.5 mA bij 10 Volt

using namespace mbed;

// override the default main function to remove USB CDC feature
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()
{
  //  Serial.begin(9600);

  pinMode(LED_PWR, OUTPUT);
  digitalWrite(LED_PWR, LOW);
  digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW);
  digitalWrite(PIN_ENABLE_I2C_PULLUP, LOW);
  
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

  //  0.25 mA bij 10 Volt
  //  NRF_POWER->SYSTEMOFF=1;
  
}

void loop()
{
  digitalWrite(LED_BUILTIN, LOW); //HIGH);
  wait_ms(100);
  digitalWrite(LED_BUILTIN, LOW);
  wait_ms(100);
}

I did not cut the 3.3 Volt line, but put 10 Volt on Vin. When putting the cpu to sleep, using NRF_POWER->SYSTEMOFF=1, I get 0.25 mA.
But when the above example runs it increased with 0.25 mA to 0.5 mA.

The processor is doing something apart from being in the standby state!
So what is happening, what is mbed still doing except waiting, some clock or something?
Can anybody shed some light on this?

UPDATE: a simpler example that just uses the regular delay() function behaves the same.

Thanks in advance, Sietse

PS. Note that I do not measure the current on the 3.3 Volt side, but this is close enough I think.

You should check this thread: Is the IMU still drawing current ? - Nano 33 BLE - Arduino Forum. A long thread but it may help.

In short, there is an error in the pins_arduino.h file which you can find usually under C:\Users......\AppData\Local\Arduino15\packages\arduino\hardware\mbed\1.1.4\variants\ARDUINO_NANO33BLE

These pin definitions are swapped compared to the variants.cpp file definitions;

Change it to:
#define PIN_ENABLE_I2C_PULLUP (32u)
#define PIN_ENABLE_SENSORS_3V3 (33u)

It got my system off routine down to 10 microAmps;

// *****************************************************************************
// Turn system off, only to be recovered by a reset, or dedicated event
// *****************************************************************************
static void systemOff(void)
{
#if DEBUG == 1
  Serial.println("Entering power down mode");
#endif

  // Close IMU and BLE modules
  IMU.end();
  BLE.end();
  
  // Leds off
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(LED_PWR, LOW);
  digitalWrite(LEDR, HIGH);
  digitalWrite(LEDG, HIGH);
  digitalWrite(LEDB, HIGH);

  // And save power by powering down the HX711 and Strain Gauge measurement
  hx711.power_down();

  // Enter system OFF, only to be recovered by a reset 
  NRF_POWER->SYSTEMOFF = 1;
}

And by the way I did measurements both powered from USB/Vin and 3V3 jumper cut running off a Coin Cell CR2477N with 950 mAh. I can easily swap from USB source to Coin Cell and do these measurements. System Off power is around 10-12 microAmps, at USB powered a little higher at around 20.

Thanks for the reply!

In the mean time I found a solution in also switching off the UART by adding the following to setup:

  //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

So now the current consumption is always around 250 uA.

This is almost all due to the DC/DC converter, so the current usage at 3.3 Volt is probably below 50 uA, but I didn't measure this.
If on the other hand you are using USB for power then the internal LDO regulator of the NINA block is used. That is more efficient (as you measured with 20 uA) and normally the way to go!

I cannot use the usb for the moment because I have 12 Volt, so I have to use Vin with the less efficient DC/DC converter.

Thanks, Sietse

PS 1. Changing pins_arduino.h or the values of the digitalWrites did not change much here.

PS 2. I could use a LDO with a low quiescent current (34 uA) to get from 12 Volt to 5 Volt for USB. That would get the quiescent current probably down to around 34+20 = 54 uA in total.

Thanks for the feedback, switching off the UART is also important for me to save further when running standalone and on battery power so I will try it as well.

Regarding the swapping of the pins; If you use the onboard IMU we found out that begin() and end() function calls use the wire library calls begin and end. This did not result in the power going down to the low uAmp levels when going to the system off state. It appeared that wire->end turned high the PIN_ENABLE_I2C_PULLUP, while effectively this was the PIN_ENABLE_SENSORS_3V3 pin due to the swapped definitions. So the end() call didn't do what it should do. Therefore they still have to fix these swapped definitions in the next release update. Even more important to have this right on the NANO BLE Sense type if you want to disable power to the on-board sensors.