RisalDash RisalDash

Project · Energy · Monitoring

See every watt your house is burning

The electricity bill tells you what you used; a live meter tells you when and on what. A PZEM-004T V3 with its 100 A CT clamp measures the whole house — voltage, current, power, accumulated kWh — and an ESP32 turns that into a dashboard with a running cost counter you check from the couch. No cloud, no subscription, your data stays home.

ProjectEnergyPZEM-004TCT clampESP32
ESP32 home energy monitor project: PZEM-004T, 100A CT clamp, kWh and cost live

How the measuring works

The PZEM-004T is a complete metering front-end: it samples mains voltage directly and current through the split-core CT clamp (clip it around the live wire — no rewiring), does the true-power maths on board, and hands the ESP clean numbers over UART. Your microcontroller never touches a dangerous analog signal — it just asks for V, A, W, kWh.

PZEM-004T wired to an ESP32 over UART: 5V, GND, TX to RX2, RX to TX2
Four wires on the low-voltage side: 5 V, GND, TX→RX2, RX→TX2. Built in BoardLab.

⚠ The mains-side rules

The measuring side of the PZEM connects to live AC — treat it with respect: everything lives in a closed junction box, the AC input goes through a 1 A fuse, all grounds are common, and the CT clamp's arrow (S1→S2) points with the current flow. Kill the breaker before touching anything on that side. If mains work isn't your thing, an electrician wires the box in ten minutes — the fun part is all on the low-voltage side.

The dashboard — tariff in, cost out

The pzem004t preset expands into the right widgets on its own; a number widget holds your tariff, and cost is one multiplication. The sketch below runs with no mains at allRisalFakePower cycles a realistic household load so you can build and demo the whole meter on your desk:

#include <RisalUI.h>
#include <RisalFake.h>               // fake household load — test with no mains at all

RisalUI dash("Energy");
RisalFakePower meter;
float volts = 230, amps = 0, watts = 0, kwh = 0, pf = 0.9f, freq = 50, cost = 0;
int tariff = 12;                     // cents per kWh — tune it live

void setup() {
  dash.layout("Live", RICON_FLASH);
  dash.sensor("pzem004t", &volts, &amps, &watts, &kwh);  // V gauge · A · W chart · kWh
  dash.metric("Power factor", &pf);
  dash.stat("Cost", &cost, "$").decimals(2);
  dash.number("Tariff c/kWh", &tariff, 1, 100, 1);
  dash.beginAP("RisalDash-Power", "12345678");
}

void loop() {
  dash.update();
  meter.update();                    // appliances switch on/off, kWh accumulates
  volts = meter.voltage(); amps = meter.current(); watts = meter.power();
  kwh = meter.energy(); pf = meter.powerFactor();
  cost = kwh * tariff / 100.0f;
}

When the box is wired, swap the fake for the real reader — same variables, dashboard unchanged:

// The real reader — PZEM-004T V3 on Serial2 (library: mandulaj/PZEM-004T-v30).
#include <PZEM004Tv30.h>
PZEM004Tv30 pzem(Serial2, 16, 17);   // RX2, TX2

float v = pzem.voltage();
if (!isnan(v)) {                     // NaN = no reading — keep the last good value
  volts = v;
  amps  = pzem.current();
  watts = pzem.power();
  kwh   = pzem.energy();
  pf    = pzem.pf();
}

Both halves ship as library examples: examples/04_Templates/PowerMeter (the meter) and EnergyMonitor (kWh + cost + breaker toggle). Publish to MQTT and it lands in Home Assistant's energy panel automatically.

Bill of materials

PartRole~Cost
ESP32 (or ESP8266)brain + Wi-Fi + dashboard$3–5
PZEM-004T V3 + 100 A CTthe actual meter$8–12
HLK-PM01 (AC→5 V)powers the ESP from the same box$2–3
Fuse 1 A + holderinput protection$1
Junction box + glandskeeps fingers out of the mains$3–5
LCD 16x2 I²C (optional)local readout on the box$2

Under $25 total — the commercial equivalents with an app start at several times that, and phone apps aside, this one's dashboard is served by the chip itself.

Build and tune the whole meter on a fake load — wire the box when it's ready.