Arduino Accelerometer Continuous but with magnitude values

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);
    }
}

}

float ei_get_sign(float number) {
return (number >= 0.0) ? 1.0 : -1.0;
}

the output that i received is IMU Initialized and nothing else. perhaps there is a way to make it work? if so, i seek your help.

best regards,

Hello @SaphiraN,

You are overwritting your buffer with a single value.

Also, you need to fill a buffer with each values of your input axis.

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).

Best,

Louis

1 Like

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
image

perhaps i did it improperly. what do you suggest i do?

cheers,

Hello @SaphiraN,

Assuming you retrained your model with only magnitude data, you need to add the following part after your function run_classifier

// 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);
        }

Best,

Louis