IoT Energy Monitoring System using esp32 and wowki simulator

IoT Energy Monitoring System using ESP32 DevKit V1 | MakeMindz
🔧 MakeMindz — Build Smarter Electronics  |  Visit the full blog →
ESP32 IoT Energy Intermediate Wokwi

IoT Energy Monitoring System using ESP32 DevKit V1

Track real-time power consumption of household appliances, analyze energy usage, calculate cost, and receive overload alerts — all from a smart web dashboard and OLED display.

📅 February 2026 ⏱️ ~45 min build time 📡 ESP32 + WiFi 🎯 Difficulty: Intermediate

⚡ Try it in your browser — Free Wokwi Simulation

No hardware needed. Run this project instantly in the Wokwi simulator.

▶ Launch Simulation

📌 Project Overview

This Smart Energy Monitoring System uses the WiFi-enabled ESP32 microcontroller to monitor voltage and current across three channels (Living Room, Kitchen, Bedroom) and calculate real-time power and energy usage. It combines IoT technology with embedded systems to give you full visibility into your home's electricity consumption.

Real-time Voltage Monitoring (0–250V)
🔌Multi-channel Current Monitoring (3 Channels)
💡Automatic Power Calculation (Watts)
🔋Energy Tracking (kWh)
💰Cost Calculation ($/kWh)
📈Historical Data Logging
🖥️Web Dashboard (Dark Theme UI)
📟OLED Local Display
🚨Overload Protection Alerts
🎛️Remote Relay Control

🔬 Working Principle & Formulas

The ESP32 reads analog signals from potentiometers (simulating sensors) via its ADC pins. These raw values are mapped to physical units. The system then applies electrical formulas to derive power, energy, and cost.

⚡ Power Formula
P = V × I × PF
V = Voltage  |  I = Current  |  PF = 0.95
🔋 Energy Formula
E = (P / 1000) × T
P = Watts  |  T = Time in hours  |  Result in kWh
💰 Cost Formula
Cost = E × Rate
E = Energy in kWh  |  Default Rate: $0.12/kWh
💡

Simulation Note

In Wokwi simulation, potentiometers simulate voltage (0–250V) and current (0–20A) sensors. In real hardware, use PZEM-004T or a CT Sensor for AC measurement.

🧰 Components Required

# Component Quantity Notes
1ESP32 DevKit V11Main microcontroller with WiFi
2Potentiometer (Wokwi) / PZEM-004T4Simulates voltage + 3 currents
3CT Sensor (Current Transformer)3For real AC current measurement
4SSD1306 OLED Display (128×64)1I2C, address 0x3C
5LED — Green1Living Room channel indicator
6LED — Blue1Kitchen channel indicator
7LED — Yellow1Bedroom channel indicator
8LED — White1Power indicator
9LED — Red1Alert indicator
10Resistors 220Ω5Current limiting for LEDs
11Buzzer (Active)1Overload alert sound
12WiFi Network / Router1For web dashboard access
13Blynk / ThingSpeak (optional)Cloud dashboard integration

🔗 Pin Connections & Wiring

⚡ Sensor Inputs (ADC Pins)
Voltage Sensor / PotD34 Orange wire
Current CH1 (Living Room)D35 Green wire
Current CH2 (Kitchen)D32 Blue wire
Current CH3 (Bedroom)D33 Yellow wire
🎛️ Relay / LED Outputs
Relay CH1 (Green LED)D26Living Room
Relay CH2 (Blue LED)D27Kitchen
Relay CH3 (Yellow LED)D14Bedroom
Power LED (White)D13Via 220Ω resistor → GND
Alert LED (Red)D12Via 220Ω resistor → GND
Buzzer (+)D25Buzzer (–) → GND
📟 OLED Display (I2C)
VCC3V3 Red wire
GNDGND Black wire
SDAD21 Blue wire
SCLD22 Yellow wire
⚠️

ADC Pins Note

ESP32 pins D34 and D35 are input-only ADC pins — perfect for sensor reading. Avoid using them as output. Also, ADC2 pins (D0, D2, D4) cannot be used when WiFi is active.

📦 Libraries to Install

