Hello there,
I'm trying to detect free falls with my XIAO nRF52840 which has the LSM6DS3 IMU included.
However, I can't make it work - neither "by polling" not receiving any interrupt for this.
I found some good examples for (Double) Taps with interrupts and it works fine.
But when I adapt the code the free-fall detection I never get anything.
And just to be sure I bought multiple nRF52840 boards but none seems to work. So they are not just broken.
Even the sample code from the libraries doesn't result anything (it compiles, just does not trigger).
I even asked in forums like here
https://forum.arduino.cc/t/lsm6ds3-free-fall-detection-not-working/1163290/7
and
https://forum.seeedstudio.com/t/xiao-nrf52840-free-fall-detection-not-working/272103
Maybe someone here might know more. I saw some good blog posts and smart answers here.
The adapted sample code (also from Sparksfun) looks like that:
#include "LSM6DS3.h" #include "Wire.h" #include "SPI.h" LSM6DS3 myIMU( I2C_MODE, 0x6A ); void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.println("Sketch came out of reset.\n"); if( myIMU.begin() != 0 ) { Serial.print("Error at begin().\n"); } else { Serial.print("\nbeginCore() passed.\n"); } uint8_t errorAccumulator = 0; uint8_t dataToWrite = 0; //Setup the accelerometer****************************** dataToWrite = 0; //Start Fresh! dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_200Hz; dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_2g; dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_416Hz; // //Now, write the patched together data errorAccumulator += myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, dataToWrite); errorAccumulator += myIMU.readRegister(&dataToWrite, LSM6DS3_ACC_GYRO_CTRL4_C); // Write 00h into WAKE_UP_DUR errorAccumulator += myIMU.writeRegister( LSM6DS3_ACC_GYRO_WAKE_UP_DUR, 0x00 ); // Set FF threshold (FF_THS[2:0] = 011b) // Set six samples event duration (FF_DUR[5:0] = 000110b) // Write 33h into FREE_FALL errorAccumulator += myIMU.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x33); // FF interrupt driven to INT1 pin // Write 10h into MD1_CFG errorAccumulator += myIMU.writeRegister( LSM6DS3_ACC_GYRO_MD1_CFG, 0x10 ); // Also route to INT2 pin // Write 10h into MD1_CFG errorAccumulator += myIMU.writeRegister( LSM6DS3_ACC_GYRO_MD2_CFG, 0x10 ); // Latch interrupt // Write 01h into TAP_CFG errorAccumulator += myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x01); if( errorAccumulator ) { Serial.println("Problem configuring the device."); } else { Serial.println("Device O.K."); } } void loop() { uint8_t readDataByte = 0; //Read the wake-up source register myIMU.readRegister(&readDataByte, LSM6DS3_ACC_GYRO_WAKE_UP_SRC); //Mask off the FF_IA bit for free-fall detection readDataByte &= 0x20; //Check for free-fall if( readDataByte ) { //debounce delay(10); Serial.println("Interrupt caught. Free fall detected."); } }
#include "LSM6DS3.h" #include "Wire.h" LSM6DS3 myIMU(I2C_MODE, 0x6A); #define int1Pin PIN_LSM6DS3TR_C_INT1 volatile uint8_t interruptCount = 0; // Amount of received interrupts uint8_t prevInterruptCount = 0; // Interrupt Counter from last loop void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } Serial.println("--- START ---"); pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); pinMode(LED_BLUE, OUTPUT); setLedRGB(false, false, true); // set blue led myIMU.settings.accelEnabled = 1; myIMU.settings.tempEnabled = 1; myIMU.settings.gyroEnabled = 1; // Gyro currently not used, disabled to save power if (myIMU.begin() != 0) { Serial.println("IMU error"); } else { Serial.println("IMU OK!"); } setupFreeFallInterrupt(); 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(); } myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x01); // LATCHED delay(500); } // -------------------- System ------------------------- // void goToPowerOff() { setLedRGB(false, false, false); Serial.println("Going to System OFF"); setupFreeFallInterrupt(); // 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 setupFreeFallInterrupt() { uint8_t error = 0; uint8_t dataToWrite = 0; // 4A = 01001010 // 0000 10 10 LSM6DS3_ACC_GYRO_BW_XL_100Hz LSM6DS3_ACC_GYRO_FS_XL_4g dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_100Hz; // 0000 0001 200Hz dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_4g; // 0000 0000 2g dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_104Hz;// 0100 0000 104Hz error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, dataToWrite); // Set the ODR config register to ODR/4 -> 1001 //error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL8_XL, 0x09); // p.61 // enable linear acceleration sensor //error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_CTRL9_XL, 0x38); // Wakeup source (p.62) // 00100000 x20 // 00101111 x2f FF error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_SRC, 0b00100000); // TAP_CFG (58h) Register (page 77) // Latch interrupt - Write 01h into TAP_CFG error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0b00000001); // LATCHED //MD1_CFG (5Eh) Functions routing on INT1 register (page 80) // Free fall error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0b000010000); // 00010000 //p.79 -> default valuesMD1_CFG error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_DUR, 0b00000000); // p.80 -> // 00110 : 6 events // 011 : 312mg threshold //error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x33); // 00110 011 error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0b000110); // 00001 011 1x 312mg //error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x30); // 00110 000 156mg //error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x00); // 00000 000 156mg //error += myIMU.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x07); // 00000 111 500mg if (error) { Serial.println("Problem configuring the device."); } else { Serial.println("Device O.K."); } } void int1ISR() { interruptCount++; } // -------------------- Utilities ------------------------- // void setLedRGB(bool red, bool green, bool blue) { if (!blue) { digitalWrite(LED_BLUE, HIGH); } else { digitalWrite(LED_BLUE, LOW); } if (!green) { digitalWrite(LED_GREEN, HIGH); } else { digitalWrite(LED_GREEN, LOW); } if (!red) { digitalWrite(LED_RED, HIGH); } else { digitalWrite(LED_RED, LOW); } }