PZEM 004T V4.0 - Esphome Not able to read simultaneously from all 3 PZEM's

When connected together I’am not able to read from PZEM’s

Have assigned unique ID’s for all 3 PZEMs
Individually, I’m able to read them in their respective IDs
But when connected altogether, they are not working
One observation from PZEM LED status is that all PZEMs transmit together, same with receiving too

Hardware Setup

Wemos D1 Mini
PZEMs are directly connected to TX-RX (parallel connection with no pullup resistor or diode)

Any support will be invaluable :slight_smile:

Full code below

substitutions:
  devicename: 3phase-power-monitor
  friendly_name: Power Monitor

esphome:
  name: ${devicename}
  friendly_name: ${friendly_name}
  name_add_mac_suffix: false
  project:
    name: esphome.web
    version: "1.0"

esp8266:
  board: esp01_1m

logger:
  baud_rate: 0        # free UART for PZEM
  level: DEBUG        # change to INFO later


wifi:
  ssid: !secret wifi_id
  password: !secret wifi_pw

  ap:
    ssid: $devicename
    password: "1122334455"

ota:
  - platform: esphome

api:

web_server:
  port: 80
  version: 3

dashboard_import:
  package_import_url: github://esphome/example-configs/esphome-web/esp8266.yaml@main
  import_full_config: true

time:
  - platform: homeassistant
    id: homeassistant_time

uart:
  tx_pin: GPIO1
  rx_pin: GPIO3
  baud_rate: 9600
  stop_bits: 1
  parity: NONE

# Increased modbus timing to prevent bus contention
modbus:
  id: mod_bus_pzem
  send_wait_time: 2000ms  # 2 seconds between requests

binary_sensor:
  - platform: status
    name: "${devicename} Status"

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${devicename} IP Address"
    ssid:
      name: "${devicename} Connected SSID"
    mac_address:
      name: "${devicename} MAC Address"

