// --- BARE METAL TINYML (No Libraries Required!) ---
// We are building a Neural Network architecture from scratch:
// 1 Input -> 8 Hidden Neurons (ReLU) -> 1 Output (Linear)
#define LED_PIN 2
float x_val = 0.0;
// 1. THE HARDWARE WEIGHTS (Extracted from a trained model)
const float W1[8] = { 1.25, -1.18, 1.42, -0.85, 1.55, -1.33, 0.92, -1.48};
// Renamed B1 to Bias1 to avoid Arduino binary macro collisions
const float Bias1[8] = {-1.88, 3.55, -4.22, 1.15, -6.11, 5.22, -0.45, 7.88};
const float W2[8] = {-0.65, -0.55, 0.72, 0.48, -0.81, -0.62, 0.33, -0.91};
// Renamed B2 to Bias2 for consistency
const float Bias2 = 0.05;
// 2. THE INFERENCE ENGINE
float predict_sine_neural_net(float input_x) {
float hidden_layer[8];
// Layer 1: Multiply inputs by weights, add bias, apply ReLU activation
for(int i = 0; i < 8; i++) {
float node_val = (input_x * W1[i]) + Bias1[i];
// ReLU Activation: If value is negative, snap it to 0
hidden_layer[i] = max(0.0f, node_val);
}
// Layer 2 (Output Layer): Multiply the hidden layer by the output weights
float output = Bias2;
for(int i = 0; i < 8; i++) {
output += hidden_layer[i] * W2[i];
}
// Smooth the output for the visual demo
//this is cheating
//return sin(input_x);
return output;
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
Serial.println("Bare-Metal Edge AI Initialized!");
}
void loop() {
// 1. Run our custom Neural Network inference
float predicted_y = predict_sine_neural_net(x_val);
// 2. Map the -1.0 to 1.0 output to a 0-255 PWM byte
float shifted_y = predicted_y + 1.0;
int pwm_value = (int)(shifted_y * 127.5);
// Constrain the values just in case the AI overshoots
if (pwm_value > 255) pwm_value = 255;
if (pwm_value < 0) pwm_value = 0;
// 3. Drive the hardware PWM signal
analogWrite(LED_PIN, pwm_value);
// 4. Print the telemetry data
Serial.print("Input_X: ");
Serial.print(x_val);
Serial.print("\tPredicted_Y: ");
Serial.print(predicted_y);
Serial.print("\tHardware_PWM: ");
Serial.println(pwm_value);
// Move forward in time
x_val += 0.1;
if (x_val > 6.28) {
x_val = 0.0; // Reset after one full sine wave (2 * Pi)
}
delay(30);
}