Building a home energy monitor with ESP32 and PZEM-004T gives you real-time visibility into your electricity consumption — critical for Indian households looking to manage rising electricity bills. The PZEM-004T is an AC energy measurement module that measures voltage, current, power, frequency, power factor, and total energy consumption. With ESP32 and a web dashboard, you can track your daily, monthly units consumption and identify power-hungry appliances in India.
Table of Contents
- Why Energy Monitoring for India
- PZEM-004T Module Specifications
- Hardware Setup and Safety
- ESP32 PZEM-004T Code
- Real-Time Web Dashboard
- Home Assistant Integration
- Indian Electricity Billing Calculator
- Frequently Asked Questions
Why Energy Monitoring for India
Energy monitoring is especially valuable for Indian households:
- Rising electricity costs: Indian electricity tariffs have increased 30–50% over the past 5 years in many states
- Tiered billing: Most Indian states use tiered tariffs where higher consumption units cost more — monitoring helps stay in cheaper tiers
- Air conditioner dominance: AC often accounts for 50–70% of summer electricity bills in India — monitoring AC consumption directly drives savings
- Subsidy awareness: TANGEDCO, MSEDCL, BESCOM and other discoms have free/subsidised unit slabs — real-time monitoring prevents overshooting subsidy limits
- Appliance identification: A single faulty geyser element can double electricity consumption — monitoring catches anomalies
PZEM-004T Module Specifications
- Voltage measurement: 80–260V AC (covers Indian range 190–250V)
- Current measurement: 0–100A (with external CT clamp)
- Power measurement: 0–23kW (single phase)
- Energy measurement: 0–9999.99kWh
- Frequency: 45–65 Hz (Indian standard 50 Hz)
- Power factor: 0.00–1.00
- Interface: UART/ModBus-RTU at 9600 baud, 3.3V compatible
- India Price: ₹400–₆00 with CT clamp
- Accuracy: ±0.5% for current, ±1% for energy
The PZEM-004T v3.0 is the current version — it uses ModBus communication and supports multiple units (with different ModBus addresses) on one UART bus.
Hardware Setup and Safety
/* PZEM-004T Connection to ESP32 */
// SAFETY: PZEM-004T AC input side is LIVE MAINS voltage
// NEVER touch the AC terminals without disconnecting power
// The ESP32 side (UART pins) is low voltage and safe to handle
// PZEM-004T connections:
// Mains side (DANGEROUS - 230V AC):
// AC INPUT L → Live wire from mains (through CT clamp if non-invasive)
// AC INPUT N → Neutral wire from mains
// CT Output + → CT clamp positive
// CT Output - → CT clamp negative
//
// UART side (safe - 5V max):
// PZEM TX → ESP32 GPIO16 (RX2)
// PZEM RX → ESP32 GPIO17 (TX2)
// PZEM VCC → 5V (from USB/power supply, NOT from same AC measurement circuit)
// PZEM GND → GND (common with ESP32 GND)
// Current Transformer (CT) Clamp installation:
// Open CT clamp, place around ONE wire (Live wire, not both L+N together)
// Close clamp, connect wires to PZEM CT terminals
// This is non-invasive - no need to cut wires!
// For whole-house monitoring:
// Install CT clamp on main service cable (BEFORE meter is illegal - AFTER meter is fine)
// Usually done at distribution box (DB board)
ESP32 PZEM-004T Code
#include <WiFi.h>
#include <PZEM004Tv30.h> // Install via Library Manager: "PZEM-004T-v30"
#include <PubSubClient.h>
#include <ArduinoJson.h>
// PZEM-004T on UART2 (GPIO16 RX, GPIO17 TX)
PZEM004Tv30 pzem(Serial2, 16, 17);
WiFiClient espClient;
PubSubClient mqtt(espClient);
struct EnergyData {
float voltage;
float current;
float power;
float energy;
float frequency;
float pf;
};
EnergyData energy;
void readEnergyData() {
energy.voltage = pzem.voltage();
energy.current = pzem.current();
energy.power = pzem.power();
energy.energy = pzem.energy();
energy.frequency = pzem.frequency();
energy.pf = pzem.pf();
Serial.printf("V: %.1fV | I: %.3fA | P: %.1fW | E: %.3fkWh | F: %.1fHz | PF: %.2f
",
energy.voltage, energy.current, energy.power,
energy.energy, energy.frequency, energy.pf);
}
void publishMQTT() {
StaticJsonDocument<256> doc;
doc["voltage"] = energy.voltage;
doc["current"] = energy.current;
doc["power"] = energy.power;
doc["energy"] = energy.energy;
doc["frequency"] = energy.frequency;
doc["pf"] = energy.pf;
// Calculate estimated cost (MSEDCL tier 1: ₹3.09/kWh, adjust for your state)
float costPerKWh = 3.09; // Maharashtra residential, 0-100 units slab
doc["est_monthly_cost"] = energy.energy * costPerKWh;
String payload;
serializeJson(doc, payload);
mqtt.publish("home/energy/main", payload.c_str());
}
void setup() {
Serial.begin(115200);
Serial2.begin(9600, SERIAL_8N1, 16, 17);
WiFi.begin("YourSSID", "YourPass");
while (WiFi.status() != WL_CONNECTED) delay(500);
mqtt.setServer("192.168.1.100", 1883);
mqtt.connect("energy-monitor");
Serial.println("Energy monitor ready");
}
void loop() {
mqtt.loop();
static unsigned long lastRead = 0;
if (millis() - lastRead > 5000) { // Read every 5 seconds
readEnergyData();
publishMQTT();
lastRead = millis();
}
}
Real-Time Web Dashboard
// Add web server to ESP32 for standalone dashboard:
#include <ESPAsyncWebServer.h>
AsyncWebServer webServer(80);
AsyncWebSocket ws("/ws");
// HTML dashboard with real-time updates via WebSocket:
const char dashboard[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<title>Home Energy Monitor</title>
<style>
body{background:#1a1a2e;color:#fff;font-family:Arial;text-align:center}
.card{background:#16213e;border-radius:12px;padding:20px;margin:10px;display:inline-block;min-width:140px}
.value{font-size:2em;color:#e63946;font-weight:bold}
.unit{font-size:0.8em;color:#aaa}
</style>
</head>
<body>
<h2>⚡ Home Energy Monitor</h2>
<div class="card"><div class="value" id="v">--</div><div class="unit">Volts</div></div>
<div class="card"><div class="value" id="i">--</div><div class="unit">Amps</div></div>
<div class="card"><div class="value" id="p">--</div><div class="unit">Watts</div></div>
<div class="card"><div class="value" id="e">--</div><div class="unit">kWh Today</div></div>
<script>
const ws = new WebSocket('ws://' + location.hostname + '/ws');
ws.onmessage = e => {
const d = JSON.parse(e.data);
document.getElementById('v').textContent = d.v?.toFixed(1) || '--';
document.getElementById('i').textContent = d.i?.toFixed(2) || '--';
document.getElementById('p').textContent = d.p?.toFixed(0) || '--';
document.getElementById('e').textContent = d.e?.toFixed(3) || '--';
};
</script>
</body>
</html>
)rawliteral";
Indian Electricity Billing Calculator
// Calculate estimated Indian electricity bill by state tariff slabs
// Reference rates (2024, residential, update with current rates):
float calculateBillMSEDCL(float units) {
// Maharashtra MSEDCL residential slabs 2024:
if (units <= 100) return units * 3.09;
if (units <= 300) return 100*3.09 + (units-100)*7.39;
return 100*3.09 + 200*7.39 + (units-300)*11.80;
}
float calculateBillBESCOM(float units) {
// Karnataka BESCOM residential slabs 2024:
if (units <= 30) return 0; // Free first 30 units
if (units <= 100) return (units-30) * 4.35;
if (units <= 200) return 70*4.35 + (units-100)*7.00;
return 70*4.35 + 100*7.00 + (units-200)*8.15;
}
// In ESP32 loop, calculate estimated monthly bill:
float monthlyKWh = energy.energy; // kWh since last reset
float estimatedBill = calculateBillMSEDCL(monthlyKWh);
Serial.printf("Estimated bill: ₹%.2f
", estimatedBill);
Frequently Asked Questions
Is it legal to install PZEM-004T on the main electricity supply in India?
You may install monitoring equipment AFTER the electricity meter (on the load side). Installing anything before or on the meter requires permission from your electricity discom. CT clamps installed on cables within your DB board (consumer distribution board) after the meter are perfectly legal for monitoring purposes.
Can PZEM-004T monitor three-phase supply common in Indian homes?
Standard PZEM-004T monitors single-phase supply. For three-phase monitoring (common in larger Indian homes and commercial premises), use three separate PZEM-004T modules (one per phase), each with different ModBus addresses. ESP32 can communicate with all three on the same UART bus.
How accurate is PZEM-004T for Indian appliances with power factor issues?
PZEM-004T measures true power (watts) and apparent power (VA) separately — it correctly measures resistive loads (geysers, incandescent bulbs) and reactive loads (ACs, motors, inverters). For ceiling fans and older AC motors with capacitor issues, power factor reading can diagnose efficiency problems.
Where should PZEM-004T be installed in an Indian apartment?
Install inside or near the Distribution Board (DB/fuse box) of your apartment. Clamp the CT around the main incoming cable after the main MCB. Ensure the PZEM-004T enclosure is IP20 rated minimum (protected from accidental contact). Keep the 230V terminals fully enclosed and inaccessible.
Can I monitor solar panel output with PZEM-004T in India?
PZEM-004T measures AC power only. For DC solar panel monitoring (before the inverter), use a DC energy meter (like INA219 or PZEM-017 for DC). For monitoring solar inverter AC output (after inverter), PZEM-004T works perfectly and integrates with HA to show solar generation vs consumption.
Add comment