Install these libraries in the Arduino IDE via Sketch → Include Library → Manage Libraries:

  • 📺Adafruit_SSD1306OLED display driverv2.5.x
  • 🎨Adafruit_GFXGraphics library (dependency)v1.11.x
  • 📡WiFi.hBuilt-in ESP32 WiFi libraryBuilt-in
  • 🌐WebServer.hBuilt-in ESP32 HTTP serverBuilt-in
  • 🔌Wire.hI2C communication (built-in)Built-in

Board Setup

In Arduino IDE: File → Preferences → Additional Board URLs → add https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json. Then install esp32 by Espressif from Board Manager.

📡 Multi-Channel Monitoring

The system monitors three independent circuits simultaneously, each mapped to a room in the house. Every channel independently tracks its own voltage, current, power, energy, and cost.

Channel 1
Living Room
ADC: D35 | Relay: D26
VoltageCurrentPower kWhCostPeak
Channel 2
Kitchen
ADC: D32 | Relay: D27
VoltageCurrentPower kWhCostPeak
Channel 3
Bedroom
ADC: D33 | Relay: D14
VoltageCurrentPower kWhCostPeak

🚨 Smart Alert System

The system continuously monitors three alert conditions. When triggered, the Red LED flashes, the buzzer sounds, the OLED shows a warning, and the web dashboard updates.

3000W
🔴 Critical Overload
Total power exceeds max — immediate alert
2000W
🟡 High Warning
Approaching overload — caution alert
15A
🔵 Current Limit
Per-channel current too high

When Alert Fires:

1

Red Alert LED turns ON

GPIO 12 drives the red LED HIGH via 220Ω resistor.

2

Buzzer Sounds

Tone at 2000Hz plays for 300ms using GPIO 25.

3

OLED Displays "! HIGH POWER !"

The display replaces the uptime counter with a flashing warning message.

4

Web Dashboard Updates

Status auto-refreshes every 5 seconds — alertActive flag set in JSON API.

🖥️ Web Dashboard Features

Access the dashboard from any browser on your WiFi network by navigating to the ESP32's IP address (printed on Serial Monitor at startup).

🔄Auto-refresh every 5 seconds
📊Power analytics & averages
💡Consumption history tracking
🧾Energy billing summary
📡Individual channel status
🎛️ON/OFF remote relay control
🔁Reset energy counters
⏱️System uptime monitoring

API Endpoints

EndpointMethodDescription
/GETMain dashboard HTML page
/statusGETJSON with all sensor data
/historyGETJSON array of power history (50 points)
/resetGETReset energy & cost counters
/relay1/on or /offGETControl Living Room relay
/relay2/on or /offGETControl Kitchen relay
/relay3/on or /offGETControl Bedroom relay

📟 OLED Display Layout

The SSD1306 128×64 OLED gives local feedback without needing WiFi. It updates every 500ms and cycles through key metrics.

OLED LAYOUT (128×64 px)
┌─────────────────────────┐
│ ENERGY MONITOR          │  ← Row 0  (title)
│─────────────────────────│  ← Row 9  (separator line)
│ Power: 1250 W           │  ← Row 12 (total power)
│ Energy: 0.04 kWh        │  ← Row 22 (cumulative energy)
│ Cost: $0.00             │  ← Row 32 (total cost)
│ L:420 K:530 B:300       │  ← Row 42 (channel breakdown)
│ Up: 0h 5m               │  ← Row 54 (uptime / alert msg)
└─────────────────────────┘

🗂️ Diagram.json — Wokwi Circuit File

Copy this diagram.json into your Wokwi project to set up all component connections automatically.

📄 diagram.json — IoT Energy Monitoring System
{
  "version": 1,
  "author": "ESP32 Energy Monitoring System",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": 0, "left": 0, "attrs": {} },
    { "type": "wokwi-potentiometer", "id": "voltage", "top": -67.2, "left": 268.8, "rotate": 180, "attrs": { "label": "Voltage (220V)" } },
    { "type": "wokwi-potentiometer", "id": "current1", "top": 28.8, "left": 268.8, "rotate": 180, "attrs": { "label": "Current CH1" } },
    { "type": "wokwi-potentiometer", "id": "current2", "top": 124.8, "left": 268.8, "rotate": 180, "attrs": { "label": "Current CH2" } },
    { "type": "wokwi-potentiometer", "id": "current3", "top": 220.8, "left": 268.8, "rotate": 180, "attrs": { "label": "Current CH3" } },
    { "type": "wokwi-led", "id": "relay1", "top": -124.8, "left": 441.6, "attrs": { "color": "green", "lightColor": "green", "label": "Living Room" } },
    { "type": "wokwi-resistor", "id": "r1", "top": -67.2, "left": 441.6, "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-led", "id": "relay2", "top": -124.8, "left": 518.4, "attrs": { "color": "blue", "lightColor": "blue", "label": "Kitchen" } },
    { "type": "wokwi-resistor", "id": "r2", "top": -67.2, "left": 518.4, "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-led", "id": "relay3", "top": -124.8, "left": 595.2, "attrs": { "color": "yellow", "lightColor": "yellow", "label": "Bedroom" } },
    { "type": "wokwi-resistor", "id": "r3", "top": -67.2, "left": 595.2, "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-led", "id": "power_led", "top": 38.4, "left": 441.6, "attrs": { "color": "white", "lightColor": "white", "label": "Power" } },
    { "type": "wokwi-resistor", "id": "r4", "top": 96, "left": 441.6, "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-led", "id": "alert_led", "top": 38.4, "left": 518.4, "attrs": { "color": "red", "lightColor": "red", "label": "Alert" } },
    { "type": "wokwi-resistor", "id": "r5", "top": 96, "left": 518.4, "rotate": 90, "attrs": { "value": "220" } },
    { "type": "wokwi-buzzer", "id": "bz1", "top": 172.8, "left": 489.6, "attrs": { "volume": "0.3" } },
    { "type": "wokwi-ssd1306", "id": "oled1", "top": 326.4, "left": 268.8, "attrs": { "i2cAddress": "0x3C" } }
  ],
  "connections": [
    [ "esp:TX0", "$serialMonitor:RX", "", [] ],
    [ "esp:RX0", "$serialMonitor:TX", "", [] ],
    [ "voltage:GND", "esp:GND.1", "black", [ "v0" ] ],
    [ "voltage:VCC", "esp:3V3", "red", [ "v0" ] ],
    [ "voltage:SIG", "esp:D34", "orange", [ "v0" ] ],
    [ "current1:GND", "esp:GND.1", "black", [ "v0" ] ],
    [ "current1:VCC", "esp:3V3", "red", [ "v0" ] ],
    [ "current1:SIG", "esp:D35", "green", [ "v0" ] ],
    [ "current2:GND", "esp:GND.2", "black", [ "v0" ] ],
    [ "current2:VCC", "esp:3V3", "red", [ "v0" ] ],
    [ "current2:SIG", "esp:D32", "blue", [ "v0" ] ],
    [ "current3:GND", "esp:GND.2", "black", [ "v0" ] ],
    [ "current3:VCC", "esp:3V3", "red", [ "v0" ] ],
    [ "current3:SIG", "esp:D33", "yellow", [ "v0" ] ],
    [ "relay1:A", "esp:D26", "green", [ "v0" ] ],
    [ "relay1:C", "r1:1", "green", [ "v0" ] ],
    [ "r1:2", "esp:GND.1", "black", [ "v0" ] ],
    [ "relay2:A", "esp:D27", "blue", [ "v0" ] ],
    [ "relay2:C", "r2:1", "blue", [ "v0" ] ],
    [ "r2:2", "esp:GND.1", "black", [ "v0" ] ],
    [ "relay3:A", "esp:D14", "yellow", [ "v0" ] ],
    [ "relay3:C", "r3:1", "yellow", [ "v0" ] ],
    [ "r3:2", "esp:GND.1", "black", [ "v0" ] ],
    [ "power_led:A", "esp:D13", "white", [ "v0" ] ],
    [ "power_led:C", "r4:1", "white", [ "v0" ] ],
    [ "r4:2", "esp:GND.2", "black", [ "v0" ] ],
    [ "alert_led:A", "esp:D12", "red", [ "v0" ] ],
    [ "alert_led:C", "r5:1", "red", [ "v0" ] ],
    [ "r5:2", "esp:GND.2", "black", [ "v0" ] ],
    [ "bz1:1", "esp:D25", "purple", [ "v0" ] ],
    [ "bz1:2", "esp:GND.2", "black", [ "v0" ] ],
    [ "oled1:VCC", "esp:3V3", "red", [ "h0" ] ],
    [ "oled1:GND", "esp:GND.2", "black", [ "h0" ] ],
    [ "oled1:SDA", "esp:D21", "blue", [ "h0" ] ],
    [ "oled1:SCL", "esp:D22", "yellow", [ "h0" ] ]
  ],
  "dependencies": {}
}

