Skip to content
Free IDE

← Components

PZEM-004T v3.0 energy meter (10 A)

Energy meter for the mains (alternating current): it measures voltage, current, power, accumulated energy, frequency and power factor, and sends the values over the UART with the Modbus RTU protocol (9600 baud, 8N1). The program sends a request with a CRC and checks the CRC of the answer before using the numbers. On the bench the load (power, power factor, mains voltage) is chosen in the part panel. On the real module the mains side carries 127/220 V: only wire it with your teacher.

Pinout

PZEM-004T5VRXTXGNDload: 100 W5VRXTXGND
PinConnect toNote
5VVIN (5 V)the TTL connector is passive: it needs 5 V from outside
RXUART TX (e.g. TX2, GPIO17)the Modbus request comes in here
TXUART RX (e.g. RX2, GPIO16)the answer goes out here
GNDGNDwithout all 4 wires it does not communicate
FastMindLocal AI assistant

The AI that remembers your life and lives on your computer

  • Long-term memory with the source of every answer
  • Works offline: your data stays on your PC
  • Reads PDFs, slides, photos and meeting recordings
Download free for Windows

Essential plan free forever

MicroPython example

from machine import UART
import struct, time

# PZEM RX to TX2 (GPIO17), PZEM TX to RX2 (GPIO16), 5V to VIN, GND to GND
# timeout_char longer than the 26 ms of the 25-byte answer at 9600 baud
uart = UART(2, 9600, tx=17, rx=16, timeout=200, timeout_char=50)

def crc16(dados):
    crc = 0xFFFF
    for b in dados:
        crc ^= b
        for _ in range(8):
            crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1
    return crc

def ler_medidas(endereco=0x01):
    pedido = bytes([endereco, 0x04, 0, 0, 0, 10])  # 10 registers starting at 0x0000
    c = crc16(pedido)
    uart.write(pedido + bytes([c & 0xFF, c >> 8]))  # CRC: low byte first
    r = uart.read(25)
    if r is None or len(r) != 25 or crc16(r[:-2]) != r[-2] | r[-1] << 8:
        return None  # no answer or wrong CRC: drop it
    v = struct.unpack('>10H', r[3:23])
    return {'V': v[0] / 10, 'A': (v[1] | v[2] << 16) / 1000, 'W': (v[3] | v[4] << 16) / 10,
            'Wh': v[5] | v[6] << 16, 'Hz': v[7] / 10, 'FP': v[8] / 100}

while True:
    print(ler_medidas())
    time.sleep(2)

Specifications

ItemValueSource
Communication9600 baud, 8 bits, no parity, 1 stop bit; Modbus RTUManual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
TTL connector5V, RX, TX, GND; passive, needs 5 V from outside; all 4 connectedManual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
Addresses0x01–0xF7; 0x00 = broadcast (no answer); 0xF8 = general (a single device on the line)Manual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
Functions0x04 reads measurements, 0x03 reads parameters, 0x06 writes a parameter, 0x42 resets the energy, 0x41 calibrationManual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
Measurement registers (0x04)0x0000 voltage (0.1 V); 0x0001–0x0002 current (1 mA); 0x0003–0x0004 power (0.1 W); 0x0005–0x0006 energy (1 Wh); 0x0007 frequency (0.1 Hz); 0x0008 PF (0.01); 0x0009 alarm (0xFFFF)Manual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
Parameters (0x03/0x06)0x0001 alarm threshold (1 W); 0x0002 address (0x0001–0x00F7)Manual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
Ranges (10 A model)80–260 V; 0–10 A (measures from 0.01 A); 0–2.3 kW (from 0.4 W); 45–65 Hz; PF 0.00–1.00; 0–9999.99 kWhManual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
Errorsfunction + 0x80 and the code: 0x01 function, 0x02 address, 0x03 data, 0x04 slaveManual "PZEM-004T V3.0 User Manual" (AC communication module), narodmon.com/img/sens/PZEM-004Tv3.pdf
CRCCRC-16, polynomial 0xA001, low byte firstMODBUS over Serial Line V1.02 (modbus.org), sections 2.5.1 and 6.2.2; github.com/mandulaj/PZEM-004T-v30 (src/PZEM004Tv30.cpp, setCRC) — Under review: the manual tables put the high byte first
Reading the answer25 bytes take ≈ 26 ms at 9600 baud: use a timeout_char above that (e.g. 50 ms)MicroPython v1.29.0: ports/esp32/machine_uart.c (mp_machine_uart_read)
Response and update timenot in the manual; here it answers 3.5 characters after the end of the request and measures right awayMODBUS over Serial Line V1.02 (modbus.org), sections 2.5.1 and 6.2.2 — Under review: measure on the module
Factory address and threshold0x01 and 2300 W in the simulatorPyPlaca component catalog — Under review: the manual does not give the factory values
Faults on the benchno answer, invalid CRC, answer from another address: they simulate the line, not the devicePyPlaca component catalog

Values marked "Under review" will still be checked against the parts in the lab.

FastTeacherFor teachers

From the syllabus to a planned semester

  • Teaching plan and calendar built automatically
  • Class diary ready to paste into SIGA
  • Slides and exercise lists with answer keys
Meet FastTeacher

Free Community edition · Windows

FastMindLocal AI assistant

The AI that remembers your life and lives on your computer

  • Long-term memory with the source of every answer
  • Works offline: your data stays on your PC
  • Reads PDFs, slides, photos and meeting recordings
Download free for Windows

Essential plan free forever

FastTeacherFor teachers

From the syllabus to a planned semester

  • Teaching plan and calendar built automatically
  • Class diary ready to paste into SIGA
  • Slides and exercise lists with answer keys
Meet FastTeacher

Free Community edition · Windows