PZEM-016 with ESP32 and ESPHome: RS485 AC Energy Monitoring

Quick summary: The PZEM-016 measures single-phase AC voltage, current, active power, frequency, power factor and accumulated energy. Its external current transformer (CT) goes around one conductor; its mains measurement terminals sense the circuit voltage; and its RS485 port sends the results to an ESP32 running ESPHome. Use a 3.3 V-compatible RS485 transceiver between the meter and the ESP32. The ESP32 never connects directly to mains or to the CT secondary.

This guide concentrates on the PZEM-016 rather than repeating our SDM120/SDM630 Modbus energy-meter guide or the site’s PZEM-017 DC energy-monitoring guide. Despite the similar model numbers, the PZEM-016 is an AC meter using a current transformer, while the PZEM-017 is a DC meter using a resistive shunt. Their wiring and electrical use cases are not interchangeable.

What the PZEM-016 measures and where it fits

The commonly sold PZEM-016 100 A variant uses an external split-core CT to measure current and an AC connection to measure voltage. It reports instantaneous electrical quantities over Modbus RTU, and maintains an active-energy counter in the meter. Commonly published module specifications give an AC measurement range of approximately 80–260 V, current measurement up to 100 A with the supplied CT, and a 9600-baud RS485 interface. Check the label and documentation for your exact hardware revision and CT; do not assume every listing includes an identical sensor or has an equivalent installation rating.

The PZEM-016 suits local consumption monitoring on a suitable single-phase circuit, for example a workshop sub-circuit or a dedicated appliance feed. The energy counter can remain available after an ESP32 reboot because the meter, not Home Assistant, performs the accumulation. The module is not a substitute for a certified utility billing meter, an RCD, a circuit breaker, or a power-quality analyser. If you need import/export separation for solar or a bidirectional grid connection, verify that the particular meter and firmware provide it: the ordinary PZEM-016 active-energy value is not the same as separate import and export registers on an SDM meter.

Safety first: separate mains installation from low-voltage electronics

Mains voltage is present at the PZEM-016 AC terminals. Installation inside a distribution board or on a fixed wiring circuit should be designed and carried out by a qualified electrician, with the circuit isolated and verified dead before work. Use the appropriate protective device, enclosure, conductor rating, strain relief, segregation and terminal torque for the site. A breadboard, open sensor board or exposed AC screw terminal is not an acceptable permanent installation.

The clamp CT normally goes around one insulated live or neutral conductor associated with the voltage measurement, never around the entire cable containing both live and neutral. With both conductors in the same CT aperture, their magnetic fields approximately cancel and the measured current approaches zero. Follow the supplied CT/meter connection instructions; do not treat an arbitrary current transformer as a drop-in replacement. Never connect the CT secondary to an ESP32 ADC, and never experiment with CT wiring on an energised installation. Some CT types can develop hazardous voltages when their secondary circuit is opened under load.

Keep the ESP32 and its USB connector in a separate touch-safe low-voltage compartment or enclosure. A reputable, appropriately approved isolated low-voltage supply is preferable to trying to power the ESP32 from a meter accessory terminal. The PZEM-016 is commonly described as providing a limited 5 V output near the RS485 connector, but its current capacity and actual voltage depend on the module; it is not a guaranteed ESP32 supply. Do not connect that terminal directly to an ESP32 3.3 V input.

Parts and architecture

  • ESP32 development board with usable UART pins and reliable Wi-Fi reception at the installation location.
  • PZEM-016 RS485 AC meter with the CT that belongs to that model and installation rating.
  • 3.3 V-logic RS485-to-UART module, preferably isolated for a permanent installation near mains equipment.
  • Dedicated, properly isolated ESP32 power supply, protected enclosure and suitable twisted-pair RS485 cable.
  • Home Assistant with ESPHome Device Builder, or a standalone ESPHome installation.

The data path is AC circuit → PZEM-016 → RS485 differential pair → RS485-to-UART transceiver → ESP32 → Wi-Fi → Home Assistant. The current transformer measures circuit current, but the RS485 transceiver does not measure any electrical quantity itself: it converts signalling so the ESP32 can read Modbus registers from the meter.

Identify the correct terminals before wiring

ConnectionPurposeImportant note
PZEM AC voltage terminalsMeasure and power the meter from the specified AC circuitMains wiring: qualified installer; do not connect to ESP32 pins.
PZEM CT inputReceives signal from the supplied current transformerUse the correct CT and its specified connector.
PZEM A / BRS485 differential communicationConnect to the matching A / B transceiver terminals; labels can differ by manufacturer.
PZEM 5 V / GND accessory terminals, if presentModule-specific auxiliary interface power/referenceNot a 3.3 V UART connection; do not assume it can power the ESP32.
Transceiver DI → ESP32 TXModbus request transmissionUse a transceiver with 3.3 V-safe logic.
Transceiver RO → ESP32 RXModbus reply receptionA 5 V logic output is unsafe on an ordinary ESP32 GPIO.

