This is IMU Interrupt Example for XIAO BLE Sense on the Dev board.
It displays the interrupt count and Sleep.
This example shows how to configure LMSD6S3TR-C on XIAO BLE SENSE to interrupt on INT1 after a Free Fall event after 3 Free Falls it sleeps and “Double Tap” INT2 wakes it up again.
/*****************************************************************************/
// 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 Free Fall event after 3 Free Falls it sleeps and "Double Tap" INT2 wakes it up again.
//
//poatched and toasted by pjg
/*******************************************************************************/
#include "LSM6DS3.h"
#include "Wire.h"
#include <U8x8lib.h>
LSM6DS3 myIMU(I2C_MODE, 0x6A); // IMU
#define int2Pin 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
uint16_t detectCount = 0;
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 'FREE FALL DEMO' compiled on "__DATE__ " at " __TIME__);
//setupDoubleTapInterrupt();
setupFreeFallInterrupt();
pinMode(int2Pin, INPUT);
attachInterrupt(digitalPinToInterrupt(int2Pin), int1ISR, RISING);
u8x8.setFont(u8x8_font_8x13B_1x2_r);
u8x8.clearDisplay();
u8x8.setCursor(0, 0);
u8x8.print("Free Fall Demo");
Serial.print("\Iterrupt Counter: ");
Serial.println(interruptCount);
}
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);
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;
if (readDataByte) {
detectCount ++;
Serial.print("Free fall detected! ");
Serial.println(detectCount);
}
delay(10);
// 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(int2Pin), NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_SENSE_HIGH);
delay(2000); // Required delay
// Trigger System OFF
NRF_POWER->SYSTEMOFF = 1;
}
// -------------------- Interrupts ------------------------- //
void setupFreeFallInterrupt() {
uint8_t errorAccumulator = 0;
uint8_t dataToWrite = 0; //Temporary variable
//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, 0x60 );
//errorAccumulator += myIMU.readRegister(&dataToWrite, LSM6DS3_ACC_GYRO_CTRL4_C);
//errorAccumulator += myIMU.writeRegister( LSM6DS3_ACC_GYRO_CTRL4_C, 0x10 );
// 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, 0x81);
if( errorAccumulator )
{
Serial.println("Problem configuring the device.");
}
else
{
Serial.println("Device O.K.");
}
}
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); }
}
Using library Seeed Arduino LSM6DS3 at version 2.0.3 in folder: D:\Arduino_projects\libraries\Seeed_Arduino_LSM6DS3
Using library Wire in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\mbed\2.9.0\libraries\Wire (legacy)
Using library U8g2 at version 2.34.22 in folder: D:\Arduino_projects\libraries\U8g2
Using library SPI in folder: C:\Users\Dude\AppData\Local\Arduino15\packages\Seeeduino\hardware\mbed\2.9.0\libraries\SPI (legacy)
"C:\\Users\\Dude\\AppData\\Local\\Arduino15\\packages\\Seeeduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-size" -A "C:\\Users\\Dude\\AppData\\Local\\Temp\\arduino\\sketches\\8253AD941CB66F96DBB83652EDEB1561/Free_fal_demo_copy_20230829210527.ino.elf"
Sketch uses 101376 bytes (12%) of program storage space. Maximum is 811008 bytes.
Global variables use 46072 bytes (19%) of dynamic memory, leaving 191496 bytes for local variables. Maximum is 237568 bytes.
HTH
GL PJ
It is possible to do Motion detection (movement) and Impact (drop detection) with Free-Fall all at the same time. Very cool.