sensor:
  - platform: wifi_signal
    name: "${devicename} WiFi Signal"
    update_interval: 60s

  - platform: uptime
    name: "${devicename} Uptime"

  # --------- PHASE L1 ----------
  - platform: pzemac
    id: pzemac1
    address: 1
    modbus_id: mod_bus_pzem
    update_interval: 90s  # Long interval, controlled by automation

    current:
      name: "Current L1"
      id: current_l1

    voltage:
      name: "Voltage L1"
      id: voltage_l1

    energy:
      name: "Energy L1"
      id: energy_l1
      device_class: energy
      state_class: total_increasing
      unit_of_measurement: "Wh"

    power:
      name: "Power L1"
      id: power_l1
      device_class: power
      state_class: measurement

    frequency:
      name: "Frequency L1"
      id: frequency_l1

    power_factor:
      name: "Power Factor L1"
      id: pf_l1

  # --------- PHASE L2 ----------
  - platform: pzemac
    id: pzemac2
    address: 2
    modbus_id: mod_bus_pzem
    update_interval: 90s

    current:
      name: "Current L2"
      id: current_l2

    voltage:
      name: "Voltage L2"
      id: voltage_l2

    energy:
      name: "Energy L2"
      id: energy_l2
      device_class: energy
      state_class: total_increasing
      unit_of_measurement: "Wh"

    power:
      name: "Power L2"
      id: power_l2
      device_class: power
      state_class: measurement

    frequency:
      name: "Frequency L2"
      id: frequency_l2

    power_factor:
      name: "Power Factor L2"
      id: pf_l2

  # --------- PHASE L3 ----------
  - platform: pzemac
    id: pzemac3
    address: 3
    modbus_id: mod_bus_pzem
    update_interval: 90s

    current:
      name: "Current L3"
      id: current_l3

    voltage:
      name: "Voltage L3"
      id: voltage_l3

    energy:
      name: "Energy L3"
      id: energy_l3
      device_class: energy
      state_class: total_increasing
      unit_of_measurement: "Wh"

    power:
      name: "Power L3"
      id: power_l3
      device_class: power
      state_class: measurement

    frequency:
      name: "Frequency L3"
      id: frequency_l3

    power_factor:
      name: "Power Factor L3"
      id: pf_l3

  # --------- DAILY ENERGY PER PHASE (kWh) ----------
  - platform: total_daily_energy
    name: "Energy L1 Daily"
    power_id: power_l1
    id: energy_l1_daily
    unit_of_measurement: kWh
    accuracy_decimals: 3
    filters:
      - multiply: 0.001

  - platform: total_daily_energy
    name: "Energy L2 Daily"
    power_id: power_l2
    id: energy_l2_daily
    unit_of_measurement: kWh
    accuracy_decimals: 3
    filters:
      - multiply: 0.001

  - platform: total_daily_energy
    name: "Energy L3 Daily"
    power_id: power_l3
    id: energy_l3_daily
    unit_of_measurement: kWh
    accuracy_decimals: 3
    filters:
      - multiply: 0.001

  # --------- CALCULATED TOTAL SENSORS ----------
  - platform: template
    name: "Total Power"
    id: total_power
    device_class: power
    state_class: measurement
    unit_of_measurement: W
    accuracy_decimals: 1
    update_interval: 30s
    lambda: |-
      float p1 = id(power_l1).state;
      float p2 = id(power_l2).state;
      float p3 = id(power_l3).state;
      if (isnan(p1) || isnan(p2) || isnan(p3)) {
        return NAN;
      }
      return p1 + p2 + p3;

  - platform: template
    name: "Total Energy"
    id: total_energy
    device_class: energy
    state_class: total_increasing
    unit_of_measurement: kWh
    accuracy_decimals: 3
    update_interval: 30s
    lambda: |-
      float e1 = id(energy_l1).state;
      float e2 = id(energy_l2).state;
      float e3 = id(energy_l3).state;
      if (isnan(e1) || isnan(e2) || isnan(e3)) {
        return NAN;
      }
      float total_wh = e1 + e2 + e3;
      return total_wh * 0.001;

  - platform: template
    name: "Total Daily Energy"
    id: total_energy_daily
    device_class: energy
    state_class: total_increasing
    unit_of_measurement: kWh
    accuracy_decimals: 3
    update_interval: 30s
    lambda: |-
      float e1 = id(energy_l1_daily).state;
      float e2 = id(energy_l2_daily).state;
      float e3 = id(energy_l3_daily).state;
      if (isnan(e1) || isnan(e2) || isnan(e3)) {
        return NAN;
      }
      return e1 + e2 + e3;

button:
  - platform: restart
    name: "${devicename} Restart"

  - platform: template
    name: "Reset Energy L1"
    on_press:
      then:
        - pzemac.reset_energy: pzemac1

  - platform: template
    name: "Reset Energy L2"
    on_press:
      then:
        - pzemac.reset_energy: pzemac2

  - platform: template
    name: "Reset Energy L3"
    on_press:
      then:
        - pzemac.reset_energy: pzemac3

# SEQUENTIAL POLLING - Critical fix for bus contention
# Poll Phase 1 every 30 seconds
interval:
  - interval: 30s
    then:
      - component.update: pzemac1

# Poll Phase 2 every 30 seconds, but offset by 10 seconds
  - interval: 10s
    then:
      - delay: 10s
      - component.update: pzemac2

# Poll Phase 3 every 30 seconds, but offset by 20 seconds  
  - interval: 20s
    then:
      - delay: 20s
      - component.update: pzemac3

Normal uart line is not a bus like rs485 is.

1 Like

I was able to solve this by adding a 1N5819 diode to each TX line.

1 Like

Even 2x PZEM-004T 4.0 had this problem.

The issue is that when there are two or more devices, the signal cannot pull the level down close to GND.

Here is 1x 4.0,2x4.0,2x4.0 With 1N5819 Fix.

1 Like

yup! Thanks for this :slight_smile: