Thursday, 6 August 2026

AI Based Battery Management System for Electric Vehicles

An end-to-end guide and technical documentation for building an AI-Powered, Agentic IoT Battery Management System (BMS) for Electric Vehicles using ESP32, n8n Automation, Telegram Voice Alerts, ThingSpeak, and Google Sheets.


1. Full Project Description

Electric Vehicle (EV) batteries require real-time tracking of parameters such as voltage, current draw, temperature, State of Charge (SoC), and State of Health (SoH). Traditional BMS units protect against overcharging or overheating locally, but lack predictive cloud intelligence and agentic automated interventions.

This project implements an Agentic AI Battery Management System:

  • Edge Layer (ESP32): Reads voltage, current (ACS712), and temperature (DS18B20/DHT11), manages load isolation via relays, and transmits metrics to the cloud over Wi-Fi/HTTP.

  • Telemetry & Visualization (ThingSpeak): Receives real-time sensor streams and provides live dashboard analytics.

  • Orchestration & AI Agent Layer (n8n): Serves as the central autonomous engine. It receives webhooks from the ESP32/ThingSpeak, evaluates anomalies, calls AI models (e.g., OpenAI API) to predict power consumption and thermal runaway, logs data to Google Sheets, and triggers Telegram voice notifications.

  • Alerting Engine (Telegram Voice Bot): Converts AI-generated text alerts into audio files using Text-to-Speech (TTS) engine and sends voice notes directly to the fleet operator's Telegram app.

2. Hardware Components List

Component Model / Specification Function / Purpose
Microcontroller ESP32-WROOM-32 Development Board Edge processing, sensor reading, Wi-Fi connectivity
Current Sensor ACS712 (20A or 30A module) Measures current draw (Amperes)
Voltage Sensor Voltage Divider / Voltage Sensor Module (0–25V) Measures battery pack terminal voltage
Temperature Sensor DS18B20 (Waterproof) or DHT11/DHT22 Monitors battery surface temperature
Relay Module 2-Channel 5V Relay Module Battery protection cutout (Overvoltage / Overcurrent / Overheat)
Battery Pack 12V LiFePO4 or 3S Li-ion Battery EV main power source under test
Display (Optional) 0.96" I2C OLED Display (SSD1306) Local dashboard display
Miscellaneous Resistors (10kΩ, 4.7kΩ), Jumper Wires, Breadboard/PCB Circuit assembly & pull-ups

3. Circuit Schematic & Wiring Guide

ESP32 Pin Connections

      +-------------------------------------------------+
      |                   ESP32-WROOM                   |
      +-------------------------------------------------+
      | Vin  ---> 5V External Supply / Buck Converter   |
      | GND  ---> Common Ground                         |
      | GPIO 34 -> ACS712 OUT (Current Sensor)          |
      | GPIO 35 -> Voltage Sensor OUT                   |
      | GPIO 4  -> DS18B20 Data (with 4.7k Pull-up)     |
      | GPIO 21 -> OLED SDA                            |
      | GPIO 22 -> OLED SCL                            |
      | GPIO 18 -> Relay 1 IN (Cut-off Relay)           |
      | GPIO 19 -> Relay 2 IN (Cooling Fan / Reserve)   |
      +-------------------------------------------------+

Detailed Wiring Instructions

  1. ACS712 Current Sensor: Connect $V_{CC}$ to 5V, $GND$ to ESP32 $GND$, and $OUT$ to GPIO 34. Ensure voltage divider (e.g., 10k/20k) if output exceeds 3.3V.

  2. Voltage Sensor Module: Connect $V_{CC}$ to Battery $(+)$, $GND$ to Battery $(-)$. Output pin goes to GPIO 35.

  3. DS18B20 Temperature Sensor: Connect $V_{CC}$ to 3.3V, $GND$ to $GND$, Data wire to GPIO 4. Connect a 4.7kΩ resistor between Data and 3.3V.

  4. Relay Module: Connect $V_{CC}$ to 5V, $GND$ to $GND$, $IN1$ to GPIO 18, $IN2$ to GPIO 19.