💻 Full Arduino Code

Upload this sketch to your ESP32 using Arduino IDE. Change ssid and password to match your WiFi network.

📡

For Wokwi Simulation

Keep SSID as "Wokwi-GUEST" and password as "" — the simulator provides a free virtual WiFi network.

Arduino C++ — main.ino
/*
 * IoT Energy Monitoring System
 * Platform: ESP32 DevKit V1
 * Author: MakeMindz | www.makemindz.com
 *
 * Features:
 * - Real-time 3-channel voltage & current monitoring
 * - Power (W), Energy (kWh), Cost ($) calculation
 * - OLED local display + Web dashboard
 * - Overload alerts (buzzer + LED)
 * - Remote relay control via HTTP
 */

#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// ── WiFi Credentials ──────────────────────────
const char* ssid     = "Wokwi-GUEST";
const char* password = "";

WebServer server(80);

// ── Pin Definitions ───────────────────────────
#define VOLTAGE_SENSOR_PIN  34
#define CURRENT_CH1_PIN     35
#define CURRENT_CH2_PIN     32
#define CURRENT_CH3_PIN     33
#define RELAY_CH1_PIN       26
#define RELAY_CH2_PIN       27
#define RELAY_CH3_PIN       14
#define BUZZER_PIN          25
#define LED_POWER_PIN       13
#define LED_ALERT_PIN       12

// ── OLED Display ──────────────────────────────
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 64
#define OLED_RESET    -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// ── Configuration ─────────────────────────────
#define VOLTAGE_CALIBRATION 1.0
#define CURRENT_CALIBRATION 1.0
#define POWER_FACTOR        0.95
#define COST_PER_KWH        0.12

// ── Alert Thresholds ──────────────────────────
#define MAX_POWER_WATTS   3000
#define HIGH_POWER_WARNING 2000
#define MAX_CURRENT_AMPS  15

// ── Data Structures ───────────────────────────
struct EnergyChannel {
  String name;
  float voltage, current, power, energy, cost;
  bool relayState;
  unsigned long lastUpdate;
  float peakPower;
  int alertCount;
};

struct SystemState {
  float totalPower, totalEnergy, totalCost, averagePower;
  unsigned long startTime, lastReset;
  int displayMode;
  bool alertActive;
  float costPerKWh;
};

EnergyChannel channels[3];
SystemState energySystem;

#define MAX_HISTORY 50
float powerHistory[MAX_HISTORY];
int historyIndex = 0;

unsigned long lastSensorRead   = 0;
unsigned long lastDisplayUpdate = 0;
unsigned long lastCostUpdate    = 0;
const long sensorInterval      = 1000;
const long displayInterval     = 500;
const long costUpdateInterval  = 60000;

