Smart Energy Monitor
Learning Objectives
- Use a CT (current transformer) sensor to measure AC current consumption
- Connect an OLED display via I²C to show real-time power data
- Calculate real power, apparent power, and energy consumption over time
- Transmit sensor data over Wi-Fi using the ESP32's built-in radio
- Build a simple web dashboard to visualize energy data remotely
Overview
The Smart Energy Monitor is a non-invasive power meter that clips around an appliance's wire and measures AC current using electromagnetic induction — no cutting of wires required. An ESP32 reads the CT sensor, calculates power consumption, displays live data on a 0.96" OLED, and serves a lightweight web dashboard over Wi-Fi — all in one device.
Good to Know
The same CT sensor principle powers commercial energy monitors like the Emporia Vue and whole-home systems like Sense. Utility companies use industrial-grade CT sensors on street transformers to measure neighbourhood-level consumption. Your project works on exactly the same physics.
Components Required
| Component | Qty | Notes |
|---|---|---|
| ESP32 Development Board | 1 | Any variant with ADC and Wi-Fi (e.g., DOIT DevKit v1) |
| SCT-013-030 CT Sensor | 1 | 30 A max, 1 V output (built-in burden resistor) |
| SSD1306 0.96" OLED Display | 1 | I²C, 128×64 pixels |
| 10 µF Capacitor | 2 | Signal bias circuit |
| 10 kΩ Resistors | 2 | Voltage divider for ADC bias |
| 3.5 mm Audio Jack (female) | 1 | CT sensor connector |
| Breadboard + Jumper Wires | 1 set | _ |
Safety Warning
Good to Know
IMPORTANT SAFETY NOTICE: The CT sensor clamps around the outside of an insulated wire — it never touches live conductors. Never open an appliance cable or touch bare wires. This project is designed to be 100% safe when used on intact, properly insulated household cables with low-voltage appliances (lamps, fans, phone chargers). Adult supervision is required.
How CT Sensors Work
A current transformer (CT) sensor uses Faraday's Law of Induction: a changing current in the primary wire (the appliance cable) induces a proportional current in the CT's secondary winding. The ratio is fixed by the number of turns. The SCT-013-030 converts up to 30 A AC primary current into 0–1 V AC output — safe for a microcontroller ADC.
Key formulas:
I_rms = (ADC_rms_voltage / burden_resistance) × turns_ratioPower (W) = V_supply × I_rms × power_factorEnergy (Wh) = Power × time_hours
Circuit Setup
The CT sensor outputs an AC signal centered around 0 V, but the ESP32 ADC only reads 0–3.3 V. Build a bias circuit to shift the signal to 1.65 V center:
- Two 10 kΩ resistors from 3.3 V and GND meet at the bias point (1.65 V)
- Connect a 10 µF cap from the CT output to the bias point
- Connect the bias point to ESP32 GPIO34 (ADC1_CH6)
| OLED Pin | ESP32 Pin | |---------|----------| | VCC | 3.3 V | | GND | GND | | SDA | GPIO21 | | SCL | GPIO22 |
ESP32 Sketch
Install these libraries from Library Manager:
EmonLibby openenergymonitorAdafruit_SSD1306Adafruit_GFX
// Smart Energy Monitor — ESP32
#include <EmonLib.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <WebServer.h>
// Wi-Fi credentials
const char* SSID = "YOUR_WIFI_NAME";
const char* PASSWORD = "YOUR_WIFI_PASSWORD";
// Pins
#define CT_PIN 34
#define OLED_W 128
#define OLED_H 64
const float SUPPLY_VOLTAGE = 230.0; // Indian mains voltage (V RMS)
const float CALIBRATION = 30.0; // SCT-013-030: 30 A / 1 V
EnergyMonitor emon;
Adafruit_SSD1306 display(OLED_W, OLED_H, &Wire, -1);
WebServer server(80);
float currentAmps = 0;
float powerWatts = 0;
float energyWh = 0;
unsigned long lastMs = 0;
String buildDashboard() {
return R"(<!DOCTYPE html><html><head><meta charset='utf-8'>
<meta http-equiv='refresh' content='2'>
<title>Energy Monitor</title>
<style>body{font-family:sans-serif;text-align:center;background:#111;color:#fff}
.val{font-size:3em;color:#4ade80}</style></head>
<body><h2>Smart Energy Monitor</h2>
<p>Current: <span class='val'>)" + String(currentAmps, 2) + R"( A</span></p>
<p>Power: <span class='val'>)" + String(powerWatts, 1) + R"( W</span></p>
<p>Energy: <span class='val'>)" + String(energyWh, 3) + R"( Wh</span></p>
</body></html>)";
}
void setup() {
Serial.begin(115200);
emon.current(CT_PIN, CALIBRATION);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay(); display.setTextColor(WHITE);
display.setTextSize(1); display.setCursor(0, 0);
display.println("Energy Monitor"); display.display();
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nIP: " + WiFi.localIP().toString());
server.on("/", []() { server.send(200, "text/html", buildDashboard()); });
server.begin();
lastMs = millis();
}
void loop() {
server.handleClient();
// Measure every 2 seconds
if (millis() - lastMs > 2000) {
currentAmps = emon.calcIrms(1480); // 1480 samples ≈ ~30 cycles at 50 Hz
powerWatts = SUPPLY_VOLTAGE * currentAmps;
energyWh += powerWatts * ((millis() - lastMs) / 3600000.0);
lastMs = millis();
// Update OLED
display.clearDisplay();
display.setTextSize(1); display.setCursor(0, 0);
display.println("Smart Energy Monitor");
display.setTextSize(2); display.setCursor(0, 16);
display.print(currentAmps, 2); display.println(" A");
display.print(powerWatts, 0); display.println(" W");
display.setTextSize(1); display.setCursor(0, 52);
display.print("E: "); display.print(energyWh, 3); display.println(" Wh");
display.display();
}
}Experiments
Appliance Audit
Clamp the CT sensor around different appliance cords one at a time: a phone charger, a table fan, a lamp (100 W incandescent vs. 9 W LED). Record the measured wattage. Compare to the rated wattage on the appliance label. Calculate efficiency: Efficiency % = (Measured W / Rated W) × 100.
24-Hour Energy Budget
Leave the monitor on a TV or computer for 24 hours. Read the accumulated energyWh value. Convert to kilowatt-hours: kWh = Wh / 1000. Look up the current electricity tariff in your state and calculate the cost of running that appliance for one month.