4. Flowchart & System Architecture

  +----------------------------------------------------------+
  |                   ESP32 Edge Microcontroller             |
  |  - Sample Sensors (Voltage, Current, Temp)               |
  |  - Compute SoC (%) & Power (W)                           |
  |  - Check Hardware Limits (Relay Trip if Critical)       |
  +----------------------------+-----------------------------+
                               |
                        Wi-Fi / HTTP POST
                               v
    +--------------------------+--------------------------+
    |                                                     |
    v                                                     v
+-----------------------+             +-------------------------------+
| ThingSpeak Cloud      |             | n8n Agentic Workflow Engine   |
| - Live Graphs         |             | - Webhook Trigger             |
| - Historical Logs     |             | - Data Preprocessing          |
+-----------------------+             +---------------+---------------+
                                                      |
                                       +--------------+--------------+
                                       |                             |
                                       v                             v
                       +-------------------------------+ +-----------------------+
                       | AI Engine (LLM / ML Node)     | | Google Sheets Node    |
                       | - Predict Consumption         | | - Append Telemetry   |
                       | - Health / Anomaly Diagnosis  | |   Logs              |
                       +---------------+---------------+ +-----------------------+
                                       |
                                       v
                       +-------------------------------+
                       | TTS Voice Generation Service  |
                       | - Convert AI Alert to Audio   |
                       +---------------+---------------+
                                       |
                                       v
                       +-------------------------------+
                       | Telegram Bot Service          |
                       | - Dispatch Voice Note & Text  |
                       +-------------------------------+

5. ESP32 Source Code

Flash this standard C++ sketch via Arduino IDE. Ensure libraries OneWire, DallasTemperature, Adafruit_SSD1306, and HTTPClient are installed.

C++

#include <WiFi.h>
#include <HTTPClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// --- Network Configuration ---
const char* SSID = "YOUR_WIFI_SSID";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";

// --- Endpoint URLs ---
const char* THINGSPEAK_URL = "http://api.thingspeak.com/update";
const char* THINGSPEAK_API_KEY = "YOUR_THINGSPEAK_WRITE_KEY";
const char* N8N_WEBHOOK_URL = "http://YOUR_N8N_SERVER_IP:5678/webhook/ev-bms-data";

// --- Hardware Pins ---
#define CURRENT_PIN 34
#define VOLTAGE_PIN 35
#define TEMP_PIN 4
#define RELAY_PIN 18

OneWire oneWire(TEMP_PIN);
DallasTemperature tempSensor(&oneWire);
Adafruit_SSD1306 display(128, 64, &Wire, -1);

// --- Global Variables ---
float voltage = 0.0;
float current = 0.0;
float temperature = 0.0;
float power = 0.0;
float soc = 0.0;

void setup() {
  Serial.begin(115200);
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH); // Relay closed by default

  tempSensor.begin();

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED Allocation Failed"));
  }
  display.clearDisplay();
  display.setTextColor(WHITE);

  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Connected");
}

void readSensors() {
  // Voltage Reading (Calibrated for 0-25V Module)
  int vAnalog = analogRead(VOLTAGE_PIN);
  voltage = (vAnalog / 4095.0) * 3.3 * 5.0; // Voltage Divider Ratio ~5:1

  // Current Reading (ACS712-20A: 100mV/A sensitivity, zero-current offset ~1.65V)
  int iAnalog = analogRead(CURRENT_PIN);
  float rawV = (iAnalog / 4095.0) * 3.3;
  current = abs((rawV - 1.65) / 0.100);

  // Temperature Reading
  tempSensor.requestTemperatures();
  temperature = tempSensor.getTempCByIndex(0);

  // Derived Metrics
  power = voltage * current;
  // Basic SoC estimation for 12V LiFePO4 / Li-ion (10.0V = 0%, 12.6V = 100%)
  soc = map(constrain(voltage * 100, 1000, 1260), 1000, 1260, 0, 100);

  // Safety Hard Cutoff
  if (temperature > 55.0 || current > 15.0 || voltage < 9.5) {
    digitalWrite(RELAY_PIN, LOW); // Trip Relay
  } else {
    digitalWrite(RELAY_PIN, HIGH);
  }
}

