PZEM-004T energy meter
The PZEM-004T v3.0 AC energy meter: voltage, current, power, kWh, frequency and power factor over Modbus-RTU at 9600 baud.
Mains is dangerous. On the bench the meter's screw terminals are wired to live mains, which can kill and start fires. Only a qualified person should connect one, in a closed enclosure. In Mokxi the mains side is never wired: the sliders stand in for it, and nothing here says that real mains wiring is safe.
Aliases: PZEM-004T, PZEM004T, PZEM-004T-100A, AC energy meter, kWh meter, power meter.
Pins
The TTL header, behind the module's optocouplers:
| Pin | What it does |
|---|---|
5V |
Supply for the TTL side, 5 V (3.3 V works on the 3.3 V boards). |
RX |
Into the meter: wire it to the board's transmit pin. |
TX |
Out of the meter: wire it to the board's receive pin. |
GND |
Ground. |
Properties
| Property | Default | Meaning |
|---|---|---|
model |
100A | 100A, with the external current transformer, or 10A, with the internal shunt. |
voltage |
230 | The mains voltage at the start, 0 to 260 V. |
current |
2 | The load current at the start, in amps. |
pf |
0.9 | The load's power factor, 0 to 1. |
frequency |
50 | The mains frequency, 45 to 65 Hz. |
address |
1 | The meter's Modbus address, 1 to 247. |
While it runs
The four sliders are the mains: voltage, load current, power factor and frequency. The readout over the board is the energy counter in kWh.
What the model gets right
The registers. The ten input registers of the manual: voltage in 0.1 V, current in 0.001 A and power in 0.1 W (each a low word then a high word), energy in watt-hours, frequency in 0.1 Hz, power factor in 0.01 and the alarm status. Power is voltage times current times power factor, and the energy counter adds it up over simulated time: a 1 kW load counts 1 Wh every 3.6 seconds.
Modbus-RTU. Read input registers (0x04), read and write the holding registers (0x03 and 0x06: the power alarm threshold and the address), reset energy (0x42), the error answers (0x01 illegal function, 0x02 illegal address, 0x03 illegal data), the CRC-16/MODBUS sent low byte first, and the end of a frame at 3.5 characters of silence. A frame with a bad CRC gets no answer. The meter answers its own address and the general address 0xF8.
The starting current. Under 0.02 A on the 100 A model (0.01 A on the 10 A model) the current, power and power factor read 0, as the manual says.
No mains, no answer. The metering side is powered from the mains it measures, so below 80 V the meter does not answer, and the library returns NAN. That is why a real PZEM on the bench with only USB power reads NAN.
What it does not model
The meter's 0.5% error: the registers read the set values exactly. The answer starts 20 ms after the request, an assumption (the manual gives no figure). The alarm threshold starts at 23000 W and the address at 1, kept only while the simulation runs. Harmonics, the energy counter rolling over, and the calibration command's effect (it is answered and changes nothing) are not modeled.
Libraries
PZEM004Tv30 by Jakub Mandula (PZEM004Tv30.h): PZEM004Tv30 pzem(swSerial); then
pzem.voltage(), pzem.current(), pzem.power(), pzem.energy() (kWh),
pzem.frequency(), pzem.pf() and pzem.resetEnergy(). On a Mega,
PZEM004Tv30 pzem(Serial2);. On a classic ESP32 DevKit, PZEM004Tv30 pzem(Serial2, 16, 17); puts it on the real UART2, the meter's TX into GPIO 16 (RX2) and its RX from
GPIO 17 (TX2); run the meter's TTL side from 3V3 so its TX swings to the ESP32's
3.3 V. The ESP32 PZEM-004T energy monitor project is that circuit. The ESP32-S3, C3
and C6 boards' second UART is not wired to pins yet: use one of the others there.
ModbusMaster (ModbusMaster.h) reads it too: node.begin(1, swSerial); then
node.readInputRegisters(0x0000, 10).
Common mistakes
Swapping TX and RX. The meter's TX goes to the board's receive pin.
Reading faster than the library allows. PZEM004Tv30 reads the meter at most every 200 ms and hands back the same values in between, so six calls in a row are one read.
Expecting energy in watt-hours. The register counts watt-hours, and energy() divides
by 1000: it is kWh.
See it in action
PZEM-004T energy monitor prints the voltage, current, power, kWh, frequency and power factor of a 1 kW heater every two seconds. Open it at /templates.
The guide Arduino AC voltage and energy meter walks through it and the ZMPT101B.