Eloquent Edge Impulse for Arduino
An Arduino library to make Edge Impulse neural networks more accessible and easy to use

Edge Impulse is a great tool to develop TinyML models without coding and in a simple to use environment.
Sadly, integrating those models back into your Arduino project is not that easy as it could be.
Thanks to the Eloquent Arduino library, though, things have changed!

How to use
Using the Eloquent library to run Edge Impulse models is pretty easy.
First of all, create your model and export as an Arduino library.

Now, create a new Arduino sketch with the following code.
/**
* This example shows how to use the Eloquent library
* to perform inference using the EdgeImpulse generated library
*/
#include <replace_with_edge_impulse_inferencing.h>
#include <eloquent.h>
#include <eloquent/tinyml/edgeimpulse.h>
Eloquent::TinyML::EdgeImpulse::Impulse impulse;
void setup() {
Serial.begin(115200);
delay(3000);
Serial.println("Starting EdgeImpulse inference");
Serial.println("Paste your feature vector in the Serial Monitor and get the predicted value");
Serial.print("(expecting ");
Serial.print(EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE);
Serial.println(" comma-separated features)");
}
void loop() {
float features[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = {0};
if (!Serial.available())
return;
for (int i = 0; i < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; i++)
features[i] = Serial.readStringUntil(',').toFloat();
// here is where the magic happens...
Serial.print("Predicted class: ");
Serial.println(impulse.predict(features));
Serial.print("Predicted label: ");
Serial.println(impulse.getLabel());
// debug class probabilities and timing
impulse.printTo(Serial);
}
Hopefully the code is self-explanatory:
- it loads the library you exported from Edge Impulse
- it loads the Eloquent Edge Impulse library
- it instantiates an
impulse
object

When the user sends a feature vector to the Serial Monitor, the impulse performs the inference and prints the results back to the Serial Monitor.
Done!
Looks pretty clean, right?
Compare with the example generated from Edge Impulse.
/**
* @brief Arduino main function
*/
void loop()
{
ei_printf("Edge Impulse standalone inferencing (Arduino)\n");
if (sizeof(features) / sizeof(float) != EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE) {
ei_printf("The size of your 'features' array is not correct. Expected %lu items, but had %lu\n",
EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, sizeof(features) / sizeof(float));
delay(1000);
return;
}
ei_impulse_result_t result = { 0 };
// the features are stored into flash, and we don't want to load everything into RAM
signal_t features_signal;
features_signal.total_length = sizeof(features) / sizeof(features[0]);
features_signal.get_data = &raw_feature_get_data;
// invoke the impulse
EI_IMPULSE_ERROR res = run_classifier(&features_signal, &result, false /* debug */);
ei_printf("run_classifier returned: %d\n", res);
if (res != 0) return;
// print the predictions
ei_printf("Predictions ");
ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
ei_printf(": \n");
ei_printf("[");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf("%.5f", result.classification[ix].value);
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(", ");
#else
if (ix != EI_CLASSIFIER_LABEL_COUNT - 1) {
ei_printf(", ");
}
#endif
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf("%.3f", result.anomaly);
#endif
ei_printf("]\n");
// human-readable predictions
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label, result.classification[ix].value);
}
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf(" anomaly score: %.3f\n", result.anomaly);
#endif
delay(1000);
}
I think we have a clear winner here.
Available methods
Here's the complete list of the methods that you can call on the impulse
object.
int8_t predict(float *features)
Perform inference on the given feature vector. Returns the most probable class index, or -1 on error.
String predictLabel(float *features)
Perform inference on the given feature vector. Returns the most probable class name.
String getLabel(void)
Get label of latest prediction.
float getProba(void)
Get probability of latest prediction.
uint16_t getDspTiming(void)
Get time spent on DSP, in milliseconds.
uint16_t getClassificationTiming(void)
Get time spent on classification, in milliseconds.
uint16_t getAnomalyTiming(void)
Get time spent on anomaly detection, in milliseconds, if anomaly detection was turned on during model generation.
bool isAnomaly(void)
Return true when an anomaly is detected, if anomaly detection was turned on during model generation.
void setMaxAnomalyScore(float maxScore)
Set the max score after which a prediction is considered an anomaly.
void printTo(PrinterInterface &printer)
Print debug information to given printer template class. Many times you will pass the Serial object.
Having troubles? Ask a question
Related posts
tinyml
Separable Conv2D kernels: a benchmark
An introduction to Machine Learning development for Arduino
tinyml
Attiny Machine Learning
Can an Attiny85 really run Machine Learning? Let's find out in this article!
tinyml
Get started with Arduino Machine Learning
A ready to use layout project to get up and running quickly with your next TinyML project
tinyml
Color classification with TinyML
Get familiar with data collection and pre-processing for Machine Learning tasks
libraries
EloquentTinyML for Arduino
An Arduino library to make TensorFlow Lite for Microcontrollers neural networks more accessible and easy to use