Built-in project · ESP32 DevKit V1

ESP32 PZEM-004T energy monitor

A PZEM-004T v3.0 AC energy meter on the ESP32’s Serial2: voltage, current, power, kWh, frequency and power factor over Modbus. Drag the mains sliders on the meter. The whole build, an ESP32 DevKit and 1 more part, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

Teaching? Assign it to your class in one click.

Intermediate Runs in your browser. Free, and no account needed.

The parts retail for about $16. On Mokxi they're free.

ESP32 PZEM-004T energy monitor · ESP32 DevKit V1live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · ESP32 DevKit V1
// PZEM-004T energy monitor on an ESP32.
//
// The PZEM-004T v3.0 talks Modbus-RTU at 9600 baud. Here it is on Serial2,
// the ESP32's UART2: the meter's TX goes into GPIO 16 (RX2) and its RX comes
// from GPIO 17 (TX2), and the PZEM004Tv30 library does the Modbus. The meter's
// TTL side runs from 3.3 V, so its TX swings to the ESP32's own logic level.
//
// The meter's mains side is set on the part's sliders here. On the bench it
// is wired to live mains, which can kill: only a qualified person should
// connect one.

#include <PZEM004Tv30.h>

PZEM004Tv30 pzem(Serial2, 16, 17);  // RX2 (the meter's TX), TX2 (the meter's RX)

void setup() {
  Serial.begin(115200);
  Serial.println("PZEM-004T energy monitor");
  // The library skips any read in the first 200 ms after reset (it returns
  // 0), so give it that long before the first one.
  delay(250);
  Serial.print("Meter address: 0x");
  Serial.println(pzem.readAddress(), HEX);
}

void loop() {
  float voltage = pzem.voltage();
  float current = pzem.current();
  float power = pzem.power();
  float energy = pzem.energy();
  float frequency = pzem.frequency();
  float pf = pzem.pf();

  if (isnan(voltage) || isnan(current) || isnan(power) || isnan(energy) || isnan(frequency) || isnan(pf)) {
    Serial.println("Error reading the meter: is it on the mains?");
  } else {
    Serial.print("Voltage: ");   Serial.print(voltage);      Serial.println(" V");
    Serial.print("Current: ");   Serial.print(current);      Serial.println(" A");
    Serial.print("Power: ");     Serial.print(power);        Serial.println(" W");
    Serial.print("Energy: ");    Serial.print(energy, 3);    Serial.println(" kWh");
    Serial.print("Frequency: "); Serial.print(frequency, 1); Serial.println(" Hz");
    Serial.print("PF: ");        Serial.println(pf);
  }
  Serial.println();
  delay(2000);
}

Parts list

3 parts, plus the jumper wires. They retail for about $16; on Mokxi they're free.

How it is wired

4 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • ESP32 DevKit V1 pin TX2; AC energy meter, PZEM-004T v3.0 pin RX
  • ESP32 DevKit V1 pin RX2; AC energy meter, PZEM-004T v3.0 pin TX
  • 3.3 V: AC energy meter, PZEM-004T v3.0 pin 5V
  • Ground: AC energy meter, PZEM-004T v3.0 pin GND

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.