XIAO BLE Sense in deep sleep mode

Have You tried this solution ?

https://github.com/khoih-prog/NRF52_TimerInterrupt

… should be good for “adafruit-bluefruit version”
I plan to check this in a few days.

I also assume that using

...
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);  
// or  sd_power_mode_set(NRF_POWER_MODE_CONSTLAT);  
sd_app_evt_wait();  // puts the nrf52 to sleep when there is nothing to do
...

timer interrupts described above should wake up my Xiao

… the same sketch is not working with XIAO ? have You tried ?

I plan to check this with my Xiao nrf52840 : bluefruit/softdevice and just sd_power_off , wake up by reset button. Hope it will run :slight_smile:

Yes, I looked at it. I also ended up not needed to wake up the board on a timer and using a pin interrupt instead which seems to work.

But the following note makes it not suitable for my needs, as I need to talk to BLE and Serial is needed for debugging. I was hoping it would have a “deferred” mode similar to regular Arduino pin interrupts, but it doesn’t.

For the time being I ended up with SoftwareTimer which seem to be part of the standard library for XIAO. It is also somewhat low level and also doesn’t have “deferred” option for callback. But it supports one-time timers and BLE and Serial seems to work in the callback.

1 Like

I prepared a sketch with SoftwareTimer and used sd_app_evt_wait() function to put my XIAO to LOWPWR mode
How can I check if this is working ?
The sketch is compiling, it is running …but I do not have a proper power meter to check if this sketch really make my XIAO running at low power.
this is my sketch

#include <Arduino.h>
#include <Adafruit_TinyUSB.h> // for Serial
#include <bluefruit.h>

/* SoftwareTimer is a helper class that uses FreeRTOS software timer
 * to invoke callback. Its periodic timing is flexible as opposed to
 * hardware timer and cannot be faster than rtos's tick which is configured
 * at  ~1 ms interval.
 *
 * If you need an strict interval timing, or faster frequency, check out
 * the hw_systick sketch example that use hardware systick timer.
 *
 * http://www.freertos.org/RTOS-software-timer.html
 */
SoftwareTimer blinkTimer;

void setup()
{
  Serial.begin(115200);
  Bluefruit.begin();          // Sleep functions need the softdevice to be active.
  sd_power_mode_set(NRF_POWER_MODE_LOWPWR); 
  pinMode(LED_BUILTIN, OUTPUT);  // initialize digital pin LED_BUILTIN as an output.
  blinkTimer.begin(1000, blink_timer_callback);  // Configure the timer with 1000 ms interval, with our callback
  blinkTimer.start();  // Start the timer
}

void loop()
{
  // do nothing here
}

/**
 * Software Timer callback is invoked via a built-in FreeRTOS thread with
 * minimal stack size. Therefore it should be as simple as possible. If
 * a periodically heavy task is needed, please use Scheduler.startLoop() to
 * create a dedicated task for it.
 *
 * More information http://www.freertos.org/RTOS-software-timer.html
 */
void blink_timer_callback(TimerHandle_t xTimerID)
{
  // freeRTOS timer ID, ignored if not used
  (void) xTimerID;
  Serial.println("timer callback");
  digitalToggle(LED_BUILTIN);
  sd_app_evt_wait(); // puts the nrf52 to sleep when there is nothing to do
}

Thanks for help.

1 Like

?? strange serial behaviour
I added one more line to the code above … just suspend loop
and now serial monitor is printing every 3 seconds. It looks like the XIAO is firing the softwaretimer every 1 second but serial is sending output every 3 seconds. Strange !?

I still can not check if xiao is really “system-on sleeping” (and consuming less power) hence I don’t have precise meter. If not - I will try tu use hardware timer.
If someone could check this out …would be great :slight_smile:

#include <Arduino.h>
#include <Adafruit_TinyUSB.h> // for Serial
#include <bluefruit.h>

