#include #include #include #include #include #include #include //#include #include "model.h" const float accelerationThreshold = 2.5; // threshold of significant in G's const int numSamples = 119; int samplesRead = numSamples; LSM6DS3 myIMU(I2C_MODE, 0x6A); // global variables used for TensorFlow Lite (Micro) tflite::MicroErrorReporter tflErrorReporter; // pull in all the TFLM ops, you can remove this line and // only pull in the TFLM ops you need, if would like to reduce // the compiled size of the sketch. tflite::AllOpsResolver tflOpsResolver; const tflite::Model* tflModel = nullptr; tflite::MicroInterpreter* tflInterpreter = nullptr; TfLiteTensor* tflInputTensor = nullptr; TfLiteTensor* tflOutputTensor = nullptr; // Create a static memory buffer for TFLM, the size may need to // be adjusted based on the model you are using constexpr int tensorArenaSize = 8 * 1024; byte tensorArena[tensorArenaSize] __attribute__((aligned(16))); // array to map gesture index to a name const char* GESTURES[] = { "punch", "flex" }; #define NUM_GESTURES (sizeof(GESTURES) / sizeof(GESTURES[0])) void setup() { Serial.begin(9600); while (!Serial); if (myIMU.begin() != 0) { Serial.println("Device error"); } else { Serial.println("Device OK!"); } Serial.println(); // get the TFL representation of the model byte array tflModel = tflite::GetModel(model); if (tflModel->version() != TFLITE_SCHEMA_VERSION) { Serial.println("Model schema mismatch!"); while (1); } // Create an interpreter to run the model tflInterpreter = new tflite::MicroInterpreter(tflModel, tflOpsResolver, tensorArena, tensorArenaSize, &tflErrorReporter); // Allocate memory for the model's input and output tensors tflInterpreter->AllocateTensors(); // Get pointers for the model's input and output tensors tflInputTensor = tflInterpreter->input(0); tflOutputTensor = tflInterpreter->output(0); } void loop() { float aX, aY, aZ, gX, gY, gZ; // wait for significant motion while (samplesRead == numSamples) { // read the acceleration data aX = myIMU.readFloatAccelX(); aY = myIMU.readFloatAccelY(); aZ = myIMU.readFloatAccelZ(); // sum up the absolutes float aSum = fabs(aX) + fabs(aY) + fabs(aZ); // check if it's above the threshold if (aSum >= accelerationThreshold) { // reset the sample read count samplesRead = 0; break; } } // check if the all the required samples have been read since // the last time the significant motion was detected while (samplesRead < numSamples) { // check if new acceleration AND gyroscope data is available // read the acceleration and gyroscope data aX = myIMU.readFloatAccelX(); aY = myIMU.readFloatAccelY(); aZ = myIMU.readFloatAccelZ(); gX = myIMU.readFloatGyroX(); gY = myIMU.readFloatGyroY(); gZ = myIMU.readFloatGyroZ(); // normalize the IMU data between 0 to 1 and store in the model's // input tensor tflInputTensor->data.f[samplesRead * 6 + 0] = (aX + 4.0) / 8.0; tflInputTensor->data.f[samplesRead * 6 + 1] = (aY + 4.0) / 8.0; tflInputTensor->data.f[samplesRead * 6 + 2] = (aZ + 4.0) / 8.0; tflInputTensor->data.f[samplesRead * 6 + 3] = (gX + 2000.0) / 4000.0; tflInputTensor->data.f[samplesRead * 6 + 4] = (gY + 2000.0) / 4000.0; tflInputTensor->data.f[samplesRead * 6 + 5] = (gZ + 2000.0) / 4000.0; samplesRead++; if (samplesRead == numSamples) { // Run inferencing TfLiteStatus invokeStatus = tflInterpreter->Invoke(); if (invokeStatus != kTfLiteOk) { Serial.println("Invoke failed!"); while (1); return; } // Loop through the output tensor values from the model for (int i = 0; i < NUM_GESTURES; i++) { Serial.print(GESTURES[i]); Serial.print(": "); Serial.println(tflOutputTensor->data.f[i], 6); } Serial.println(); } } }