void sendTelemetry() {
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;

    // 1. Send to ThingSpeak
    String tsUrl = String(THINGSPEAK_URL) + "?api_key=" + THINGSPEAK_API_KEY +
                   "&field1=" + String(voltage) +
                   "&field2=" + String(current) +
                   "&field3=" + String(temperature) +
                   "&field4=" + String(soc);
    http.begin(tsUrl);
    http.GET();
    http.end();

    // 2. Send JSON Payload to n8n Webhook
    http.begin(N8N_WEBHOOK_URL);
    http.addHeader("Content-Type", "application/json");
    String payload = "{\"voltage\":" + String(voltage) +
                     ",\"current\":" + String(current) +
                     ",\"temperature\":" + String(temperature) +
                     ",\"power\":" + String(power) +
                     ",\"soc\":" + String(soc) + "}";
    http.POST(payload);
    http.end();
  }
}

void updateDisplay() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.printf("EV BMS AI System\n");
  display.printf("Volt: %.2f V\n", voltage);
  display.printf("Curr: %.2f A\n", current);
  display.printf("Temp: %.1f C\n", temperature);
  display.printf("Power: %.1f W\n", power);
  display.printf("SoC: %.0f %%\n", soc);
  display.display();
}

void loop() {
  readSensors();
  updateDisplay();
  sendTelemetry();
  delay(15000); // 15-second update interval
}

6. n8n Automation Workflow Setup

The n8n engine coordinates AI evaluation, spreadsheet logging, and Telegram messaging.

Workflow Execution Steps

  1. Webhook Trigger Node: Receives POST request from ESP32 with JSON data (voltage, current, temperature, power, soc).

  2. Google Sheets Node: Appends a new row with timestamp, voltage, current, temperature, power, and SoC.

  3. AI Agent / OpenAI Node: Analyzes parameters and generates structured predictive diagnostics.

  4. If / Switch Node: Evaluates if AI flags an anomaly (e.g., thermal spike or battery strain).

  5. TTS Node (ElevenLabs or OpenAI Audio API): Converts AI summary into audio (.ogg or .mp3).

  6. Telegram Node: Transmits audio alert to fleet operator's Telegram channel.

n8n Workflow JSON Export

You can import this JSON directly into your n8n workspace:

JSON

{
  "name": "EV_BMS_Agentic_Automation",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "ev-bms-data",
        "options": {}
      },
      "name": "Webhook ESP32",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [250, 300]
    },
    {
      "parameters": {
        "operation": "append",
        "sheetId": "YOUR_GOOGLE_SHEET_ID",
        "range": "Raw_Data!A:F",
        "options": {}
      },
      "name": "Google Sheets Log",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [500, 200]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "content": "=Analyze EV battery metrics: Voltage={{$json.body.voltage}}V, Current={{$json.body.current}}A, Temp={{$json.body.temperature}}C, SoC={{$json.body.soc}}%. Provide a brief diagnostic summary (under 40 words) for driver voice alert. State if thermal risk or rapid drain exists."
            }
          ]
        }
      },
      "name": "AI Predictive Diagnostic",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1,
      "position": [500, 400]
    },
    {
      "parameters": {
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "text": "={{$node[\"AI Predictive Diagnostic\"].json.message.content}}",
        "additionalFields": {}
      },
      "name": "Telegram Alert",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [750, 400]
    }
  ],
  "connections": {
    "Webhook ESP32": {
      "main": [
        [
          { "node": "Google Sheets Log", "type": "main", "index": 0 },
          { "node": "AI Predictive Diagnostic", "type": "main", "index": 0 }
        ]
      ]
    },
    "AI Predictive Diagnostic": {
      "main": [
        [
          { "node": "Telegram Alert", "type": "main", "index": 0 }
        ]
      ]
    }
  }
}

7. Telegram Bot & Voice Setup

Step-by-Step Telegram Setup

  1. Search @BotFather on Telegram.

  2. Send /newbot, name your bot (e.g., EV_BMS_Agent_Bot), and obtain the HTTP API Token.

  3. Obtain your Chat ID by messaging @userinfobot.

  4. In n8n, create a Telegram Credential using the API token.

Voice Generation Pipeline

To generate voice notes:

  1. Add an HTTP Request Node after the AI node pointing to OpenAI TTS API ([https://api.openai.com/v1/audio/speech](https://api.openai.com/v1/audio/speech)).

  2. Payload:

    JSON

    {
      "model": "tts-1",
      "input": "{{$node['AI Predictive Diagnostic'].json.message.content}}",
      "voice": "alloy"
    }
    
  3. Set Response Option to File / Binary.

  4. In the Telegram Node, set Operation to sendAudio or sendVoice and attach the binary data.

8. Google Sheets Integration

  1. Create a new Google Sheet named EV_BMS_Cloud_Database.

  2. Name the first sheet Raw_Data and add headers in Row 1:

    Timestamp | Voltage (V) | Current (A) | Temp (°C) | Power (W) | SoC (%)

  3. Link n8n to your Google Account using OAuth2 credentials in n8n.

  4. Select Append Row operation and map the body variables to respective columns.

9. ThingSpeak Cloud Dashboard Setup

  1. Sign up at ThingSpeak.

  2. Create a new Channel named EV_BMS_Dashboard.

  3. Define 4 Fields:

    • Field 1: Voltage (V)

    • Field 2: Current (A)

    • Field 3: Temperature (°C)

    • Field 4: State of Charge (%)

  4. Copy the Write API Key and paste it into the ESP32 source code.

  5. Add Visual Widgets (Gauges and Line Charts) for real-time fleet monitoring.

10. AI Power Consumption & Health Logic

The AI Agent evaluates three key algorithms:

  1. Remaining Useful Range Prediction:

    $$\text{Estimated Range (km)} = \left( \frac{\text{SoC} \times \text{Capacity}_{\text{kWh}}}{100} \right) \times \frac{1000}{\text{Current Avg Consumption (Wh/km)}}$$
  2. Thermal Runaway Warning Logic:

    $$\Delta T = T_{\text{current}} - T_{\text{previous}}$$

    If $\Delta T > 2.0^{\circ}\text{C/min}$ while $I > 10\text{A}$, trigger Immediate Isolation & Voice Warning.

  3. State of Health (SoH) Estimation:

    Comparing actual discharge curves against the ideal lithium chemistry lookup matrix to flag internal resistance deterioration over time.

11. Deployment Guide & Future Enhancements

1.Hardware Bench Test:

Assemble circuit on breadboard. Power with bench power supply and verify sensor readings against a multimeter before connecting live battery packs.

2.Deploy n8n Automation Engine:

Run n8n locally via Docker (docker run -it --rm --name n8n -p 5678:5678 n8nio/n8n) or deploy on a cloud server (AWS / DigitalOcean).

3.Flash ESP32 Firmware:

Program ESP32 with updated Wi-Fi credentials and API endpoints. Confirm HTTP 200 responses in Serial Monitor.

4.Production Hardening:

Enclose hardware in an IP65 rated junction box, add optocouplers for high-voltage isolation, and add CAN-bus transceiver modules (e.g., MCP2515) for industrial EV integration.

Future Roadmap

  • CAN-Bus Integration: Transition from raw analog sensors to OBD-II / CAN-bus reading directly from commercial EV battery controllers.

  • On-Edge TinyML: Quantize the thermal anomaly model to run directly on the ESP32 using TensorFlow Lite for Microcontrollers, reducing cloud dependency.

AI Based Autonomous Farming Robot with Crop Health Monitoring

AI-Based Autonomous Farming Robot with Crop Health Monitoring

1. Full Project Description

The AI-Based Autonomous Farming Robot is an end-to-end Agentic IoT solution designed to automate crop health monitoring, environmental sensing, and field navigation.

Architecture Overview

  1. Edge Sensing & Actuation (ESP32): Reads soil moisture, ambient temperature/humidity (DHT22), optical leaf health via an LDR light/multispectral reflectance array, and tracks battery power consumption (INA219). It controls dual DC motors (L298N driver) for autonomous row navigation.

  2. Telemetry Dispatch: The ESP32 transmits sensor payload telemetry every cycle directly to ThingSpeak for continuous time-series graphing and sends a parallel HTTP POST webhook payload to an n8n Automation Engine.

  3. Agentic Orchestration & AI Analysis (n8n Engine): n8n parses incoming JSON payloads and routes sensor metrics to an AI Agent (powered by OpenAI / Groq / Gemini). The AI Agent evaluates soil stress levels, predicts power drain, and assesses plant health anomalies.

  4. Data Persistence & Analytics: Telemetry and AI health assessments are automatically logged to Google Sheets for historical auditing and yield forecasting.

  5. Real-time Voice Alerts (Telegram Bot): If crop stress, low soil moisture, or high power drain is detected, n8n passes the AI-generated advisory to a Text-to-Speech engine (OpenAI TTS / ElevenLabs) and delivers an audio voice note message directly to the farmer via Telegram.

2. Components List

Component Quantity Purpose / Specification
ESP32 NodeMCU Development Board 1 Master Edge Microcontroller with Wi-Fi & Bluetooth
L298N Dual H-Bridge Motor Driver 1 Controls 12V Gear Motors for robot locomotion
12V DC Geared Motors + Wheels 2 Differential drive robot chassis propulsion
DHT22 Temperature & Humidity Sensor 1 Ambient microclimate environmental monitoring
Capacitive Soil Moisture Sensor v1.2 1 Corrosion-resistant soil moisture measurement
LDR Photoresistor Module / Optical Sensor 1 Foliage reflectance / ambient light health checking
INA219 I2C Current/Voltage Sensor Module 1 Real-time voltage, current, and power consumption monitoring
HC-SR04 Ultrasonic Sensor 1 Autonomous obstacle detection and navigation
12.6V 3S Li-ion Battery Pack (18650) 1 Main power source for motors and electronics
LM2596 Buck Converter (12V to 5V) 1 Regulates 12V down to clean 5V for ESP32 and sensors
Breadboard / Custom PCB & Jumper Wires 1 Lot Interconnections

3. Circuit Schematic Diagram

Connection Pinout Table

Sensor / Module Module Pin ESP32 GPIO Pin Power Rail
L298N Motor Driver IN1 / IN2 GPIO 16 / GPIO 17 12V External (Motor Power)

IN3 / IN4 GPIO 18 / GPIO 19 12V External

ENA / ENB GPIO 22 / GPIO 23
DHT22 Sensor DATA GPIO 4 (10k Pull-up to 3.3V) 3.3V / GND
Soil Moisture Sensor AOUT GPIO 34 (ADC1_CH6) 3.3V / GND
LDR Sensor Module AOUT GPIO 35 (ADC1_CH7) 3.3V / GND
INA219 Power Sensor SDA / SCL GPIO 21 (SDA) / GPIO 22 (SCL) 3.3V / GND
HC-SR04 Ultrasonic TRIG / ECHO GPIO 12 / GPIO 13 5V / GND
LM2596 Buck Converter OUT+ / OUT- ESP32 VIN / GND 12V Battery Input

Schematic Wire Block Diagram

Plaintext

               +--------------------------------------------------------+
               |                   12.6V Li-ion Battery                 |
               +---------------------------+----------------------------+
                                           |
                                 +---------+---------+
                                 |                   |
                         +-------v-------+   +-------v-------+
                         | LM2596 Buck   |   | L298N Driver  |
                         | Converter 5V  |   | (Motor Power) |
                         +-------+-------+   +-------+-------+
                                 |                   |
                        +--------v-------------------+--------+
                        |           ESP32 DevBoard            |
                        +----+--------+-------+-------+-------+
                             |        |       |       |
                 +-----------+   +----+---+  ++-----+ ++------+
                 |               |        |   |     |  |      |
           +-----v-----+      +--v---+ +--v---+ +---v--v-+ +--v-----+
           | Capacitive|      |DHT22 | | LDR  | | INA219 | | HC-SR04|
           | Soil Sensor|     |Temp/ | | Leaf | | I2C    | | Ultra- |
           | (GPIO 34) |      |Hum   | | Light| | Sensor | | sonic  |
           +-----------+      +------+ +------+ +--------+ +--------+

4. System Flowchart

Plaintext

[START: Robot Power On]
       |
       v
[Initialize Wi-Fi, I2C, Sensors, & Motors]
       |
       v
[Read Sensors: Temp, Humidity, Moisture, Reflectance, Power]
       |
       v
[Obstacle Ahead < 20cm?] --YES--> [Stop Motors & Pivot Autonomous Turn]
       |                                     |
       NO                                    v
       |                          [Resume Forward Path]
       v
[Package Sensor Payload JSON]
       |
       v
[HTTP POST -> ThingSpeak Dashboard] (Every 15s)
       |
       v
[HTTP POST -> n8n Webhook Endpoint]
       |
       v
[n8n Workflow Activated]
       |
       +---> [Write Raw Telemetry -> Google Sheets]
       |
       +---> [Pass Telemetry -> Agentic AI Node]
                   |
                   v
         [Evaluate Crop Stress & Run Power Prediction Model]
                   |
         Anomalies / Threshold Crossed?
                   |
              +----+----+
             YES        NO
              |         |
              v         v
     [Generate Audio  [Log Healthy Status]
      via TTS API]
              |
              v
     [Send Telegram Voice
      Alert to Farmer]

5. ESP32 Source Code

Compile using Arduino IDE with the following required libraries:

WiFi.h, HTTPClient.h, DHT.h, Wire.h, Adafruit_INA219.h, ThingSpeak.h.

C++

#include <WiFi.h>
#include <HTTPClient.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_INA219.h>
#include <ThingSpeak.h>

// WiFi Configuration
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";

// ThingSpeak & n8n Configuration
WiFiClient client;
unsigned long thingSpeakChannelID = 1234567; // Replace with Channel ID
const char* thingSpeakAPIKey = "YOUR_THINGSPEAK_WRITE_KEY";
const char* n8nWebhookURL = "https://your-n8n-instance.com/webhook/crop-health";

// Pin Definitions
#define DHTPIN 4
#define DHTTYPE DHT22
#define SOIL_PIN 34
#define LDR_PIN 35
#define TRIG_PIN 12
#define ECHO_PIN 13

// L298N Motor Pins
#define IN1 16
#define IN2 17
#define IN3 18
#define IN4 19

DHT dht(DHTPIN, DHTTYPE);
Adafruit_INA219 ina219;

// Timing Constants
unsigned long lastPublishTime = 0;
const unsigned long publishInterval = 15000; // 15 seconds

void setup() {
  Serial.begin(115200);

  // Pin Modes
  pinMode(SOIL_PIN, INPUT);
  pinMode(LDR_PIN, INPUT);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT);

  // Initialize Sensors
  dht.begin();
  if (!ina219.begin()) {
    Serial.println("Warning: INA219 current sensor initialized with errors!");
  }

  // Connect WiFi
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi Connected! IP: " + WiFi.localIP().toString());

  ThingSpeak.begin(client);
}

long getDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout
  if (duration == 0) return 999;
  return duration * 0.034 / 2;
}

void moveForward() {
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW);
}

void turnRight() {
  digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);  digitalWrite(IN4, HIGH);
}

void stopRobot() {
  digitalWrite(IN1, LOW); digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW); digitalWrite(IN4, LOW);
}

void loop() {
  // Autonomous Navigation Loop
  long distance = getDistance();
  if (distance < 25) { // Obstacle closer than 25cm
    stopRobot();
    delay(300);
    turnRight();
    delay(600);
  } else {
    moveForward();
  }

  // Telemetry Upload Loop
  if (millis() - lastPublishTime >= publishInterval) {
    lastPublishTime = millis();

    float temp = dht.readTemperature();
    float hum = dht.readHumidity();
    int rawSoil = analogRead(SOIL_PIN);
    // Calibration: Map raw ADC (12-bit) to moisture percentage
    float moisture = map(rawSoil, 3200, 1400, 0, 100); 
    moisture = constrain(moisture, 0, 100);

    int rawLDR = analogRead(LDR_PIN);
    float leafReflectance = map(rawLDR, 0, 4095, 0, 100);

    float busVoltage = ina219.getBusVoltage_V();
    float current_mA = ina219.getCurrent_mA();
    float power_mW = ina219.getPower_mW();

    if (isnan(temp) || isnan(hum)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }

    // 1. Upload to ThingSpeak Dashboard
    ThingSpeak.setField(1, temp);
    ThingSpeak.setField(2, hum);
    ThingSpeak.setField(3, moisture);
    ThingSpeak.setField(4, leafReflectance);
    ThingSpeak.setField(5, busVoltage);
    ThingSpeak.setField(6, power_mW);
    
    int tsCode = ThingSpeak.writeFields(thingSpeakChannelID, thingSpeakAPIKey);
    Serial.println("ThingSpeak Update Status: " + String(tsCode));

    // 2. Transmit JSON Webhook to n8n Automation Engine
    if (WiFi.status() == WL_CONNECTED) {
      HTTPClient http;
      http.begin(n8nWebhookURL);
      http.addHeader("Content-Type", "application/json");

      String jsonPayload = "{";
      jsonPayload += "\"temperature\":" + String(temp, 1) + ",";
      jsonPayload += "\"humidity\":" + String(hum, 1) + ",";
      jsonPayload += "\"soil_moisture\":" + String(moisture, 1) + ",";
      jsonPayload += "\"leaf_health_index\":" + String(leafReflectance, 1) + ",";
      jsonPayload += "\"battery_voltage\":" + String(busVoltage, 2) + ",";
      jsonPayload += "\"power_consumption_mW\":" + String(power_mW, 1);
      jsonPayload += "}";

      int httpResponseCode = http.POST(jsonPayload);
      Serial.println("n8n Webhook Response Code: " + String(httpResponseCode));
      http.end();
    }
  }
}

6. n8n Workflow JSON

Import this JSON directly into your n8n editor (Settings -> Import from File / URL):

JSON

{
  "name": "AI Agentic IoT Crop Health & Voice Notification Pipeline",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "crop-health",
        "options": {}
      },
      "name": "ESP32 Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [100, 300]
    },
    {
      "parameters": {
        "operation": "append",
        "sheetId": "YOUR_GOOGLE_SHEET_ID",
        "range": "A:G",
        "options": {}
      },
      "name": "Google Sheets Logger",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4,
      "position": [320, 180]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are an expert Autonomous Agriculture AI Agent. Analyze the telemetry data provided: Temperature, Humidity, Soil Moisture, Leaf Health Index, Battery Voltage, and Power Consumption. Output a JSON payload containing: 1) 'alert_required' (boolean), 2) 'speech_text' (A concise script under 30 words for farmer voice alerts in clear simple terms), and 3) 'power_prediction' (estimated battery operating hours remaining)."
            },
            {
              "role": "user",
              "content": "={{ JSON.stringify($json.body) }}"
            }
          ]
        }
      },
      "name": "AI Crop Reasoning Agent",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1,
      "position": [320, 420]
    },
    {
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.message.content.alert_required }}",
              "value2": true
            }
          ]
        }
      },
      "name": "Check Alert Requirement",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [540, 420]
    },
    {
      "parameters": {
        "resource": "audio",
        "operation": "generate",
        "text": "={{ $json.message.content.speech_text }}",
        "voice": "alloy"
      },
      "name": "OpenAI Text-To-Speech",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1,
      "position": [760, 320]
    },
    {
      "parameters": {
        "operation": "sendAudio",
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "binaryData": true,
        "binaryPropertyName": "data",
        "caption": "🚨 AI Farm Robot Alert!"
      },
      "name": "Send Telegram Voice Alert",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [980, 320]
    }
  ],
  "connections": {
    "ESP32 Webhook Trigger": {
      "main": [
        [
          { "node": "Google Sheets Logger", "type": "main", "index": 0 },
          { "node": "AI Crop Reasoning Agent", "type": "main", "index": 0 }
        ]
      ]
    },
    "AI Crop Reasoning Agent": {
      "main": [
        [
          { "node": "Check Alert Requirement", "type": "main", "index": 0 }
        ]
      ]
    },
    "Check Alert Requirement": {
      "main": [
        [
          { "node": "OpenAI Text-To-Speech", "type": "main", "index": 0 }
        ]
      ]
    },
    "OpenAI Text-To-Speech": {
      "main": [
        [
          { "node": "Send Telegram Voice Alert", "type": "main", "index": 0 }
        ]
      ]
    }
  }
}

7. Telegram Bot Setup

  1. Open Telegram and search for @BotFather.

  2. Send /newbot, provide a name (e.g., SmartAgriRobotBot), and choose a username.

  3. Save the returned API Token (e.g., 7123456789:AAF...).

  4. Start a chat with your newly created bot and send any message (e.g., "Hello").

  5. Retrieve your numeric Chat ID by navigating to:

    [https://api.telegram.org/bot](https://api.telegram.org/bot)<YOUR_BOT_TOKEN>/getUpdates

  6. Enter the Token and Chat ID into the Telegram credentials section within n8n.

8. Google Sheets Integration

  1. Create a new Google Spreadsheet named Crop_Health_Telemetry.

  2. Add column headers in Row 1:

    • Column A: Timestamp

    • Column B: Temperature (°C)

    • Column C: Humidity (%)

    • Column D: Soil Moisture (%)

    • Column E: Leaf Health Index

    • Column F: Battery Voltage (V)

    • Column G: Power (mW)

  3. Connect your Google Account in n8n under Credentials -> Google Sheets OAuth2 API.

  4. Link the Spreadsheet ID in the Google Sheets Logger node.

9. ThingSpeak Cloud Dashboard Setup

  1. Sign up at ThingSpeak.com.  

  2. Click Channels -> My Channels -> New Channel.  

  3. Name: AI Farming Robot Dashboard.

  4. Configure Channel Fields:  

    • Field 1: Temperature (°C)  

    • Field 2: Humidity (%)  

    • Field 3: Soil Moisture (%)

    • Field 4: Leaf Health Index

    • Field 5: Battery Voltage (V)

    • Field 6: Power Consumption (mW)

  5. Save Channel and copy your Channel ID and Write API Key into the ESP32 code.  

  6. Customize the public/private dashboard with Gauge Widgets for Soil Moisture and Line Graphs for power consumption over time.

10. AI Power Consumption Prediction Logic

The power depletion rate is dynamically predicted inside the AI Agent using a regression formula based on instantaneous current draw and battery state:

$$P_{\text{instant}} = V_{\text{bus}} \times I_{\text{load}}$$
$$\text{Remaining Runtime (Hours)} = \frac{(V_{\text{bus}} - V_{\text{cutoff}}) \times Q_{\text{capacity}}}{P_{\text{instant}}} \times \eta$$

Where:

  • $V_{\text{bus}}$ = Current Battery Voltage read by INA219.

  • $V_{\text{cutoff}}$ = 9.9V (3S Li-ion empty threshold).

  • $Q_{\text{capacity}}$ = Nominal battery capacity (e.g., 2.5 Ah).

  • $P_{\text{instant}}$ = Measured power consumption in Watts.

  • $\eta$ = Discharge efficiency coefficient ($\approx 0.85$).

The AI Agent executes this reasoning calculation dynamically to predict runtime and flags an alert when estimated runtime drops under 30 minutes.

11. Voice Notification Automation

  1. Trigger: An anomaly is detected by n8n (e.g., soil_moisture < 25% or power_mW > 4500mW).

  2. Text Generation: The OpenAI Agent produces a contextual, high-priority summary script.

  3. Synthesis: The script is piped to the OpenAI Audio API (tts-1 model, alloy voice) or ElevenLabs, creating an .ogg / .mp3 audio payload.  

  4. Delivery: The n8n Telegram node transmits the binary audio file via sendAudio / sendVoice method, causing the farmer's mobile device to receive an audible push notification with voice instructions.

12. Future Enhancements & Deployment Guide

Deployment Checklist

  • Enclosure: Standard 3D-printed IP65 weatherproof housing to shield the ESP32 and motor driver from rain and dust.

  • Power: Mount a 5V/12V dual solar panel array directly on top of the robot chassis for continuous trickle charging.

Technical Next Steps

  • Edge Computer Vision: Upgrade the LDR sensor to an ESP32-CAM or Raspberry Pi Orin Nano running an ONNX YOLOV8 model for real-time leaf lesion and weed detection.

  • RTK GPS Autonomous Pathing: Integrate a Neo-6M GPS module with Real-Time Kinematic positioning for field navigation accurate to within centimeters.

Demonstrative Video Reference

To observe a implementation of a voice-triggered Telegram AI agent powered by n8n and Whisper/OpenAI speech nodes, check the demonstration below:

Build a Telegram Voice Trigger AI Agent in n8n  

This video demonstrates how incoming audio and AI voice responses are handled seamlessly in an n8n pipeline.