element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • 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 287 subscribers
  • Views 3067 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 2 years 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 2 years 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 2 years 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…
Parents
  • TobiasR
    +1 TobiasR over 2 years ago

    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 info.

    But in short: you need to enable the TIMER_EN flag in the TAP_CFG register.

    I added a pull request in the sample code of seeedstudio. Once this is accepted the examples from their website should work again!

    Thanks to everyone for your support!

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • Reject Answer
    • Cancel
Reply
  • TobiasR
    +1 TobiasR over 2 years ago

    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 info.

    But in short: you need to enable the TIMER_EN flag in the TAP_CFG register.

    I added a pull request in the sample code of seeedstudio. Once this is accepted the examples from their website should work again!

    Thanks to everyone for your support!

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • Reject Answer
    • Cancel
Children
No Data
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