Hi, I'm working on this project: fall detection for the elderly. The basic concept is that when an elderly person falls, the watch detects the fall and sends a message to the caretaker. This part focuses on fall detection. The attached code is the code for fall detection. I can't simulate the fall scenario with this logic. Please advise on the logic written. thank you.
#include <Wire.h> // I2C communication
#include "BMA250.h" // Accelerometer library
#include <TinyScreen.h> // TinyScreen library
// Accelerometer variables
BMA250 accel_sensor;
int x, y, z;
float accelMagnitude;
// Fall detection thresholds
float impactThreshold = 2.5;
float freeFallThreshold = 0.5;
float recoveryThreshold = 1.0;
unsigned long recoveryDelay = 1000;
// Fall detection states
enum FallState { IDLE, IMPACT_DETECTED, FREE_FALL_DETECTED };
FallState fallState = IDLE;
unsigned long impactTime = 0;
unsigned long freeFallTime = 0;
// Setup Serial for different boards
#if defined(ARDUINO_ARCH_SAMD)
TinyScreen display = TinyScreen(TinyScreenDefault);
#define SerialMonitorInterface SerialUSB
#else
TinyScreen display = TinyScreen(TinyScreenDefault);
#define SerialMonitorInterface Serial
#endif
const FONT_INFO& font10pt = thinPixel7_10ptFontInfo;
void setup() {
SerialMonitorInterface.begin(115200);
Wire.begin();
SerialMonitorInterface.println("Initializing BMA250...");
accel_sensor.begin(BMA250_range_2g, BMA250_update_time_64ms);
// Initialize TinyScreen
display.begin();
display.setBrightness(15); // Adjust brightness (0-15)
display.setFlip(true); // Adjust orientation if necessary
display.clearScreen();
}
void loop() {
accel_sensor.read(); // Read accelerometer data
x = accel_sensor.X;
y = accel_sensor.Y;
z = accel_sensor.Z;
if (x == -1 && y == -1 && z == -1) {
SerialMonitorInterface.println("ERROR: Invalid data.");
return;
}
accelMagnitude = sqrt(sq(x) + sq(y) + sq(z)); // Calculate magnitude
switch (fallState) {
case IDLE:
if (accelMagnitude > impactThreshold) {
SerialMonitorInterface.println("Impact detected!");
impactTime = millis();
fallState = IMPACT_DETECTED;
}
break;
case IMPACT_DETECTED:
if (accelMagnitude < freeFallThreshold) {
SerialMonitorInterface.println("Free fall detected!");
freeFallTime = millis();
fallState = FREE_FALL_DETECTED;
} else if (millis() - impactTime > recoveryDelay) {
SerialMonitorInterface.println("False alarm, resetting to IDLE.");
fallState = IDLE;
}
break;
case FREE_FALL_DETECTED:
if (accelMagnitude < recoveryThreshold && (millis() - freeFallTime) > 500) {
SerialMonitorInterface.println("Fall confirmed!");
displayFallDetected(); // Show message on TinyScreen
fallState = IDLE;
} else if (millis() - freeFallTime > recoveryDelay) {
SerialMonitorInterface.println("False alarm, resetting to IDLE.");
fallState = IDLE;
}
break;
}
showSerial(); // Debugging output
delay(250); // Adjust delay as necessary
}
void displayFallDetected() {
display.clearScreen();
display.setFont(font10pt); // Choose a suitable font
display.setCursor(10, 20); // Set position (x, y)
display.print("Fall Detected!"); // Refresh the screen to show the message
}
void showSerial() {
SerialMonitorInterface.print("X = ");
SerialMonitorInterface.print(x);
SerialMonitorInterface.print(" Y = ");
SerialMonitorInterface.print(y);
SerialMonitorInterface.print(" Z = ");
SerialMonitorInterface.print(z);
SerialMonitorInterface.print(" Accel Magnitude = ");
SerialMonitorInterface.println(accelMagnitude);
}
Background information:
BMA250: TinyCircuits-BMA250-library
I'm using TinyZero Processor Board
TinyScreen TinyShield for display
#include <Wire.h> // I2C communication
#include "BMA250.h" // Accelerometer library
#include <TinyScreen.h> // TinyScreen library
// Accelerometer variables
BMA250 accel_sensor;
int x, y, z;
float accelMagnitude;
// Fall detection thresholds
float impactThreshold = 2.5;
float freeFallThreshold = 0.5;
float recoveryThreshold = 1.0;
unsigned long recoveryDelay = 1000;
// Fall detection states
enum FallState { IDLE, IMPACT_DETECTED, FREE_FALL_DETECTED };
FallState fallState = IDLE;
unsigned long impactTime = 0;
unsigned long freeFallTime = 0;
// Setup Serial for different boards
#if defined(ARDUINO_ARCH_SAMD)
TinyScreen display = TinyScreen(TinyScreenDefault);
#define SerialMonitorInterface SerialUSB
#else
TinyScreen display = TinyScreen(TinyScreenDefault);
#define SerialMonitorInterface Serial
#endif
const FONT_INFO& font10pt = thinPixel7_10ptFontInfo;
void setup() {
SerialMonitorInterface.begin(115200);
Wire.begin();
SerialMonitorInterface.println("Initializing BMA250...");
accel_sensor.begin(BMA250_range_2g, BMA250_update_time_64ms);
// Initialize TinyScreen
display.begin();
display.setBrightness(15); // Adjust brightness (0-15)
display.setFlip(true); // Adjust orientation if necessary
display.clearScreen();
}
void loop() {
// Read accelerometer data
accel_sensor.read();
x = accel_sensor.X;
y = accel_sensor.Y;
z = accel_sensor.Z;
// Handle invalid data
if (x == -1 && y == -1 && z == -1) {
SerialMonitorInterface.println("ERROR: Invalid data.");
return;
}
// Calculate acceleration magnitude
accelMagnitude = sqrt(sq(x) + sq(y) + sq(z)) / 256.0; // Normalize to g
// Log the current readings
showSerial();
// Directly test the acceleration magnitude
if (accelMagnitude > impactThreshold) {
SerialMonitorInterface.println("Impact detected!");
} else if (accelMagnitude < freeFallThreshold) {
SerialMonitorInterface.println("Free fall detected!");
displayFallDetected();
} else if (accelMagnitude < recoveryThreshold) {
SerialMonitorInterface.println("Recovering...");
} else {
SerialMonitorInterface.println("No fall detected.");
}
delay(250); // Delay to manage loop speed
}
void displayFallDetected() {
display.clearScreen();
display.setFont(font10pt); // Choose a suitable font
display.setCursor(10, 20); // Set position (x, y)
display.print("Fall Detected!"); // Refresh the screen to show the message
}
void showSerial() {
SerialMonitorInterface.print("X = ");
SerialMonitorInterface.print(x);
SerialMonitorInterface.print(" Y = ");
SerialMonitorInterface.print(y);
SerialMonitorInterface.print(" Z = ");
SerialMonitorInterface.print(z);
SerialMonitorInterface.print(" Accel Magnitude = ");
SerialMonitorInterface.println(accelMagnitude);
}
is this ok? I'm still confused how to set the Fall detection thresholds. when boards is on the table, it reads recovering. if you shake the the board it displays free detected. please advice on this. thank you.
impactThreshold (2.5g): Detects a sudden impact or shock.
freeFallThreshold (0.5g): Detects free fall with minimal acceleration.
recoveryThreshold (1.0g): Ensures the device is stable after a fall.
#include <Wire.h> // I2C communication
#include "BMA250.h" // Accelerometer library
#include <TinyScreen.h> // TinyScreen library
// Accelerometer variables
BMA250 accel_sensor;
int x, y, z;
float accelMagnitude;
// Fall detection thresholds
float impactThreshold = 2.5;
float freeFallThreshold = 0.5;
float recoveryThreshold = 1.0;
// Flag to halt accelerometer reading after fall
bool fallDetected = false;
// Setup Serial for different boards
#if defined(ARDUINO_ARCH_SAMD)
TinyScreen display = TinyScreen(TinyScreenDefault);
#define SerialMonitorInterface SerialUSB
#else
TinyScreen display = TinyScreen(TinyScreenDefault);
#define SerialMonitorInterface Serial
#endif
const FONT_INFO& font10pt = thinPixel7_10ptFontInfo;
void displayFallDetected();
void showSerial();
void setup() {
SerialMonitorInterface.begin(115200);
Wire.begin();
SerialMonitorInterface.println("Initializing BMA250...");
accel_sensor.begin(BMA250_range_2g, BMA250_update_time_64ms);
// Initialize TinyScreen
display.begin();
display.setBrightness(15); // Adjust brightness (0-15)
display.setFlip(true); // Adjust orientation if necessary
display.clearScreen();
}
void loop() {
if (fallDetected) {
SerialMonitorInterface.println("Fall detected! Stopping accelerometer.");
displayFallDetected();
// Check for user response
if (display.getButtons(TSButtonLowerLeft)) { // Yes (help required)
SerialMonitorInterface.println("Yes, need help!");
display.clearScreen();
display.setFont(font10pt);
display.setCursor(10, 10);
display.print("Sending Help...");
}
if (display.getButtons(TSButtonLowerRight)) { // No (cancel)
SerialMonitorInterface.println("No help needed.");
display.clearScreen();
display.setFont(font10pt);
display.setCursor(10, 10);
display.print("Help Canceled.");
fallDetected = false;
display.clearScreen();
return;
}
delay(10000); // Wait for 10 seconds
// Restart accelerometer after timeout
SerialMonitorInterface.println("Restarting accelerometer...");
accel_sensor.begin(BMA250_range_2g, BMA250_update_time_64ms);
fallDetected = false;
display.clearScreen();
return;
}
// Read accelerometer data
accel_sensor.read();
x = accel_sensor.X;
y = accel_sensor.Y;
z = accel_sensor.Z;
// Handle invalid data
if (x == -1 && y == -1 && z == -1) {
SerialMonitorInterface.println("ERROR: Invalid data.");
return;
}
// Calculate acceleration magnitude
accelMagnitude = sqrt(sq(x) + sq(y) + sq(z)) / 256.0;
// Display readings
showSerial();
// Check thresholds for fall detection
if (accelMagnitude > impactThreshold) {
SerialMonitorInterface.println("Impact detected!");
fallDetected = true;
} else if (accelMagnitude < freeFallThreshold) {
SerialMonitorInterface.println("Free fall detected!");
fallDetected = true;
} else if (accelMagnitude < recoveryThreshold) {
SerialMonitorInterface.println("Recovering...");
} else {
SerialMonitorInterface.println("No fall detected.");
}
delay(250); // Delay to manage loop speed
}
void displayFallDetected() {
display.clearScreen();
display.setFont(font10pt);
display.setCursor(10, 10);
display.print("Fall Detected!");
display.setCursor(10, 20);
display.print("Do you need help?");
display.setCursor(0, 45);
display.print("-> Yes");
display.setCursor(70, 45);
display.print("No <-");
}
void showSerial() {
SerialMonitorInterface.print("X = ");
SerialMonitorInterface.print(x);
SerialMonitorInterface.print(" Y = ");
SerialMonitorInterface.print(y);
SerialMonitorInterface.print(" Z = ");
SerialMonitorInterface.print(z);
SerialMonitorInterface.print(" Accel Magnitude = ");
SerialMonitorInterface.println(accelMagnitude);
}
this code currently detects fall and then displays "Fall Detected! Do you need help? Yes No". if we click yes it displays "Sending help" if no, goes back to normal. problem now is when I cleck the button, it doesn't read the input. no reaction when the button is pressed. i have set timer to 10s, after it goes back to normal. Please advice on this. thank you.
yes, it is a project. i got a base code for accelerometer from tinycircuits. From there, i developed this using chatgpt. this is my first time doing this.
Take a step back and read and understand the datasheet and see if you can write yourself code to use the built in capabilities to detect free fall or a shock
Have you studied how running and walking also fit those parameters? Or sitting down on a hard chair or bench? Or setting down on the toilet? Or falling into bed?
Will your code be able to differentiate a damaging fall from a rolling fall?
You can’t shortcut with AI and copied code - you need to know something of it , otherwise you are wasting your time and likely to give up .
If you know nothing , this is too complex as a start project .
There are few shortcuts in life …
If this a school, then what have you been taught this far ??