/* SoftwareTimer is a helper class that uses FreeRTOS software timer
 * to invoke callback. Its periodic timing is flexible as opposed to
 * hardware timer and cannot be faster than rtos's tick which is configured
 * at  ~1 ms interval.
 *
 * If you need an strict interval timing, or faster frequency, check out
 * the hw_systick sketch example that use hardware systick timer.
 *
 * http://www.freertos.org/RTOS-software-timer.html
 */
SoftwareTimer blinkTimer;

void setup()
{
  Serial.begin(115200);
  Bluefruit.begin();          // Sleep functions need the softdevice to be active.
  sd_power_mode_set(NRF_POWER_MODE_LOWPWR); 
  pinMode(LED_BUILTIN, OUTPUT);  // initialize digital pin LED_BUILTIN as an output.
  blinkTimer.begin(1000, blink_timer_callback);  // Configure the timer with 1000 ms interval, with our callback
  blinkTimer.start();  // Start the timer

  suspendLoop(); // Suspend Loop() to save power, since we didn't have any code there
}

void loop()
{
  // do nothing here , loop is already suspended, CPU will not run loop() at all
}

/**
 * Software Timer callback is invoked via a built-in FreeRTOS thread with
 * minimal stack size. Therefore it should be as simple as possible. If
 * a periodically heavy task is needed, please use Scheduler.startLoop() to
 * create a dedicated task for it.
 *
 * More information http://www.freertos.org/RTOS-software-timer.html
 */
void blink_timer_callback(TimerHandle_t xTimerID)
{
  // freeRTOS timer ID, ignored if not used
  (void) xTimerID;
  Serial.print("timer callback at - ");
  Serial.println(millis());
  digitalToggle(LED_BUILTIN);
  sd_app_evt_wait(); // puts the nrf52 to sleep when there is nothing to do
}

serial monitor output

...
13:40:50.928 -> timer callback at - 222418
13:40:50.928 -> timer callback at - 223418
13:40:50.928 -> timer callback at - 224418
13:40:53.951 -> timer callback at - 225418
13:40:53.951 -> timer callback at - 226418
13:40:53.951 -> timer callback at - 227418
13:40:56.952 -> timer callback at - 228418
13:40:56.952 -> timer callback at - 229418
13:40:56.952 -> timer callback at - 230418
...

I’ll try it with the PPK2…standby.
:slight_smile: GL

2 Likes

power up

#define BUTTONPIN 4
...
nrf_gpio_cfg_sense_input(g_ADigitalPinMap[BUTTONPIN], NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); //wake from deep sleep

power down

sd_power_system_off();

However, the DCDC providing 3v3 to my peripherals remains powered on. Is there a way to shut it down?

How low did you go in current consumption with Xiao Ble Sense? 100uA is too high for me.

Can you share the code for sleep/wakeup with accelerometer on Xiao Ble Sense? Thanks

Can you please share full code? I want to wakeup Ble Sense on accelerometer interrupt.

Unless I’m missing the point of your question, it’s working as is, from post
https://forum.seeedstudio.com/t/xiao-ble-sense-in-deep-sleep-mode/263477/120?u=pj_glasso above.
uses the TAPs to wake it up.
HTH
GL :slight_smile:

Hello there.
May I ask how you turned off that Charge LED?

Hi there, Yea, No one has figured it out yet AFAIK. which ain’t much :grin:
HTH
GL
:wink:

2 Likes

Still not have been able to make the lowpower mode to work properly after reading all this thread… I can make the deepsleep work. I can assign a pin to wake from deepsleep, but it do a full system reset…

But I need the system to wakeup automatically at interval ( like every minutes to report then go back to sleep). So I need not a total sleep, but just lowering the power at max.

I can have a timer generate periodic interrupt. But if I use sd_app_evt_wait, the system don’t stop, it just keep like there was no instruction.


