Created
October 10, 2022 19:38
-
-
Save ShawnHymel/2b27c298cad725cd5a5ea1909216a21e to your computer and use it in GitHub Desktop.
Edge Impulse magic wand inference example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Magic Wand Inference Demo | |
* | |
* Attach a button to pin 2. Press button to start collection. Raw data will be | |
* collected and fed to the impulse for inference. Inference results are printed | |
* to the serial terminal. | |
* | |
* Author: Shawn Hymel (EdgeImpulse, Inc.) | |
* Date: October 10, 2022 | |
* License: Apache-2.0 (apache.org/licenses/LICENSE-2.0) | |
*/ | |
#include <my-magic-wand-standardized_inferencing.h> | |
#include <Arduino_LSM9DS1.h> | |
// Settings | |
#define BTN_PIN 2 // Button pin | |
#define LED_R_PIN 22 // Red LED pin | |
#define THRESHOLD 0.8 // Threshold for performing action | |
// Constants | |
#define CONVERT_G_TO_MS2 9.80665f // Used to convert G to m/s^2 | |
#define SAMPLING_FREQ_HZ 100 // Sampling frequency (Hz) | |
#define SAMPLING_PERIOD_MS 1000 / SAMPLING_FREQ_HZ // Sampling period (ms) | |
#define NUM_CHANNELS EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME // 6 channels | |
#define NUM_READINGS EI_CLASSIFIER_RAW_SAMPLE_COUNT // 100 readings | |
#define NUM_CLASSES EI_CLASSIFIER_LABEL_COUNT // 4 classes | |
// Means and standard deviations from our dataset curation | |
static const float means[] = {0.4686, -0.4075, 8.3669, 0.0717, 4.7533, -9.9816}; | |
static const float std_devs[] = {2.9989, 7.0776, 6.8269, 60.9333, 101.3666, 109.0392}; | |
void setup() { | |
// Enable button pin | |
pinMode(BTN_PIN, INPUT_PULLUP); | |
// Enable LED pin (RGB LEDs are active low on the Nano 33 BLE) | |
pinMode(LED_R_PIN, OUTPUT); | |
digitalWrite(LED_R_PIN, HIGH); | |
// Start serial | |
Serial.begin(115200); | |
// Start accelerometer (part of IMU) | |
if (!IMU.begin()) { | |
Serial.println("Failed to initialize IMU!"); | |
while (1); | |
} | |
} | |
void loop() { | |
float acc_x, acc_y, acc_z, gyr_x, gyr_y, gyr_z; | |
unsigned long timestamp; | |
ei_impulse_result_t result; | |
int err; | |
float input_buf[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE]; | |
signal_t signal; | |
// Wait for button press | |
while (digitalRead(BTN_PIN) == 1); | |
// Turn on LED to show we're recording | |
digitalWrite(LED_R_PIN, LOW); | |
// Record samples in buffer | |
for (int i = 0; i < NUM_READINGS; i++) { | |
// Take timestamp so we can hit our target frequency | |
timestamp = millis(); | |
// Get raw readings from the accelerometer and gyroscope | |
IMU.readAcceleration(acc_x, acc_y, acc_z); | |
IMU.readGyroscope(gyr_x, gyr_y, gyr_z); | |
// Convert accelerometer units from G to m/s^s | |
acc_x *= CONVERT_G_TO_MS2; | |
acc_y *= CONVERT_G_TO_MS2; | |
acc_z *= CONVERT_G_TO_MS2; | |
// Perform standardization on each reading | |
// Use the values from means[] and std_devs[] | |
acc_x = (acc_x - means[0]) / std_devs[0]; | |
acc_y = (acc_y - means[1]) / std_devs[1]; | |
acc_z = (acc_z - means[2]) / std_devs[2]; | |
gyr_x = (gyr_x - means[3]) / std_devs[3]; | |
gyr_y = (gyr_y - means[4]) / std_devs[4]; | |
gyr_z = (gyr_z - means[5]) / std_devs[5]; | |
// Fill input_buf with the standardized readings. Recall tha the order | |
// is [acc_x0, acc_y0, acc_z0, gyr_x0, gyr_y0, gyr_z0, acc_x1, ...] | |
input_buf[(NUM_CHANNELS * i) + 0] = acc_x; | |
input_buf[(NUM_CHANNELS * i) + 1] = acc_y; | |
input_buf[(NUM_CHANNELS * i) + 2] = acc_z; | |
input_buf[(NUM_CHANNELS * i) + 3] = gyr_x; | |
input_buf[(NUM_CHANNELS * i) + 4] = gyr_y; | |
input_buf[(NUM_CHANNELS * i) + 5] = gyr_z; | |
// Wait just long enough for our sampling period | |
while (millis() < timestamp + SAMPLING_PERIOD_MS); | |
} | |
// Turn off LED to show we're done recording | |
digitalWrite(LED_R_PIN, HIGH); | |
// Turn the raw buffer into a signal for inference | |
err = numpy::signal_from_buffer(input_buf, | |
EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, | |
&signal); | |
if (err != 0) { | |
Serial.print("ERROR: Failed to create signal from buffer: "); | |
Serial.println(err); | |
return; | |
} | |
// Run the impulse | |
err = run_classifier(&signal, &result, false); | |
if (err != 0) { | |
Serial.print("ERROR: Failed to run classifier: "); | |
Serial.println(err); | |
return; | |
} | |
// Print the results | |
Serial.println("Predictions"); | |
for (int i = 0; i < EI_CLASSIFIER_LABEL_COUNT; i++) { | |
Serial.print(" "); | |
Serial.print(result.classification[i].label); | |
Serial.print(": "); | |
Serial.println(result.classification[i].value); | |
} | |
// Make sure the button has been released for a few milliseconds | |
while (digitalRead(BTN_PIN) == 0); | |
delay(100); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment