> For the complete documentation index, see [llms.txt](https://docs.consentiumiot.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.consentiumiot.com/tutorials/edge-machine-learning/sine-wave-predictor-with-iot.md).

# 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.

```cpp
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.

```cpp
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:

```cpp
#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
}
```
