Any sensor combination to Edge Impulse

My original goal before finding Edge Impulse was to allow my students to train any sensor combination of data as a machine learning model to then control actuators. I was using Tensorflowjs and figured out how to convert tfjs models to c header files for loading on Arduinos. Can someone, probably @janjongboom give me an update on where Edge Impulse is on that kind of data input and output flexibility?

I am debating if I should re-look at my old methods or just wait for Edge Impulse to be able to do it.

Edge is MUCH easier and more flexible with the data than anything I made in the past.

My old link

For sensor fusion examples, check out Jan’s answers for audio + motion sensor fusion here: How to recogonize voice and motion in the same time?


Thanks @jenny The smoke detection example is really interesting and great that they included an example of their impulse here that new feature to share impulses is very useful. Well done @aurel. I looked at the github here but had a hard time finding the main ardiuno code.

I will probably just have to try my own using the arduino example in the data-forwarder Looks like you have lots of power once the data is on edge impulse and that is what I am interested in.

So this is what I loaded onto the Arduino Portenta

// for the Arduino Portenta

#define FREQUENCY_HZ        6
#define INTERVAL_MS         (1000 / (FREQUENCY_HZ + 1))

static unsigned long last_interval_ms = 0;

void setup() {
    pinMode(LEDB, OUTPUT);

void loop() {

    if (millis() > last_interval_ms + INTERVAL_MS) {
        digitalWrite(LEDB, !digitalRead(LEDB)); // flip internal LED
        last_interval_ms = millis();

        int   w = analogRead(A1);
        int   x = analogRead(A2);
        float y = analogRead(A3)/10.0;
        float z = analogRead(A4)/10.0;

        Serial.println(String(w) + ',' + String(x) + ',' + String(y,3) + ',' + String(z,3) );


And it seems to load fine. adding the rawData blocks when creating an impulse makes sense. Any opinions on the mixing of integers and floats?

Anyone know if the code can auto load. Just one set of labelled data say every 10 minutes?

Presently data acquisition needs to be started on the edge impulse side and goes for several seconds. Also any ability to self label? I just want to get the data onto edge impulse and then use the filters to correctly label things.

I guess my question is can the setup information be sent from the Arduino?

I wonder if I can format the Arduino output to be like the data upload json.

here is another possibly helpful link

Here is what I am trying to do. I guess it is a combination of the data uploader and the data forwarder. Here is my Arduino code

void setup() {
  // put your setup code here, to run once:


void loop() {


which of course does not work, because I am sending data uploader information to the data forwarder. Can anyone appreciated why this would be useful, fully formatted information directly from an Arduino live to Edge Impulse. Later today I will try to send the formatted Arduino information onto an SD card, but that skips the important “live” part. Theoretically, while fully automated data was being forwarded to Edge Impulse I could check the incoming data live. Can anyone think of a way to do that right now. Am I missing some vital part of the data forwarder?

Nothing like working code. This code works on the Portenta saving to an SD card and uploads using the uploader. It takes the analog value from A1, A2, A3, A4 and allows the data uploader to enter the labelled values onto Edge Impulse using the command

edge-impulse-uploader *.json
  Portenta - TestSDCARD

  The sketch shows how to mount an SDCARD and list its content.
  then add a file.

  Note: SD Card seems finisky, takes a few times to load the filesystem

  The circuit:
   - Portenta H7 + Vision Shield
   - Portenta H7 + Portenta Breakout

  This example code is in the public domain.
#include "SDMMCBlockDevice.h"
#include "FATFileSystem.h"

SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");
FILE *myFile;
char buffer[40];   // must be long enough for all data points with commas: 56,34,23,56

void setup() {
  while (!Serial);

  Serial.println("Mounting SDCARD...");
  int err =  fs.mount(&block_device);
  if (err) {
    // Reformat if we can't mount the filesystem
    // this should only happen on the first boot
    Serial.println("No filesystem found, please check on computer and manually format if needed.");
  //  err = fs.reformat(&block_device);  // seriously don't want to format your good data
  if (err) {
     Serial.println("Error formatting SDCARD ");
  DIR *dir;
  struct dirent *ent;
  int dirIndex = 0;

  Serial.println("List SDCARD content: ");
  if ((dir = opendir("/fs")) != NULL) {
    // Print all the files and directories within directory (not recursively)
    while ((ent = readdir (dir)) != NULL) {
    closedir (dir);
  } else {
    // Could not open directory
    Serial.println("Error opening SDCARD\n");
  if(dirIndex == 0) {
    Serial.println("Empty SDCARD");
 Serial.println("------------------------- Done --------------------------------"); 

void loop() {

  int myTime = millis()/1000; // seconds since the sketch began
  //char myFileName[] = "fs/folder1/00000000.json";  // works if folder1 pre-made
  char myFileName[] = "fs/00000000.json";   // fs/ needs to be there think fileSystem
  int myExtensionLength = 4;  // .txt = 3 .json = 4
  // does anyone understand why the  + '0' is needed below???
  myFileName[sizeof(myFileName)- myExtensionLength - 10] = myTime/10000000 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 9] = myTime/1000000 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 8] = myTime/100000 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 7] = myTime/10000 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 6] = myTime/1000 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 5] = myTime/100 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 4] = myTime/10 % 10 + '0';
  myFileName[sizeof(myFileName)- myExtensionLength - 3] = myTime % 10 + '0';
  // Can make a new file but can't make a new folder
  myFile = fopen(myFileName, "a");  // "a" for append or make it if file not there

  //  fprintf(myFile,"test \r\n");
    // now lets get the sensor values   
    char buffer1[7]; 
    itoa( analogRead(A1), buffer1, 10);
    char buffer2[7]; 
    itoa( analogRead(A2), buffer2, 10);
    char buffer3[7]; 
    itoa( analogRead(A3), buffer3, 10);
    char buffer4[7]; 
    itoa( analogRead(A4), buffer4, 10);

    char myComma[] = ",";
    memcpy (buffer, "", sizeof(buffer) );  // one way to delete the old buffer
    strcat(buffer, buffer1);
    strcat(buffer, myComma);
    strcat(buffer, buffer2);
    strcat(buffer, myComma);
    strcat(buffer, buffer3);
    strcat(buffer, myComma);
    strcat(buffer, buffer4);
    fprintf(myFile, buffer);



Not live using the forwarder but better than nothing.

1 Like

So I made an Arduino Portenta SD Card .JSON file making program for 4 analog sensors, while I was at it I also made a Portenta .CSV file making program for 4 analog sensors. See the code here

Note: The Portenta SD Card is finicky, I often hold it and restart the Portenta for it to do the main file check. Also it adds to files, so a file already there will be added to.

1 Like