A conventional four-wire RS485 transceiver has a differential bus side (A and B) and a UART logic side (DI, RO, DE, /RE). Some boards have automatic direction control and expose only TX/RX on their logic side. Others need a GPIO to switch between transmitting and receiving. The code below uses automatic direction control because its wiring is simpler; a separate configuration for a manual-direction transceiver appears later.

Wire an automatic-direction RS485 converter to the ESP32

PZEM-016 RS485 A  ------------ converter A (or D+)
PZEM-016 RS485 B  ------------ converter B (or D-)

3.3 V logic RS485 converter       ESP32 (example classic DevKit)
VCC / logic supply   ------------ board-appropriate 3V3 supply
GND                  ------------ GND
DI / TX-input        <------------ GPIO17 (ESP32 TX)
RO / RX-output       ------------> GPIO16 (ESP32 RX)

PZEM AC and CT wiring: installed independently by an electrician.
DO NOT connect PZEM AC, CT or a 5 V UART output to an ESP32 pin.

Check your converter’s pin labels: some “TXD/RXD” modules describe signals from the adapter’s perspective, and others from the microcontroller’s perspective. The reliable rule is ESP32 TX → transceiver transmit input and transceiver receive output → ESP32 RX. Confirm that the converter can operate at the voltage you provide. A generic MAX485 module sold as a 5 V board is not automatically 3.3 V-safe: its RO line may reach 5 V even if an ESP32 can drive its DI input.

On a short single-meter bus, start with A-to-A and B-to-B. If communication fails but the wiring, settings and power are correct, consult the transceiver documentation because different vendors sometimes invert A/B naming. Use twisted pair, avoid running unshielded communication wiring alongside mains conductors, and apply termination at the physical ends of a sufficiently long RS485 bus. Adding a 120 Ω resistor at every device can overload the bus; built-in termination and biasing need to be counted before adding more components.

Complete ESPHome configuration for one PZEM-016

This example uses an ordinary ESP32 DevKit, GPIO17 for transmit, GPIO16 for receive, a 3.3 V logic, auto-direction RS485 adapter, and one meter at Modbus address 1. The current ESPHome pzemac sensor platform is documented for PZEM-004T V3; the PZEM-016 uses the related Modbus register layout, but model/firmware revisions can differ. Treat this as a working starting point to validate against your actual PZEM-016, not a blanket promise that every board branded “PZEM-016” behaves identically.

esphome:
  name: pzem016-ac-monitor
  friendly_name: PZEM016 AC Monitor

esp32:
  board: esp32dev
  framework:
    type: esp-idf

logger:
  # Keep normal logs on the ESP32 USB serial port, not on RS485 GPIOs.

api:

ota:
  - platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

uart:
  id: pzem_uart
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600
  parity: NONE
  stop_bits: 1

modbus:
  id: pzem_bus
  uart_id: pzem_uart

sensor:
  - platform: pzemac
    id: pzem016_meter
    modbus_id: pzem_bus
    address: 1
    voltage:
      name: "AC Voltage"
    current:
      name: "AC Current"
    power:
      name: "AC Active Power"
    frequency:
      name: "AC Frequency"
    power_factor:
      name: "AC Power Factor"
    energy:
      id: pzem016_energy_wh
      name: "AC Energy Meter"
      # pzemac exposes the meter counter in Wh; the filter reports kWh.
      filters:
        - multiply: 0.001
      unit_of_measurement: kWh
      device_class: energy
      state_class: total_increasing
      accuracy_decimals: 3
    update_interval: 30s

Keep Wi-Fi credentials in ESPHome’s secrets.yaml; do not publish real SSIDs, passwords or API encryption keys. Compile and install the YAML from ESPHome, then inspect live logs. If your board uses a different ESP32 variant, change esp32.board and choose pins that exist on that variant. GPIO16/17 are convenient on many classic ESP32 DevKits but are not universal across every ESP32 module or board.

The energy component is exposed in watt-hours by pzemac; multiplying by 0.001 presents kilowatt-hours to Home Assistant. That conversion changes the reported unit, not the meter’s stored counter. Use state_class: total_increasing only when the upstream counter behaves as an increasing cumulative reading and resets are exceptional; if your device resets frequently or wraps its limited register, inspect long-term statistics for erroneous jumps.

If your RS485 board uses DE and /RE direction pins

Many basic MAX485-style adapters require the ESP32 to control the transmit-enable pins. On modules with separate DE (active high) and /RE (active low), joining them drives transmit when high and receive when low. Use a GPIO that is not a boot-strapping pin, and confirm the module’s logic-voltage requirements. A modern ESP32 UART driver can manage half-duplex direction via the uart.flow_control_pin setting; if your transceiver is auto-direction, omit this setting entirely.

