I was trying the free-fall detect sample from the library but I don’t get anything. I see the start logs in the serial monitor but after that it gets quiet.
I was wondering if everything is correct there. In the loop the wakeup register is checked but always 0.
I had to go back to 2.9.0 To get it to work as b4.
HTH
GL
//poatched and toasted by pjg
/*******************************************************************************/
#include "LSM6DS3.h"
#include "Wire.h"
#include <U8x8lib.h>
LSM6DS3 myIMU(I2C_MODE, 0x6A); // IMU
#define int1Pin PIN_LSM6DS3TR_C_INT1
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE);
// OLEDs without Reset of the Display
const int buttonPin = 1; // the number of the pushbutton pin
int buttonState = 0; // variable for reading the pushbutton status
int BuzzerPin = A3;
uint8_t interruptCount = 0; // Amount of received interrupts
uint8_t prevInterruptCount = 0; // Interrupt Counter from last loop
void setup() {
Serial.begin(9600);
delay(1000); //relax...
Serial.println("Processor came out of reset.\n");
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
pinMode(LED_BUILTIN, OUTPUT);// initialize the LED pin as an output:
pinMode(buttonPin, INPUT_PULLUP);// initialize the pushbutton pin as an input:
pinMode(BuzzerPin, OUTPUT);
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!");
}
Serial.println("\nLSM6D3 'High Level Example' compiled on "__DATE__ " at " __TIME__);
setupDoubleTapInterrupt();
pinMode(int1Pin, INPUT);
attachInterrupt(digitalPinToInterrupt(int1Pin), int1ISR, RISING);
u8x8.setFont(u8x8_font_8x13B_1x2_r);
u8x8.clearDisplay();
u8x8.setCursor(0, 0);
u8x8.print("Tap Demo");
}
void loop() {
setLedRGB(false, false, true); // reset led to blue only
u8x8.setCursor(0, 3);
u8x8.print(interruptCount);
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 >= 3) {
// Trigger System OFF after 5 interrupts
goToPowerOff();
}
delay(500);
}
// -------------------- System ------------------------- //
void goToPowerOff() {
setLedRGB(false, false, false);
Serial.println("Going to System OFF");
u8x8.clearDisplay();
u8x8.setCursor(0, 3);
u8x8.print("SLEEP");
setupDoubleTapInterrupt(); // not needed here, if already applied..
delay(1000); // 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);
delay(2000); // Required delay
// 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); //* Acc = 416Hz (High-Performance mode)// Turn on the accelerometer
// ODR_XL = 416 Hz, FS_XL = 2g
myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x8E);// INTERRUPTS_ENABLE, SLOPE_FDS// Enable interrupts and tap detection on X, Y, Z-axis
myIMU.writeRegister(LSM6DS3_ACC_GYRO_TAP_THS_6D, 0x85);// Set tap threshold 8C
myIMU.writeRegister(LSM6DS3_ACC_GYRO_INT_DUR2, 0x7F);// Set Duration, Quiet and Shock time windows 7F
myIMU.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_THS, 0x80);// Single & double-tap enabled (SINGLE_DOUBLE_TAP = 1)
myIMU.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0x08);// Double-tap interrupt driven to INT1 pin
}
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); }
}
Ah’ OK I see that now. So are you getting interrupts ?
are you able to reproduce the video "impact detection with the polling of the Threshold and Time?
LMK,
GL
You want ;
Pseudo-code
To summarize, here is the pseudo-code required to initialize free-fall detection
Set event duration (FF_DUR5 bit) - Write 00h into WAKE_UP_DUR
Set FF threshold (FF_THS[2:0] = 011b) and set six samples event duration (FF_DUR[5:0] = 000110b) - Write 33h into FREE_FALL
Drive free-fall interrupt to INT1 pin - Write 10h into MD1_CFG
Latch interrupt - Write 01h into TAP_CFG
To check if a free-fall event has occurred, read register WAKE_UP_SRC and check if bit 5 (FF_IA) is set
main points are the Freefall has Interrupt has to be latched and you still poll for the interrupt to have occurred. (or attach it to another pin or flag in your interrupt routine.)
yours looks like the sparkfun example btw
HTH
GL
Hey there, thanks for your help. As stated I copied the code from someone in this forum who wanted the double tap interrupt. And for that purpose everything works perfectly fine! Hence my thought it shouldn’t be too hard to switch to free-fall.
Regarding your suggestions, I thought I have almost all of these settings, haven’t I?
I was not sure about the FF_DUR to be honest. The documentation states
Free-fall duration event. Default: 0
But what values can I enter there? I mean is this something like “millis” or “check cycles” or “processor ticks”? But then again, these are some flags only. So I’m confused.
Hi there,
Well It looks like it’s not complete, and the thing about the Interrupt and a Pin needing attached . When I get some free time I’ll look closer but you are close but I think your not getting the interrupt from the FF the duration is 153ms min. afaik
The address and the register bit as well as the Rising or Falling edge of the Interrupt all need to be compatible logic.
HTH
GL
Hello there,
thanks for all the feedback. I tried to fix things but had no success.
The blog post that explains a little more was nice and gave some insights but I still can’t make it work.
I bought another nRF52840 but have the same issue - so the chip is not broken or so.
I even tried to fix the sample code from the library but it’s not working either.
#include "LSM6DS3.h"
#include "Wire.h"
#define CLEAR_STEP true
#define NOT_CLEAR_STEP false
//Create a instance of class LSM6DS3
LSM6DS3 lsm6ds3(I2C_MODE, 0x6A); //I2C device address 0x6A
uint16_t detectCount = 0;
void setup() {
Serial.begin(9600);
while (!Serial);
if (lsm6ds3.begin() != 0) {
Serial.println("Device error");
} else {
Serial.println("Device OK!");
}
if (0 != config_free_fall_detect()) {
Serial.println("Fail to configure!");
} else {
Serial.println("Success to Configure!");
}
}
void loop() {
uint8_t readDataByte = 0;
//Read the wake-up source register
lsm6ds3.readRegister(&readDataByte, LSM6DS3_ACC_GYRO_WAKE_UP_SRC);
//Mask off the FF_IA bit for free-fall detection
readDataByte &= 0x20;
if (readDataByte) {
detectCount ++;
Serial.print("Free fall detected! ");
Serial.println(detectCount);
}
delay(10);
}
int config_free_fall_detect(void) {
uint8_t error = 0;
uint8_t dataToWrite = 0;
dataToWrite |= LSM6DS3_ACC_GYRO_BW_XL_200Hz;
dataToWrite |= LSM6DS3_ACC_GYRO_FS_XL_2g;
dataToWrite |= LSM6DS3_ACC_GYRO_ODR_XL_416Hz;
error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_CTRL1_XL, dataToWrite);
error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_WAKE_UP_DUR, 0x00);
error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_FREE_FALL, 0x33);
error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, 0x10);
error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_MD2_CFG, 0x10);
error += lsm6ds3.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x01);
return error;
}
So Hi there,
I see you have been asking over on Arduino. That volatile discussion is important but NOT pertinent to this Code. BTW. You missed ONE major detail.
Here is the output and a small clip of it in action.
Device OK!
Success to Configure!
Free fall detected! 1
Free fall detected! 2
Free fall detected! 3
Free fall detected! 4
Free fall detected! 5
Free fall detected! 6
Free fall detected! 7
Free fall detected! 8
Free fall detected! 9
Free fall detected! 10
Section Interrupt generation and Section 5.2 more specifically. About the Zone, the free fall zone consist of the time duration and threshold, you asked what do you write there, well based on the scales you choose you can adjust the levels and duration of ““Zero G”” closest to Zero on all axis = Free Fall
You didn’t notice in my Double tap code I , enable the interrupt for the 2 Tap writing an 0x81
Section 5.2 in the fine print
The basic interrupts (6D/4D, free-fall, wake-up, tap, inactivity) have to be enabled by setting the
INTERRUPTS_ENABLE bit in the TAP_CFG register.
Changing your 0x01 to 0x81 and Wha-la… Interrupt generation.
1. Write 60h to CTRL1_XL // Turn on the accelerometer
// ODR_XL = 416 Hz, FS_XL = ±2 g
2. Write 81h to TAP_CFG // Enable interrupts and latch interrupt
3. Write 00h to WAKE_UP_DUR // Set event duration (FF_DUR5 bit)
4. Write 33h to FREE_FALL // Set FF threshold (FF_THS[2:0] = 011b)
// Set six samples event duration (FF_DUR[5:0] = 000110b)
5. Write 10h to MD1_CFG // FF interrupt driven to INT1 pin
The sample code exploits a threshold set to 312 mg for free-fall recognition and the event is notified by hardware
through the INT1 pin. The FF_DUR[5:0] field of the FREE_FALL / WAKE_UP_DUR registers is configured like this
to ignore events that are shorter than 6/ODR_XL = 6/412 Hz ~= 15 msec in order to avoid false detections.
Oh that looks awesome.
So I understand I forgot to set the highest bit (the one for the timestamp)?
But why is that important for the interrupt?
I mean it looks like this fixes things but I really have no clue on how I should have known that. To be honest, the documentation was a bit too short for my taste.
The document you found looks better actually. Gonna read through it so I hope I don’t have to ask more noob questions in the future.
In any case thank you very much for your help. I will need some time to understand all this but I guess that will help a lot!
Sure, no problem . You didn’t enable the Interrupt is all. the 01 sets it to latch and the 80 enables them. add them together “81” and it works as it should. read the AppNote you’ll get it all in there. I’ll post another demo with it all together with the DEV Expansion board.
HTH
GL PJ
But why is that flag “enable them”?
The documentation reads:
TIMER_EN : Timestamp count enable, output data are collected in TIMESTAMP0_REG (40h),
TIMESTAMP1_REG (41h), TIMESTAMP2_REG (42h) register. Default: 0
(0: timestamp count disabled; 1: timestamp count enabled)
So I understood it is something like “I know the exact tick when it happened”. Where did you see this enables / disables them globally? I guess I still don’t understand some things perfectly. Even though, the document you provided helped a lot. Took me some hours but I finally understand some things. Thanks a lot!
And there is still something I don’t understand.
Since you are helping me so much, perhaps you might tell me more.
In my interrupt code I receive the interrupt exactly once. So I assume I have to (re)set things again after the interrupt was fired.
Where can I get that information from? Which values have to be set again and which persist?
LOL, did you read the whole thing? tiny print too…
OK Anyway Depending on several things, How you program the PIN_MODE for the interrupt pin is one.
Then how you program the chip to act with the Interrupt pin internally.
the above uses the Latching" feature of the pin. ie. interrupt is asserted until you READ the WAKE_UP_SRC register. You can change that mode to only interrupt on a Free_Fall and release Interrupt after it’s within threshold.
this is less desirable for my application btw .
READ the app_note
Look over the Code in the New thread…here.XIAO nRF52840 Sense Free-Falls , Sleep & Double Tap Wake Up Demo
Hey there,
no, I did not read EVERYTHING. There were some chapters I didn’t want to go into depth since this would lead to even more questions.
But these interrupts and free-fall/tap/movement detection chapters etc. were pretty interesting.
So do I understand you right, the interrupt is “blocked” until I read from the register?
I guess I understand now. So once I’m done with my logic, I have to call
This then “resets” everything and I can receive another one.
Nice! Again I have no idea where that was written but I’m happy you pointed me to what I was missing.
Sorry for all these beginner questions. I’m still studying this. I hope in a few semesters I might get a better understanding of all this - and help others like you did.