Here is my example, if anybody is interested.
At startup LED is blue, a double tap leads to an interrupt and LED blinks green. After 5 interrupts, XIAO BLE Sense goes into System OFF state (LED off), while LSM6DS3TR-C stays awake, looking for double taps. If another double tap occures, XIAO BLE Sense wakes up (LED blue).
If you want to monitor serial, be sure to close and reopen after wake up.
My current measurements (via battery tabs only):
- XIAO BLE Sense and IMU active (gyro disabled - not needed for example): 1.68 mA
- IMU active, XIAO BLE Sense in System OFF: 450µA
Because deep sleep is currently widely discussed: I did not modify the shipped bootloader, and i’m working with Board Firmware 2.6.1
/*****************************************************************************/
// IMU Interrupt Example for XIAO BLE Sense
// This example shows how to configure LMSD6S3TR-C on XIAO BLE SENSE to interrupt
// on INT1 after a "Double Tap" was recognized.
// Additionally, the device goes into System OFF state, after 5 interrupts were
// received. Another "Double Tap" will wake up the device again.
//
// by chuck
/*******************************************************************************/
#include "LSM6DS3.h"
#include "Wire.h"
LSM6DS3 myIMU(I2C_MODE, 0x6A);
#define int1Pin PIN_LSM6DS3TR_C_INT1
uint8_t interruptCount = 0; // Amount of received interrupts
uint8_t prevInterruptCount = 0; // Interrupt Counter from last loop
void setup() {
Serial.begin(9600);
pinMode(LEDR, OUTPUT);
pinMode(LEDG, OUTPUT);
pinMode(LEDB, OUTPUT);
setLedRGB(false, false, true); // set blue led
myIMU.settings.gyroEnabled = 0; // Gyro currently not used, disabled to save power
if (myIMU.begin() != 0) {
Serial.println("IMU error");
} else {
Serial.println("IMU OK!");
}
setupDoubleTapInterrupt();
pinMode(int1Pin, INPUT);
attachInterrupt(digitalPinToInterrupt(int1Pin), int1ISR, RISING);
}
void loop() {
setLedRGB(false, false, true); // reset led to blue only
Serial.print("\Iterrupt Counter: ");
Serial.println(interruptCount);
// if interrupt was received in this cycle
if (interruptCount > prevInterruptCount) {
Serial.println("\Interrupt received!");
setLedRGB(false, true, false); // set green only
}
prevInterruptCount = interruptCount;
if (interruptCount >= 5) {
// Trigger System OFF after 5 interrupts
goToPowerOff();
}
delay(500);
}
// -------------------- System ------------------------- //
void goToPowerOff() {
setLedRGB(false, false, false);
Serial.println("Going to System OFF");
setupDoubleTapInterrupt(); // not needed here, if already applied..
delay(100); // delay seems important to apply settings, before going to System OFF
//Ensure interrupt pin from IMU is set to wake up device
nrf_gpio_cfg_sense_input(digitalPinToInterrupt(int1Pin), NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
// Trigger System OFF
NRF_POWER->SYSTEMOFF = 1;
}
// -------------------- Interrupts ------------------------- //
void setupDoubleTapInterrupt() {
uint8_t error = 0;
uint8_t dataToWrite = 0;
// Double Tap Config
myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, 0x60);
myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x8E);// INTERRUPTS_ENABLE, SLOPE_FDS
myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_THS_6D, 0x8C);
myIMU.writeRegister(LSM6DS3_ACC_GYRO_INT_DUR2, 0x7F);
myIMU.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_THS, 0x80);
myIMU.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0x08);
}
void int1ISR()
{
interruptCount++;
}
// -------------------- Utilities ------------------------- //
void setLedRGB(bool red, bool green, bool blue) {
if (!blue) { digitalWrite(LEDB, HIGH); } else { digitalWrite(LEDB, LOW); }
if (!green) { digitalWrite(LEDG, HIGH); } else { digitalWrite(LEDG, LOW); }
if (!red) { digitalWrite(LEDR, HIGH); } else { digitalWrite(LEDR, LOW); }
}