// ── Setup ─────────────────────────────────────
void setup() {
  Serial.begin(115200);

  pinMode(RELAY_CH1_PIN, OUTPUT);
  pinMode(RELAY_CH2_PIN, OUTPUT);
  pinMode(RELAY_CH3_PIN, OUTPUT);
  pinMode(BUZZER_PIN,    OUTPUT);
  pinMode(LED_POWER_PIN, OUTPUT);
  pinMode(LED_ALERT_PIN, OUTPUT);
  pinMode(VOLTAGE_SENSOR_PIN, INPUT);
  pinMode(CURRENT_CH1_PIN,    INPUT);
  pinMode(CURRENT_CH2_PIN,    INPUT);
  pinMode(CURRENT_CH3_PIN,    INPUT);

  channels[0].name = "Living Room";
  channels[1].name = "Kitchen";
  channels[2].name = "Bedroom";

  for (int i = 0; i < 3; i++) {
    channels[i].voltage    = 0;
    channels[i].current    = 0;
    channels[i].power      = 0;
    channels[i].energy     = 0;
    channels[i].cost       = 0;
    channels[i].relayState = true;
    channels[i].lastUpdate = millis();
    channels[i].peakPower  = 0;
    channels[i].alertCount = 0;
    digitalWrite(RELAY_CH1_PIN + i, HIGH);
  }

  energySystem.totalPower   = 0;
  energySystem.totalEnergy  = 0;
  energySystem.totalCost    = 0;
  energySystem.averagePower = 0;
  energySystem.startTime    = millis();
  energySystem.lastReset    = millis();
  energySystem.displayMode  = 0;
  energySystem.alertActive  = false;
  energySystem.costPerKWh   = COST_PER_KWH;

  // Init OLED
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("OLED failed"));
  } else {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("ENERGY MONITOR");
    display.println("Initializing...");
    display.display();
    delay(2000);
  }

  // Connect WiFi
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi");
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Connecting WiFi...");
  display.display();
  while (WiFi.status() != WL_CONNECTED) {
    delay(500); Serial.print(".");
  }
  Serial.println("\n✓ WiFi connected!");
  Serial.print("Dashboard: http://");
  Serial.println(WiFi.localIP());

  // Register routes
  server.on("/", handleRoot);
  server.on("/status", handleStatus);
  server.on("/history", handleHistory);
  server.on("/reset", handleReset);
  server.on("/relay1/on",  []() { controlRelay(0, true);  });
  server.on("/relay1/off", []() { controlRelay(0, false); });
  server.on("/relay2/on",  []() { controlRelay(1, true);  });
  server.on("/relay2/off", []() { controlRelay(1, false); });
  server.on("/relay3/on",  []() { controlRelay(2, true);  });
  server.on("/relay3/off", []() { controlRelay(2, false); });
  server.begin();

  digitalWrite(LED_POWER_PIN, HIGH);
  tone(BUZZER_PIN, 1000, 100); delay(150);
  tone(BUZZER_PIN, 1500, 100);
  updateDisplay();
}

// ── Loop ──────────────────────────────────────
void loop() {
  server.handleClient();
  unsigned long now = millis();

  if (now - lastSensorRead >= sensorInterval) {
    lastSensorRead = now;
    readSensors();
    calculatePower();
    checkAlerts();
  }
  if (now - lastDisplayUpdate >= displayInterval) {
    lastDisplayUpdate = now;
    updateDisplay();
  }
  if (now - lastCostUpdate >= costUpdateInterval) {
    lastCostUpdate = now;
    updateEnergyCost();
  }
}

// ── Sensor Reading ────────────────────────────
void readSensors() {
  int voltageRaw = analogRead(VOLTAGE_SENSOR_PIN);
  float voltage  = map(voltageRaw, 0, 4095, 0, 250) * VOLTAGE_CALIBRATION;

  int r1 = analogRead(CURRENT_CH1_PIN);
  int r2 = analogRead(CURRENT_CH2_PIN);
  int r3 = analogRead(CURRENT_CH3_PIN);

  channels[0].current = map(r1, 0, 4095, 0, 20) * CURRENT_CALIBRATION;
  channels[1].current = map(r2, 0, 4095, 0, 20) * CURRENT_CALIBRATION;
  channels[2].current = map(r3, 0, 4095, 0, 20) * CURRENT_CALIBRATION;

  for (int i = 0; i < 3; i++) {
    channels[i].voltage = voltage;
    if (!channels[i].relayState) channels[i].current = 0;
  }
}

// ── Power Calculation ─────────────────────────
void calculatePower() {
  energySystem.totalPower = 0;
  for (int i = 0; i < 3; i++) {
    channels[i].power = channels[i].voltage * channels[i].current * POWER_FACTOR;
    if (channels[i].power > channels[i].peakPower)
      channels[i].peakPower = channels[i].power;

    unsigned long dt = millis() - channels[i].lastUpdate;
    float hours = dt / 3600000.0;
    channels[i].energy += (channels[i].power / 1000.0) * hours;
    channels[i].lastUpdate = millis();
    channels[i].cost = channels[i].energy * energySystem.costPerKWh;
    energySystem.totalPower += channels[i].power;
  }
  energySystem.totalEnergy = channels[0].energy + channels[1].energy + channels[2].energy;
  energySystem.totalCost   = energySystem.totalEnergy * energySystem.costPerKWh;

  powerHistory[historyIndex] = energySystem.totalPower;
  historyIndex = (historyIndex + 1) % MAX_HISTORY;

  float sum = 0;
  for (int i = 0; i < MAX_HISTORY; i++) sum += powerHistory[i];
  energySystem.averagePower = sum / MAX_HISTORY;
}

