Skip to content

Instantly share code, notes, and snippets.

@ShawnHymel
Created October 10, 2022 19:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ShawnHymel/2b27c298cad725cd5a5ea1909216a21e to your computer and use it in GitHub Desktop.
Save ShawnHymel/2b27c298cad725cd5a5ea1909216a21e to your computer and use it in GitHub Desktop.
Edge Impulse magic wand inference example
/**
* 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