Getting lower power consumption on Seeed XIAO nRF52840

@daCoder . I am working with @DBurd49ers on trying to optimize the sleep mode.

Here is the current code we are using:

#include "LSM6DS3.h"
#include "Wire.h"
#include <Arduino.h>
/*#include <SPI.h>
#include <SdFat.h>*/
#include <Adafruit_FlashTransport.h>
// for flashTransport definition
//#include "flash_config.h"
#include <bluefruit.h>
//#include <ArduinoBLE.h>
//#include <LowPower.h>

//const int slaveSelectPin = 12;

//Adafruit_FlashTransport_QSPI flashTransport;
 
//BLEService ledService("3ac82d02-002b-4ccb-b68c-1c7839cbc4c0");

byte accelArray[16];

//BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
//BLECharacteristic switchCharacteristic("3ac82d02-002b-4ccb-b68c-1c7839cbc4c0", BLERead | BLEWrite, sizeof(accelArray), true);

LSM6DS3 myIMU(I2C_MODE, 0x6A);
#define intPin PIN_LSM6DS3TR_C_INT1

int interrupts_received = 0;
int prev_interrupts_received = 0;
int no_change = 0;
int ble_enabled = 0;
int work_LED_status = HIGH;

#define MANUFACTURER_ID   0x0059

// "nRF Connect" app can be used to detect beacon
uint8_t beaconUuid[16] =
{
  0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
  0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
};

// A valid Beacon packet consists of the following information:
// UUID, Major, Minor, RSSI @ 1M
BLEBeacon beacon(beaconUuid, 0x0102, 0x0304, -54);

void setup() {

  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  
  digitalWrite(LED_RED, HIGH);
  digitalWrite(LED_GREEN, HIGH);
  digitalWrite(LED_BLUE, work_LED_status);

    Adafruit_FlashTransport_QSPI flashTransport;

    Bluefruit.begin();
    Bluefruit.setName("Ver Mac Device 1"); 
    Bluefruit.setTxPower(-40); 
    // off Blue LED for lowest power consumption
    Bluefruit.autoConnLed(false);
    //Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values

    // Manufacturer ID is required for Manufacturer Specific Data
    beacon.setManufacturer(MANUFACTURER_ID);

    // Setup the advertising packet
    startAdv();

  

    flashTransport.begin();
    flashTransport.runCommand(0xB9);
    flashTransport.end();

    //myIMU.settings.gyroEnabled = 0; // Gyro currently not used, disabled to save power
    if (myIMU.begin() != 0) {
        //Serial.println("Device error");
    } else {
        //Serial.println("Device OK!");
    }

    delay(300);

    setupSingleTapInterrupt();
    

    pinMode(intPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(intPin), intIncrementer, LOW);
}

void startAdv(void)
{  
  // Advertising packet
  // Set the beacon payload using the BLEBeacon class populated
  // earlier in this example
  Bluefruit.Advertising.setBeacon(beacon);

  // Secondary Scan Response packet (optional)
  // Since there is no room for 'Name' in Advertising packet
  Bluefruit.ScanResponse.addName();
  
  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   * 
   * Apple Beacon specs
   * - Type: Non connectable, undirected
   * - Fixed interval: 100 ms -> fast = slow = 100 ms
   */
  //Bluefruit.Advertising.setType(BLE_GAP_ADV_TYPE_ADV_NONCONN_IND);
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(3067, 3067);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds  
}

void loop() {

    delay(100);

    if (no_change >= 60)
    {
        //setLedRGB(true, false, false);
        //delay(10000);
        setLedRGB(false, false, false);
        //delay(10000);
        lowPowerMode();
    }

    if (interrupts_received > prev_interrupts_received)
    {
        prev_interrupts_received = interrupts_received;
        no_change = 0;
    }
    else
    {
        //setLedRGB(true, false, false);
        //delay(100);
        no_change++;
    }
}

void setupSingleTapInterrupt()
{
    myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, 0x60);
    myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x8E);
    myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_THS_6D, 0x80);
    myIMU.writeRegister(LSM6DS3_ACC_GYRO_INT_DUR2, 0x7F);
    myIMU.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_THS, 0x01);
    myIMU.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0x20);
}

void lowPowerMode()
{
    //Serial.println(F("Powering down system!"));
    nrf_gpio_cfg_sense_input(digitalPinToInterrupt(intPin), NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
    delay(1000);
    sd_power_system_off();
    NRF_POWER->SYSTEMOFF = 1;
    /*sd_power_mode_set(NRF_POWER_MODE_LOWPWR);

    sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);

    sd_power_system_off();*/
}

void intIncrementer() 
{
    interrupts_received++;
}

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(LED_BUILTIN, HIGH); } else { digitalWrite(LED_BUILTIN, LOW); }
}

I believe our IMU interrupt is not working but trying to understand if this is related to the proper PIN setup or the soft device ignoring the interrupt when sleeping? Any advise on how to work around this?

1 Like