Sine wave predictor with IoT

Documentation for Consentium TinyML Library Integration

This guide explains the usage and functionality of the Consentium TinyML library with ESP32 or Raspberry Pi Pico W compatible Edge boards. The code demonstrates how to perform sine wave prediction using a TensorFlow Lite model, which runs on a microcontroller (ESP32 or Raspberry Pi Pico W) and interacts with IoT boards for data transmission.

Key Components

Libraries Used

  • EdgeNeuron.h: This library includes the necessary functionality to work with TensorFlow Lite on microcontroller platforms.

  • ConsentiumThings.h: Provides support for IoT-related operations, such as WiFi initialization and data transmission.

Core Variables

  • ConsentiumThingsDalton board;: Creates an object to manage IoT operations (WiFi, data transmission).

  • WiFi Credentials:

    • ssid: Network SSID (WiFi name).

    • pass: WiFi password.

  • API Keys:

    • SendApiKey: The key to authenticate sending data to a remote server.

    • BoardApiKey: API key for identifying the board.

  • TensorFlow Lite Variables:

    • tensor_arena: Memory arena for TensorFlow Lite model execution.

    • kTensorArenaSize: Defines the maximum size of the tensor arena.

Code Breakdown

1. Setup Function

This function initializes both WiFi connectivity and the TensorFlow Lite model.

void setup() {
  board.initWiFi(ssid, pass); // Initialize WiFi with the given credentials
  board.beginSend(SendApiKey, BoardApiKey); // Start sending data
  
  // Initialize the model
  if (!initializeModel(model, tensor_arena, kTensorArenaSize)) {
    while (true);  // Halt if model initialization fails
  }
}
  • board.initWiFi(ssid, pass);: Connects to the specified WiFi network.

  • board.beginSend(SendApiKey, BoardApiKey);: Authenticates the board with its unique API keys.

  • initializeModel(...): Loads the TensorFlow Lite model into memory using the defined tensor arena. If this fails, the execution stops.

2. Main Loop

The loop function continuously predicts the sine of x using the model and compares it with the actual sine value.

void loop() {
  if (x > 6.28) {
    x = 0.0;
  }

  setModelInput(x, 0); // Set model input
  if (!runModelInference()) {
    return;  // If inference fails, exit the loop
  }

  float y_predicted = getModelOutput(0); // Retrieve the model's output
  float y_actual = sin(x); // Compute the actual sine value
  
  vector<double> sensorValues = {x, y_predicted, y_actual}; // Prepare sensor values
  const char* sensorInfo[] = {"Input", "Predicted", "Actual"}; // Metadata for each value

  board.sendData(sensorValues, sensorInfo, LOW_PRE); // Send the data with low precision

  x += step;  // Increment x by 0.1 (or any set step size)
  delay(interval); // Delay between each iteration (7 seconds)
}
  • setModelInput(x, 0);: Provides the input (x value) to the TensorFlow Lite model.

  • runModelInference();: Runs the inference process to predict the sine value.

  • getModelOutput(0);: Retrieves the model's predicted output.

  • sin(x);: Calculates the actual sine of x for comparison.

  • board.sendData(...): Sends the input, predicted, and actual sine values to a remote server with low precision (to reduce data size).

Additional Notes

  • WiFi Configuration: The code connects to a WiFi network using initWiFi(). If there are connectivity issues, ensure the SSID and password are correct.

  • API Keys: The API keys (SendApiKey and BoardApiKey) are essential for interacting with the server. If the keys are invalid, the data will not be sent successfully.

  • TensorFlow Lite Model: This code assumes that a pre-trained TensorFlow Lite model is already present, loaded via model.h. Ensure that the model is compiled correctly and fits within the defined tensor_arena size.

Potential Modifications

  • Step Size (x): You can adjust the step size for x to change how quickly it increments. A smaller step will result in more detailed predictions.

  • Delay: The delay(interval); statement controls how frequently data is sent. In this case, the delay is set to 7 seconds. Adjust it as per your use case.

  • Model Initialization: If the model initialization frequently fails due to insufficient memory, consider increasing the kTensorArenaSize value or reducing the model complexity.

Example Use Case

This code is designed to predict the sine of values between 0 and 2π using a TinyML model on an edge device. It's a typical example for IoT projects where data is transmitted wirelessly to a remote server.


License: This project is licensed under the MIT License. The above information, including the text from Consentium IoT., must be included in any redistribution or modification of this code.


Full Code:

/***************************************************
  This is Consentium's TinyML library
  ----> https://docs.consentiuminc.online/
  Check out the links above for our tutorials and product diagrams.

  This Consentium's TinyML library works only for ESP32/Raspberry Pi Pico W compatible Edge boards. 
  
  Written by Debjyoti Chowdhury for Consentium.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

#include <EdgeNeuron.h>
#include <ConsentiumThings.h>
#include "model.h"

ConsentiumThingsDalton board; // Create ConsentiumThings object

const char *ssid = "DebjyotiFi"; // Add WiFi SSID
const char *pass = "cxa1619s";   // Add WiFi password
constexpr uint16_t interval = 7000; // Wait for 7 seconds
const char *SendApiKey = "a98a467056c590a22d5d740f89a1c2f2"; // Send API key
const char *BoardApiKey = "02fad5a5e1d39f3b"; // Board API key

// Reduced Tensor arena size for TensorFlow Lite
constexpr uint16_t kTensorArenaSize = 2000;
alignas(16) uint8_t tensor_arena[kTensorArenaSize];

// Define the range for x (between 0 and 2π)
float x = 0.0;
constexpr float step = 0.1; // Step size for x increments

void setup() {
  // Initialize WiFi and IoT board
  board.initWiFi(ssid, pass);  
  board.beginSend(SendApiKey, BoardApiKey);

  // Initialize the model
  if (!initializeModel(model, tensor_arena, kTensorArenaSize)) {
    // Reduce print messages to save space
    // Serial.println("Model initialization failed!");
    while (true);  // Halt execution on failure
  }
}

void loop() {
  // Ensure x stays within the [0, 2π] range
  if (x > 6.28) {
    x = 0.0;
  }

  // Set input value in the model's input tensor
  setModelInput(x, 0);

  // Run the inference
  if (!runModelInference()) {
    // Serial.println("Inference Failed!");
    return;
  }

  // Get the predicted output
  float y_predicted = getModelOutput(0);

  // Get the actual sine of x
  float y_actual = sin(x);

  // Use vector of sensor values for sending data
  vector <double> sensorValues = {x, y_predicted, y_actual};
  const char* sensorInfo[] = {"Input","Predicted", "Actual"};

  // Send data with low precision to save space
  board.sendData(sensorValues, sensorInfo, LOW_PRE);

  // Increment x by the defined step size
  x += step;

  // Add a delay between loop iterations
  delay(interval);  // Adjust delay as needed for your use case
}

Last updated