Question/Issue: i made a model for fall detection using triaxial acceleration converted into magnitude values, but havent been able to get the model to do inferencing. is there a way to allow the model to be able to infer with magnitude values?
Project ID: 156826
Context/Use case: with the example code, i disabled
if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3){
ei_printf(“ERR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME should be equal to 3 (the 3 sensor axes)\n”);
return;
}
in void setup().
after that, i modified void run_inference_background() and void loop() into:
void loop() {
while (1) {
delay(run_inference_every_ms);
float x, y, z;
if (IMU.accelerationAvailable()){
IMU.readAcceleration(x, y, z);
Serial.print("X: ");
Serial.print(x);
Serial.print(" g, Y: ");
Serial.print(y);
Serial.print(" g, Z: ");
Serial.print(z);
Serial.print(" g ");
// Calculate magnitude of acceleration
float magnitude = sqrt(x * x + y * y + z * z) * CONVERT_G_TO_MS2;
// Print the calculated magnitude
Serial.print("Magnitude: ");
Serial.print(magnitude);
Serial.println(" m/s^2");
// Limit the magnitude to the max accepted range
if (fabs(magnitude) > MAX_ACCEPTED_RANGE) {
magnitude = ei_get_sign(magnitude) * MAX_ACCEPTED_RANGE;
}
// Put the magnitude into the buffer for the classifier
buffer[0] = magnitude; // Assuming the classifier is expecting a single input value per inference
// Turn the raw buffer in a signal which we can then classify
signal_t signal;
int err = numpy::signal_from_buffer(buffer, 1, &signal); // Adjust the second parameter according to your buffer size
if (err != 0) {
ei_printf("Failed to create signal from buffer (%d)\n", err);
continue;
}
// Run the classifier
ei_impulse_result_t result = { 0 };
err = run_classifier(&signal, &result, false);
if (err != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", err);
continue;
}
// Output the results
ei_printf("Result: %f\n", result.classification[0].value);
}
}
In your case the window size is 3000ms sampled at 50Hz (thus 600 values per single axis).
I assume, you want to train your impulse with the m axis instead of x, y, z correct?
And as per your arduino code, you can use the arduino example for the IMU as a template and modify it:
void loop()
{
ei_printf("\nStarting inferencing in 2 seconds...\n");
delay(2000);
ei_printf("Sampling...\n");
// Allocate a buffer here for the values we'll read from the IMU
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix += 1) {
// Determine the next tick (and then sleep later)
uint64_t next_tick = micros() + (EI_CLASSIFIER_INTERVAL_MS * 1000);
IMU.readAcceleration(x, y, z);
// Calculate magnitude of acceleration
float magnitude = sqrt(x * x + y * y + z * z) * CONVERT_G_TO_MS2;
buffer[ix] *= magnitude;
delayMicroseconds(next_tick - micros());
}
// Turn the raw buffer in a signal which we can the classify
signal_t signal;
int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
if (err != 0) {
ei_printf("Failed to create signal from buffer (%d)\n", err);
return;
}
// Run the classifier
ei_impulse_result_t result = { 0 };
err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", err);
return;
}
Let me know if that works (I have not tested the code).
dearest louis, i thank you for your suggestion and have incorporated the code you have stated into mine to become:
void loop() {
while (1) {
delay(run_inference_every_ms);
float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
float x, y, z;
for (size_t ix = 0; ix < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; ix ++) {
// uint64_t next_tick = micros()+(EI_CLASSIFIER_INTERVAL_MS*1000);
IMU.readAcceleration(x, y, z);
Serial.print("X: ");
Serial.print(x);
Serial.print(" g Y: ");
Serial.print(y);
Serial.print(" g Z: ");
Serial.print(z);
Serial.print(" g ");
// Calculate magnitude of acceleration
float magnitude = sqrt(x * x + y * y + z * z) * CONVERT_G_TO_MS2;
// Print the calculated magnitude
Serial.print("M: ");
Serial.print(magnitude);
Serial.print(" m/s^2 ");
buffer[ix] *= magnitude;
// delayMicroseconds(next_tick - micros());
// // Limit the magnitude to the max accepted range
// if (fabs(magnitude) > MAX_ACCEPTED_RANGE) {
// magnitude = ei_get_sign(magnitude) * MAX_ACCEPTED_RANGE;
// }
// Turn the raw buffer in a signal which we can then classify
signal_t signal;
int err = numpy::signal_from_buffer(buffer, EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal); // Adjust the second parameter according to your buffer size
if (err != 0) {
ei_printf("Failed to create signal from buffer (%d)\n", err);
continue;
}
// Run the classifier
ei_impulse_result_t result = { 0 };
// Output the results
if (result.classification[ix].label == "fall") {
Serial.println("Fall");
digitalWrite(RED, LOW);
digitalWrite(GREEN, HIGH);
}
else {
Serial.println("");
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
}
err = run_classifier(&signal, &result, false);
if (err != EI_IMPULSE_OK) {
ei_printf("ERR: Failed to run classifier (%d)\n", err);
continue;
}
}
}
and saw the acceleration output from the serial monitor! However, i havent been able to receive the classifier’s result for whether or not it detected a fall. The line that said:
if (result.classification[ix].label == “fall”) {
Serial.println(“Fall”);
did not meet my expectation every time i simulated a fall or any high intensity activity. The following image shows what the serial monitor produced
perhaps i did it improperly. what do you suggest i do?