// ── Alert Checker ─────────────────────────────
void checkAlerts() {
  bool triggered = false;
  if (energySystem.totalPower > MAX_POWER_WATTS)   triggered = true;
  if (energySystem.totalPower > HIGH_POWER_WARNING) triggered = true;
  for (int i = 0; i < 3; i++) {
    if (channels[i].current > MAX_CURRENT_AMPS) {
      channels[i].alertCount++;
      triggered = true;
    }
  }
  if (triggered && !energySystem.alertActive) {
    energySystem.alertActive = true;
    digitalWrite(LED_ALERT_PIN, HIGH);
    tone(BUZZER_PIN, 2000, 300);
  } else if (!triggered && energySystem.alertActive) {
    energySystem.alertActive = false;
    digitalWrite(LED_ALERT_PIN, LOW);
  }
}

// ── OLED Update ───────────────────────────────
void updateDisplay() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("ENERGY MONITOR");
  display.drawLine(0, 9, 128, 9, SSD1306_WHITE);

  display.setCursor(0, 12);
  display.print("Power: "); display.print(energySystem.totalPower, 0); display.println(" W");
  display.setCursor(0, 22);
  display.print("Energy: "); display.print(energySystem.totalEnergy, 2); display.println(" kWh");
  display.setCursor(0, 32);
  display.print("Cost: $"); display.println(energySystem.totalCost, 2);
  display.setCursor(0, 42);
  display.print("L:"); display.print(channels[0].power, 0);
  display.print(" K:"); display.print(channels[1].power, 0);
  display.print(" B:"); display.print(channels[2].power, 0);

  display.setCursor(0, 54);
  if (energySystem.alertActive) {
    display.print("! HIGH POWER !");
  } else {
    unsigned long up = (millis() - energySystem.startTime) / 1000;
    display.print("Up:"); display.print(up/3600); display.print("h ");
    display.print((up%3600)/60); display.print("m");
  }
  display.display();
}

// ── Relay Control ─────────────────────────────
void controlRelay(int ch, bool state) {
  if (ch >= 0 && ch < 3) {
    channels[ch].relayState = state;
    digitalWrite(RELAY_CH1_PIN + ch, state ? HIGH : LOW);
    tone(BUZZER_PIN, state ? 1200 : 800, 100);
    server.sendHeader("Location", "/");
    server.send(303);
  }
}

void updateEnergyCost() {
  for (int i = 0; i < 3; i++)
    channels[i].cost = channels[i].energy * energySystem.costPerKWh;
  energySystem.totalCost = energySystem.totalEnergy * energySystem.costPerKWh;
}

// ── Web Handlers (see full source for HTML) ───
void handleRoot()    { /* Full dark-theme dashboard HTML */ }
void handleStatus()  { /* Returns JSON with all sensor data */ }
void handleHistory() { /* Returns JSON array of power history */ }
void handleReset()   {
  for (int i = 0; i < 3; i++) {
    channels[i].energy = channels[i].cost = channels[i].peakPower = 0;
    channels[i].alertCount = 0;
  }
  energySystem.totalEnergy = energySystem.totalCost = 0;
  energySystem.lastReset = millis();
  server.sendHeader("Location", "/");
  server.send(303);
}

▶ View Full Code + Live Simulation

The complete project with web dashboard HTML is available on Wokwi.

Open in Wokwi

🏭 Applications

🏠Home Energy Management
🔢Smart Metering System
🏗️Industrial Load Monitoring
☀️Solar Panel Tracking
📋Energy Audit Projects
📱IoT Smart Home
💡Cost Optimization
🔬Student Projects

🚀 Future Enhancements

📡Real AC measurement using PZEM-004T module
☁️Cloud integration with Blynk / ThingSpeak
📧Email / SMS overload alerts
📱Mobile app control interface
🕒Peak / off-peak tariff support
📄Monthly PDF billing report export
💾SD card data logging
🤖AI-based energy saving recommendations

🔧 More ESP32 Projects on MakeMindz

© 2026 MakeMindz — Electronics, IoT & Embedded Systems Tutorials

ESP32 · Arduino · IoT · Wokwi · Raspberry Pi

Comments

try for free