# Replacement uart section for a manual-direction transceiver:
uart:
  id: pzem_uart
  tx_pin: GPIO17
  rx_pin: GPIO16
  flow_control_pin: GPIO23   # GPIO23 -> DE and /RE joined on converter
  baud_rate: 9600
  parity: NONE
  stop_bits: 1

The rest of the ESPHome configuration remains the same. Current ESPHome documentation permits flow_control_pin under uart: for ESP32 hardware control and also describes the Modbus-level flow-control option for converters that cannot use UART hardware flow control. Do not set both at once for the same adapter. If compilation reports that a key is unsupported, check the exact installed ESPHome version and component documentation rather than moving keys at random.

Power up, discover the device and verify each reading

Start with a previously installed, enclosed meter whose mains wiring and CT orientation have been checked. Power the low-voltage ESP32 supply, connect to ESPHome logs, then enable the metered circuit using the normal electrical installation controls. The first useful test is a nonzero, plausible voltage reading. Follow with a known appliance and compare the change in current and active power against an independently observed load or a suitable reference meter. Resistive loads often show power factor near 1; switch-mode supplies and motors can show lower power factor even when the sensor is operating correctly.

Do not use a live mains conductor as a convenient experimental “test wire”. If voltage appears but current and power remain near zero with a known load, ask the installer to verify which single conductor passes through the CT and that the CT matches the meter input. If current is plausible but power is unexpectedly low, check voltage/current are associated with the same circuit, then assess the actual load’s power factor. Frequency should be around the supply frequency, for example approximately 50 Hz on a nominal 50 Hz grid.

Power, apparent power and power factor: avoid misleading dashboards

The meter’s active power is reported in watts and is the quantity relevant to ordinary energy consumption. Apparent power, in volt-amperes, is roughly RMS voltage multiplied by RMS current for a single-phase circuit. Power factor is active power divided by apparent power under the applicable measurement conditions. Thus, a 230 V circuit drawing 2 A at power factor 0.6 has about 460 VA of apparent power but only about 276 W of active power. You should not calculate energy as volts × amps × hours unless the application genuinely supports that simplification.

The energy register already integrates active power over time. Prefer it to software integration when the meter’s cumulative counter is stable: it will continue accumulating while Wi-Fi or Home Assistant is offline, provided the PZEM-016 itself remains powered and measuring. Conversely, if the meter loses its AC supply, it cannot observe energy consumed during that downtime. A CT alone cannot make the module a fully non-invasive monitor because the meter still needs its specified AC voltage connection.

Using the reading in Home Assistant’s Energy dashboard

Once the ESPHome device is discovered in Home Assistant, open the PZEM016 device page and confirm that its voltage, current, power and energy entities have sensible units. Use the kWh cumulative energy entity—not a W power entity—as the consumption source in Home Assistant’s Energy dashboard. Depending on your configuration, it may be appropriate as an individual device or circuit monitor rather than the whole-house grid import sensor. A sub-circuit reading should not be entered as total home electricity if it excludes other loads.

Home Assistant’s Energy dashboard expects appropriate device class, state class and energy units; the example sets those explicitly on the converted kWh sensor. Statistics may not appear instantly after adding an entity. Give Home Assistant time to create statistical samples, then look for warnings in Developer Tools → Statistics if the sensor does not appear as a selectable source. If you change entity IDs or units after collecting history, check the effect on existing long-term statistics before deleting or renaming entities.

Daily and monthly energy without resetting the PZEM counter

Do not reset the meter’s lifetime energy register every midnight just to display daily usage. That destroys the long-term baseline and can confuse Home Assistant’s statistics. Instead use Home Assistant’s Utility Meter integration to derive daily and monthly counters from the same increasing kWh source. Set the source to the PZEM016 energy entity, select a daily cycle for one helper and a monthly cycle for the other, and leave the physical meter counter alone.

If the module’s firmware or register width eventually wraps its energy reading, Home Assistant may interpret the drop as a reset. Check the device’s actual counter maximum and behaviour before relying on it for multiyear accounting. If the module can be reset through a Modbus command, keep that action out of routine automations; reset intentionally only after recording the previous value and understanding the dashboard consequences.

Monitoring multiple PZEM-016 meters on a shared RS485 bus

RS485 can connect multiple devices along a properly wired bus, but Modbus RTU requires each meter to have a unique slave address. Many modules ship at address 1. Commission one meter at a time, change and verify its address using the device’s supported procedure or a suitable Modbus commissioning tool, and then connect it to the shared pair. Do not send a broadcast address-change command while multiple factory-default devices are on the same bus.

