… 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
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.
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
}
?? 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
#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
...
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é`
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.
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.
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).
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?