#include <Arduino.h>
#include <Adafruit_TinyUSB.h> // for Serial
#include <bluefruit.h>
#include "Arduino_nRF5x_lowPower.h"
// These define's must be placed at the beginning before #include "NRF52TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
// Don't define TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system.
#define TIMER_INTERRUPT_DEBUG         0
#define _TIMERINTERRUPT_LOGLEVEL_     3
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "NRF52TimerInterrupt.h"

#define WAKE_LOW_PIN  D0
// here I have handler for interrpupt... not present because it work fine....


void loop() {

    // setup your wake-up pins.
    pinMode(WAKE_LOW_PIN,  INPUT_PULLUP_SENSE);    // this pin (WAKE_LOW_PIN) is pulled up and wakes up the feather when externally connected to ground.
            
    digitalWrite(LED_BLUE, HIGH);          // just turn the blue led to show that i'M sleep mode

    sd_power_mode_set(POWER_MODE_LOW_POWER);
    Serial.print(millis());   // print the time to see if when I get bac
    __WFE();   // I suppose this is to enable event  for wake up
    __WFI();    // I suppose this is to enable interruption for wake up
    delay(2000);    // from comment I have seen on that thread, need to put a delay here
   
    sd_app_evt_wait();            // Here the system should go in standby , but does'nt
    //NRF_POWER->SYSTEMOFF = 1;   // If a put this active, the process stop, and will restart on pin activation, but the timer seem to freeze, When it restart, jump to reset
    digitalWrite(LED_BLUE, LOW);    // this should turn off the blue led telling me the programm has reach this point, but the led never go off immediately with sd_app_evt_wait, and never with SYSTEM OFF

`Texte préformaté`

Have You checked this issue ?

There doesn’t seem to be a way to shut off the 3v3 voltage regulator as it comes from a separate IC U6 and not the DCDC of the chip, according to the schematic. Charging characteristics of XIAO_nRF52840 and XIAO_ESP32C3 - Products & Technology / XIAO - Seeed Forum (seeedstudio.com)

If some of your peripherals draw less than 15mA, I can suggest connecting the ground and other pins of that peripheral to digital pins, and then setting the digital pins to HIGH right before deep sleep. Elsewhere it is suggested that “The max GPIO sink/source current is 15 mA. This is max both from one pin or as the total for all the pins (entire package).”

I was able to remove most of the quiescent current from a connected Neopixel by doing this, going from above 200uA to around 40uA in deep sleep.

Hi,

Di you measured what current is drained out of the sleep mode?
I get 4.1µA when the LED is off with this code:

#include "Adafruit_SPIFlash.h"


Adafruit_FlashTransport_QSPI flashTransport;

void QSPIF_sleep(void)
{
  flashTransport.begin();
  flashTransport.runCommand(0xB9);
  flashTransport.end();  
}

void setup() {
  digitalWrite(LED_GREEN, 1);
  QSPIF_sleep();
}

void loop() {

  digitalWrite(LED_GREEN, 0);
  delay(500);
  digitalWrite(LED_GREEN, 1);
  delay(5000);
}

Note: In my setup the device is powered by a 3V CR3220 connected on the 3V3 pin

Since the example code claims 3µA in “deep sleep”, I don’t know if it worth to struggle with this for 1µA. Especially considering that Nordic documentation states that going out of System OFF resets the device.

I tried the same code here on my XIAO BLE board, but measure 250uA when LED off.

A few comments/questions:

  • Which board definition were you using?
  • I tried the “Adafruit ItsyBitsy nRF52840 Express” and “Adafruit Feather nRF52840 Express”
  • Compiler didn’t like LED_GREEN, wonder how you found that?
  • I tried to power both via the 3v3 pin and via the bat+ pin

Well,
I don’t know about the board definitions you’re speaking about, I just selected “Seeed Xiao nRF52840” from the board selector. Notice that I don’t have the “Sense” model (there is no IMU on my board).
image

Hello, could you please share an example or some hints on how to wake up the xiao ble after the deep sleep mode with the suggested RESET or RTC? Is it possible to reset the board from code or program an alarm to wake up?

Many thanks in advance!