When sharing the UART, place another pzemac entry in the sensor: list with its own address and unique entity names. Use the same modbus_id for the shared bus; avoid creating one UART or Modbus hub per meter when all meters are on the same physical pair. Polling several meters at 30–60-second intervals is usually adequate for dashboards. Shorter periods increase bus traffic and can make weak wiring or marginal timing more visible.

# Example: second meter on the SAME existing pzem_bus;
# add as another item in the top-level sensor: list.
  - platform: pzemac
    id: pzem016_workshop
    modbus_id: pzem_bus
    address: 2
    voltage:
      name: "Workshop AC Voltage"
    current:
      name: "Workshop AC Current"
    power:
      name: "Workshop AC Power"
    energy:
      name: "Workshop Energy Wh"
    update_interval: 45s

Before relying on multiple sensors, verify that a load change in one circuit affects only the intended meter. Similar names, repeated slave addresses or incorrect CT placement can create convincing-looking but incorrect dashboards. On long runs, use a twisted-pair trunk rather than a star of long stubs, follow the transceiver manufacturer’s grounding and isolation guidance, and terminate the bus at its two physical ends where required.

Troubleshooting: no readings or Modbus timeouts

  • No values at all: Verify that the PZEM is powered from the appropriate AC source, that its communications side is functional, and that the ESP32/RS485 adapter have their correct low-voltage supplies. USB powering the ESP32 does not necessarily power the metering circuit.
  • Timeouts or CRC errors: Check UART settings (typically 9600 baud, no parity, one stop bit for many PZEM-016 modules), A/B polarity, unique slave address, termination and bus routing. Do not disable Modbus CRC checks to hide a wiring fault.
  • Transceiver transmits but never receives: Check TX/RX crossover and direction control. If DE is permanently asserted, the RS485 transceiver may prevent the meter’s response.
  • Voltage correct, current zero: Verify CT placement around one conductor, matching CT model and wiring, and whether the tested appliance is actually on that measured conductor. Have the installer recheck the CT on an isolated circuit.
  • Energy changes but Home Assistant shows no Energy source: Verify kWh units, energy device class, cumulative state class and the entity’s Statistics diagnostics. Confirm you did not select instantaneous watts instead.
  • ESP32 reboots whenever a load starts: Suspect power-supply quality, electrical interference, cable routing and enclosure design before assuming an ESPHome sensor bug.

A staged fault-finding method

Avoid changing five variables between tests. Confirm the low-voltage UART with one meter and short cable; verify the meter’s address and serial parameters; confirm the meter produces data; only then add long wiring, further meters and dashboard automations. If you have a USB-to-RS485 adapter, a suitable Modbus diagnostic utility can help determine whether the meter responds independently of the ESP32. Keep this commissioning equipment on the designated communication terminals—never on the PZEM’s AC or CT connections.

When values suddenly disappear after an ESPHome update, compare the active firmware YAML with the previously working file, including the board variant, UART pins and RS485 direction control. On ESP32, the ordinary USB serial console and a second UART can be used simultaneously with suitable GPIO assignments; avoid reusing the UART pins for a display, GPS or other component. If logs show normal Wi-Fi/API operation but repeated Modbus timeouts, concentrate on the local RS485 path rather than changing Home Assistant integrations.

PZEM-016 versus PZEM-004T, PZEM-017 and SDM meters

MeterWhat it measuresConnection to ESP32Best reason to select it
PZEM-016Single-phase AC; external CT; voltage, current, power, cumulative energyRS485 through a suitable transceiverAn AC monitoring point with a shared, addressable RS485 link.
PZEM-004T V3Single-phase AC; model-dependent CT or direct current pathUART-level Modbus via the correct interfaceA compact local AC meter where direct, short UART wiring suits the installation.
PZEM-017DC voltage/current/power/energy; external shuntRS485 through a suitable transceiverBattery or other appropriate DC circuits with correctly rated shunt.
SDM120/SDM630 ModbusSingle-/three-phase AC; model-dependent import/export and per-phase quantitiesRS485 through a suitable transceiverDIN-rail circuit or grid monitoring requiring the relevant meter-specific measurement set.

The correct choice depends on your circuit, required measurement direction, installation category, local electrical rules and enclosure. A sensor that can measure current is not automatically rated to be installed on a particular mains feeder. For grid import/export accounting, a meter exposing separate import and export registers is more informative than an unspecified cumulative PZEM-016 reading; for DC solar or battery measurements, use a DC meter and an appropriately rated shunt instead of the AC CT described here.

Sources and related guides

Bottom line: The PZEM-016 can supply local AC electrical measurements to Home Assistant through one ESP32 and an RS485 interface, while keeping cumulative energy in the meter itself. Get the mains installation and CT placement right first; then validate the UART voltage levels, Modbus address and counter units before building automations around the data.

Share your love