Hi Greglarious, Welcome…
That being said , Yea they are not 100% on working examples around here, It’s NOT really managed just kind of thrown on a wiki and rarely updated. The User’s here are EXCELLENT though. The support is responsive but not from an Engineering POV.
I managed to learn allot about the IMU here is the free fall template I tweaked and works VERY well with the Expansion Board, but also on the chip alone. (see Video)
here is the code and pics & bonus video if there’s no Cockpit issue’s/. You know Between the Keyboard and the floor
HTH
GL
/*
Here is an example code that you can use to detect a light impact using the LSM6DS3 IMU
and write the event information to the BLE characteristic value: , Check the comments for the values I've used successfully, You can WRITE them via the BLE connection and USE NRF connect to test.
(best $10 bucs I ever spent)
*/
//
#include <ArduinoBLE.h>
#include <Arduino.h>
#include <LSM6DS3.h>
#include <Wire.h>
#include <U8x8lib.h>
LSM6DS3 IMU(I2C_MODE, 0x6A); //I2C device address 0x6A // IMU
#define int2Pin PIN_LSM6DS3TR_C_INT1
float aX, aY, aZ, gX, gY, gZ;
String timeDateStamp = (" __TIME____DATE__" );
float ftemperature = 25.0;
bool imuParked = false;
bool droppedFlag = false;
bool motionAlarm = true;
String imuOrientation = "upright";
double tapToOpen = true;
int numberOfTaps = 3;
const int appearance = (0x19);
int orientation = -1; // use -1 to indicate initial state
const int orientationUpdateInterval = 1000; // update orientation every 5 seconds
unsigned long lastOrientationUpdate = 0;
// BLE Service and Characteristics
BLEService fallService("FDDA0001-7D3E-4988-B8E1-2E314F7A1D2A");
BLEStringCharacteristic fallCharacteristic("FDDA0002-7D3E-4988-B8E1-2E314F7A1D2A", BLERead | BLENotify, 20);
BLEFloatCharacteristic impactLevelCharacteristic("FDDA0003-7D3E-4988-B8E1-2E314F7A1D2A", BLERead | BLEWrite);
// Fall detection parameters
float impactThreshold = 1.5; // G-force threshold for impact (default value) HEX 20 40 =10G, 20 41 =2.5 G, 10 40= 2.25G,80 3F 1.0G,C0 3F = 1.5G
const int impactTime = 250; // Time (ms) to wait for impact
bool impactDetected = false;
unsigned long impactTimestamp;
unsigned long lastReadTimestamp = 0;
const int readInterval = 50; // Time interval (ms) to read acceleration data
//Create a instance of class
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
void setup() {
Serial.begin(9600);
delay(3000); //relax...Get Ready for serial port
Serial.println();
Serial.println("Power ON "); // Let's BEGIN!!
Serial.println("Test program compiled on " __DATE__ " at "__TIME__);
Serial.println();
IMU.begin();
initdisplay(); // Sets Font and clears screen.
if (!BLE.begin()) {
Serial.println("Starting BLE failed!");
while (1);
}
testimu(); //sets begin and reads Temps to verify alive
BLE.setLocalName("FallDetector");
BLE.setAdvertisedService(fallService);
fallService.addCharacteristic(fallCharacteristic);
fallService.addCharacteristic(impactLevelCharacteristic);
BLE.addService(fallService);
fallCharacteristic.writeValue("No Impact");
impactLevelCharacteristic.setValue(impactThreshold);
BLE.advertise();
Serial.println("BLE Fall Detector is ready");
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
impactDetected = false;
while (central.connected()) {
if (impactLevelCharacteristic.written()) {
float newThreshold = impactLevelCharacteristic.value();
if (newThreshold >= 0.5 && newThreshold <= 10.0) {
impactThreshold = newThreshold;
Serial.print("Updated impactThreshold to: ");
Serial.println(impactThreshold);
}
}
unsigned long currentMillis = millis();
if (currentMillis - lastReadTimestamp >= readInterval) {
lastReadTimestamp = currentMillis;
// read the acceleration data
aX = IMU.readFloatAccelX();
aY = IMU.readFloatAccelY();
aZ = IMU.readFloatAccelZ();
float magnitude = sqrt(aX * aX + aY * aY + aZ * aZ);
if (magnitude > impactThreshold && !impactDetected) {
impactDetected = true;
impactTimestamp = millis();
}
if (impactDetected && (millis() - impactTimestamp) > impactTime) {
impactDetected = false;
fallCharacteristic.writeValue("Impact Detected!");
setLedRGB(true, false, false); // Turn on RED LED
Serial.println("Impact Detected!");
u8x8.clearDisplay();
u8x8.setCursor(5, 0);
u8x8.print("Impact Detected!");
delay(1000);
fallCharacteristic.writeValue("No Impact");
setLedRGB(false, false, false); // Turn off any LED 's OFF
Serial.println("No Impact");
u8x8.clearDisplay();
u8x8.setCursor(5, 0);
u8x8.print("No Impact");
getOrientation();
}
}
}
Serial.print("Disconnected from central: ");
Serial.println(central.address());
getOrientation();
}
}
//end of main loop
bool checkForFall() {
bool impact = false;
unsigned long currentMillis = millis();
if (currentMillis - lastReadTimestamp >= readInterval) {
lastReadTimestamp = currentMillis;
float ax = IMU.readFloatAccelX();
float ay = IMU.readFloatAccelY();
float az = IMU.readFloatAccelZ();
float magnitude = sqrt(ax * ax + ay * ay + az * az);
if (magnitude > impactThreshold && !impactDetected) {
impactDetected = true;
impactTimestamp = millis();
}
if (impactDetected && (millis() - impactTimestamp) > impactTime) {
impactDetected = false;
impact = true;
}
}
return impact;
}
void getOrientation() {
// Check if it's time to update the orientation
if (millis() - lastOrientationUpdate >= orientationUpdateInterval) {
lastOrientationUpdate = millis();
// read the acceleration data
aX = IMU.readFloatAccelX();
aY = IMU.readFloatAccelY();
aZ = IMU.readFloatAccelZ();
// determine the orientation
int newOrientation;
if (abs(aX) > abs(aY) && abs(aX) > abs(aZ)) {
newOrientation = (aX > 0) ? 1 : 0;
} else if (abs(aY) > abs(aZ)) {
newOrientation = (aY > 0) ? 2 : 3;
} else {
newOrientation = (aZ > 0) ? 4 : 5;
}
// print the orientation if it changed
if (newOrientation != orientation) {
Serial.print("3D Position:-->");
u8x8.clearLine(0);
u8x8.setCursor(0, 0);
orientation = newOrientation;
switch (orientation) {
//Serial.println (orientation);
case 0:
Serial.println("UPRIGHT");
u8x8.print("UPRIGHT");
break;
case 1:
Serial.println("Ass UP ");
u8x8.print("Ass UP ");
break;
case 2:
Serial.println("SIDEWAYS LEFT");
u8x8.print("SIDEWAYS LEFT");
break;
case 3:
Serial.println("SIDEWAYS RIGHT");
u8x8.print("SIDEWAYS RIGHT");
break;
case 4:
Serial.println("TOP UP");
u8x8.print("TOP UP");
break;
case 5:
Serial.println("TOP DOWN");
u8x8.print("TOP DOWN");
break;
}
}
orientation = -1; // use -1 to indicate initial state
}
}
void initdisplay() {
pinMode(LEDR, OUTPUT); // initialize the LED pin as an output:
pinMode(LEDG, OUTPUT); // initialize the LED pin as an output:
pinMode(LEDB, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT); // initialize the LED pin as an output:
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
u8x8.setFont(u8x8_font_8x13B_1x2_r);
u8x8.clearDisplay();
u8x8.setCursor(0, 0);
u8x8.print("Power ON ");
}
void testimu() {
if (IMU.begin() != 0) { // Start IMU
Serial.println("Device error");
setLedRGB(false, true, false); // Red
} else {
Serial.println("IMU GOOD"); //Serial.println("aX,aY,aZ,gX,gY,gZ");
getOrientation();
// //Thermometer
Serial.print("Temperature: ");
Serial.print((String) + IMU.readTempF() + "\u00b0");
Serial.println();
}
}
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);
}
}
https://youtu.be/stL80Iezyk4