How to Turn off and on through motion recognition

Hello,

I am coding on a Seeed Xiao NRF52840 Sense, with the LSM6DS3 6-axis chip. I was wanting to write some code on possibly putting the chip into power off mode, but then when a significant motion is detected by the LSM6DS3, if that would be able to wake it up into the power on mode?

Currently I am using the Arduino IDE, with the appropriate libraries and I am coding on a MAC. 

I have seen this ticket which wakes up from a double tap, but i was wondering if there was a way to make it wakeup from any "significant Motion found in the high level example for the LSM6DS3, the code snippets I am referencing will be located below.

Any help would be appreciated.

This is the Double tap to wakeup from an interrupt.

/*****************************************************************************/
// 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); }
}

This is the high level example with significant motion.

#include <LSM6DS3.h>
#include <Wire.h>

//Create a instance of class LSM6DS3
LSM6DS3 myIMU(I2C_MODE, 0x6A);    //I2C device address 0x6A
float aX, aY, aZ, gX, gY, gZ;
const float accelerationThreshold = 2.5; // threshold of significant in G's
const int numSamples = 119;
int samplesRead = numSamples;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial);
  //Call .begin() to configure the IMUs
  if (myIMU.begin() != 0) {
    Serial.println("Device error");
  } else {
    Serial.println("aX,aY,aZ,gX,gY,gZ");
  }
}

void loop() {
  // wait for significant motion
  while (samplesRead == numSamples) {
    // read the acceleration data
    aX = myIMU.readFloatAccelX();
    aY = myIMU.readFloatAccelY();
    aZ = myIMU.readFloatAccelZ();

    // sum up the absolutes
    float aSum = fabs(aX) + fabs(aY) + fabs(aZ);

    // check if it's above the threshold
    if (aSum >= accelerationThreshold) {
      // reset the sample read count
      samplesRead = 0;
      break;
    }
  }

  // check if the all the required samples have been read since
  // the last time the significant motion was detected
  while (samplesRead < numSamples) {
    // check if both new acceleration and gyroscope data is
    // available
    // read the acceleration and gyroscope data

    samplesRead++;

    // print the data in CSV format
    Serial.print(myIMU.readFloatAccelX(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatAccelY(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatAccelZ(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroX(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroY(), 3);
    Serial.print(',');
    Serial.print(myIMU.readFloatGyroZ(), 3);
    Serial.println();

    if (samplesRead == numSamples) {
      // add an empty line if it's the last sample
      Serial.println();
    }
  }
}

Parents
  • Hi

    That would be possible as long as the accelerometer is powered while the nRF52840 is turned off. Then you can configure the pin going from the accelerometer as a wake up pin. Then when the accelerometer reports a change in motion it will wake up the nRF52840.

    When the nRF52840 is in system OFF it can only be awakened by an external event, either on a GPIO or the NFC antenna.

    Best regards,

    Simon

Reply
  • Hi

    That would be possible as long as the accelerometer is powered while the nRF52840 is turned off. Then you can configure the pin going from the accelerometer as a wake up pin. Then when the accelerometer reports a change in motion it will wake up the nRF52840.

    When the nRF52840 is in system OFF it can only be awakened by an external event, either on a GPIO or the NFC antenna.

    Best regards,

    Simon

Children
No Data
Related