element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Experts, Learning and Guidance
  • Technologies
  • More
Experts, Learning and Guidance
Ask an Expert Forum XIAO nRF52840 free-fall detection not working
  • Blog
  • Forum
  • Documents
  • Leaderboard
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Experts, Learning and Guidance to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • State Verified Answer
  • Replies 15 replies
  • Subscribers 275 subscribers
  • Views 2811 views
  • Users 0 members are here
  • ardunio
  • interrupts
  • nrf52840
  • free-fall
  • lsm6ds3
Related
See a helpful answer?

Be sure to click 'more' and select 'suggest as answer'!

If you're the thread creator, be sure to click 'more' then 'Verify as Answer'!

XIAO nRF52840 free-fall detection not working

TobiasR
TobiasR over 1 year ago

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.");
 }
 
}
And here is also the adapted sample from the double tap (which worked but doesn't when changing tap to free-fall):
#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); }
}
Does anyone have any idea what I'm doing wrong?
  • Sign in to reply
  • Cancel

Top Replies

  • TobiasR
    TobiasR over 1 year ago +4 verified
    To everyone having the same issue The issue was solved (sadly not by me but guys like you). So for anyone else having this issue you may have a look here forum.seeedstudio.com/.../9 for additional…
  • baldengineer
    baldengineer over 1 year ago +1
    My long-time experience with Seeedstudio is that their examples do not work. In fact, I have received pre-release boards that had broken examples from day 1 that never got fixed! Since the Xiao is really…
  • balajivan1995
    0 balajivan1995 over 1 year ago

    Can you please confirm you are using "Xiao nrf 52840 sense " not "xiao nrc 52840". If you are using sense variant, can you please run the i2c bus sniffer example in Arduino to check whether the imu module is discoverable or not?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • dougw
    0 dougw over 1 year ago

    Is free fall something the chip is supposed to detect or something your MCU will detect? Free fall presumably is when all acceleration goes to zero. Is there such a trigger condition?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • TobiasR
    0 TobiasR over 1 year ago in reply to balajivan1995

    I downloaded the Seeedstudio library (I bought it there and that's what they suggest).

    The Arduino IDE says I'm using

    Seeed XIAO nRF52840 Sense

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • TobiasR
    0 TobiasR over 1 year ago in reply to dougw

    Yes there is even an example of this on their website. It just is outdated I guess.

    The later code I posted is from their examples even.

    https://github.com/Seeed-Studio/Seeed_Arduino_LSM6DS3/blob/master/examples/FreeFallDetect/FreeFallDetect.ino

    And all the other examples work (I see something in the accelration and gyro, a double tap detection I found in the internet works with interrupts...)

    Just the free-fall doesn't.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • balajivan1995
    0 balajivan1995 over 1 year ago in reply to TobiasR

    Okay, verify imu is scannable just to be sure.

    delay() is a blocking function, if interrupt happens during that time it won't be noticed by the controller.  Try to reduce the blocking delay in loop or use non blocking delay using millis() function if you can

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • TobiasR
    0 TobiasR over 1 year ago in reply to balajivan1995

    The second project I posted was the one from from the samples.

    The first one is what I actually need with the interrupt. Yet both don't work.

    I tested it many times (and with multiple boards) so I doubt the 10ms is the problem - but I can give it another try with a shorter period. Maybe that helps.

    Still, something else seems to be wrong.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • balajivan1995
    0 balajivan1995 over 1 year ago in reply to TobiasR

    Seems like this is a common issue with xiao boards. Can you please try this one

    forum.seeedstudio.com/.../7

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • TobiasR
    0 TobiasR over 1 year ago in reply to balajivan1995

    Thanks for the suggestion but it works fine - except for the free fall detection.

    The gyro and accelerometer is working great. I tried the double-tap code from someone on the forum and it worked perfectly fine (and caused the interrupt).

    So it is not a communication issue with the IMU. The interrupt is not reported (or I configured something wrong) - I would guess.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • colporteur
    0 colporteur over 1 year ago in reply to dougw

    Thanks for the post. Your commentary motivated me to do some reading on free-fall. WOW! That math shite I loved when I worked in aviation.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • baldengineer
    0 baldengineer over 1 year ago in reply to balajivan1995

    No, interrupts work fine during a delay(). They will trigger and their ISR will run. 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube