Assistance with Modbus and PZEM-004T

Hi All,

I’m trying to add a PZEM-004T with a direct USB Serial connection to my RPi using Modbus. I have been able to get entities to appear, however for some of my entities I keep getting unavailable and/or unknown errors.

I’ve also noticed that since adding in Modbus, my startup and shutdown/restart times are significantly longer, with 2021-08-17 08:10:04 ERROR (SyncWorker_6) [homeassistant.components.modbus.modbus] Pymodbus: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 2 bytes (0 received) scattered throughout my logs.

My existing Modbus code is:

  - name: Power_Monitoring
    type: serial
    baudrate: 9600
    bytesize: 8
    method: rtu
    parity: N
    port: /dev/ttyUSB0
    stopbits: 1
    retry_on_empty: true
    close_comm_on_error: false
    timeout: 10
    sensors:
    - name: PM_Voltage
      unit_of_measurement: V
      slave: 1
      address: 0x0000
      scale: 0.1
      offset: 0
      input_type: input
      precision: 1
#      data_type: float
    - name: PM_Current
      unit_of_measurement: A
      slave: 1
      count: 2
      scale: 0.001
      offset: 0
      precision: 1
      input_type: input
      address: 0x0002
 #     data_type: float16
 #     swap: word_byte
    - name: PM_power
      unit_of_measurement: W
      slave: 1
      count: 2
      scale: 0.001
      offset: 0
      precision: 1
      input_type: input
      address: 0x0003
    - name: PM_Frequency
      unit_of_measurement: Hz
      slave: 1
      address: 0x0007
      scale: 0.1
      offset: 0
      input_type: input
      precision: 1

Any assistance and/or guidance would be appreciated.

1 Like

Hello,
please note I’m new to HA but since my first successful test was with PZEM I try to share my experience.
I’ve found that count=2 is wrong, you need count=1.
Also im my config address are not in HEX.
Hope this can help.

I’m using:

modbus:
  - name: rs485usb
    type: serial
    method: rtu
    port: /dev/ttyUSB0
    baudrate: 9600
    stopbits: 1
    bytesize: 8
    parity: N
    timeout: 1

This is my configuration:

   sensors:
      - name: Tensione
        device_class: voltage
        unit_of_measurement: V
        slave: 1
        address: 0
        input_type: input
        scale: 0.1
        offset: 0
        precision: 1
        data_type: int16
      - name: Corrente
        unit_of_measurement: A
        device_class: current
        slave: 1
        address: 1
        input_type: input
        scale: 0.001
        offset: 0
        precision: 3
        data_type: int16
     - name: "Potenza Istantanea"
        unit_of_measurement: W
        device_class: power
        slave: 1
        address: 3
        input_type: input
        scale: 0.1
        offset: 0
        precision: 1
        data_type: int16
        device_class: power
      - name: FedeHome_Wh
        unit_of_measurement: Wh
        device_class: energy
        slave: 1
        address: 5
        input_type: input
        scale: 1
        offset: 0
        precision: 1
        data_type: int16
        device_class: energy
    - name: Frequenza
        unit_of_measurement: Hz
        slave: 1
        address: 7
        input_type: input
        scale: 0.1
        offset: 0
        precision: 1
        data_type: int16
      - name: Cosfi
        unit_of_measurement: Cosfi
        slave: 1
        address: 8
        input_type: input
        scale: 0.01
        offset: 0
        precision: 2
        data_type: int16
1 Like

Thanks for the help. I’ve made the changes you suggested and am still running into issues. I’ve tried with and without count: 2, and with and without any of the timeout clauses. My boot time is up over 5 minutes and my entities are pictured below. Some are still 0 or unavailable.

The clamp is connected to a wire that’s feeding my NAS/Pi etc, so I know that there should be data available.

Any ideas?

modbus:
  - name: Power_Monitoring
    type: serial
    baudrate: 9600
    bytesize: 8
    method: rtu
    parity: N
    port: /dev/ttyUSB0
    stopbits: 1
    retry_on_empty: true
    close_comm_on_error: false
    timeout: 10
    sensors:
    
    - name: PM_Voltage
      device_class: voltage
      unit_of_measurement: V
      slave: 1
      address: 0
      input_type: input
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
      
    - name: PM_Current
      unit_of_measurement: A
      device_class: current
      slave: 1
      address: 1
      input_type: input
      scale: 0.001
      offset: 0
      precision: 3
      data_type: int16
      count: 2
 
    - name: PM_power
      unit_of_measurement: W
      device_class: power
      slave: 1
      scale: 0.1
      offset: 0
      precision: 1
      input_type: input
      address: 3
      data_type: int16
      count: 2
      
    - name: PM_Consupmption_Wh
      unit_of_measurement: Wh
      device_class: energy
      slave: 1
      address: 5
      input_type: input
      scale: 1
      offset: 0
      precision: 1
      data_type: int16
      count: 2
      
    - name: PM_Frequency
      unit_of_measurement: Hz
      slave: 1
      address: 7
      input_type: input
      scale: 0.1
      offset: 0
      precision: 1
      data_type: int16
      
    - name: PM_Power Factor
      unit_of_measurement: Cosfi
      slave: 1
      address: 8
      input_type: input
      scale: 0.01
      offset: 0
      precision: 2
      data_type: int16

if you want to test first on a regular PI (not ha os), I found this one to work on the v3.0 usb ttl, to test (so independently of HA)
https://gist.github.com/bandaangosta/134c9d84ae9bd317297e96dcc0b9c860

Then the code from fvecchiatti works for HA (after moving the USB from one pi to the other) :slight_smile:

I actually used this code as a base for something I hacked together. I’m sending the data out over mqtt now without any issue.

yes I was thinking of doing the same initally, remote PI, Python mqtt, and the python above, can u still share yours?

tx

I also added the Riemann calculation from Integration - Riemann sum integral - Home Assistant
now…
strange things:

I have negative peaks in Watt’s … not sure why the sensor would give such big negative values (around -2500W a dozen of times a day (not night when all is quite). I think it happens when there is a higher load.

The Wh goes way too quick high, till 32K then -32K (int16 issue?)
Compared with the Riemann calc, completeley different (so I guess it’s just wrong)

The Riemann calculated numbers go down sometimes, but I guess this is due to the negative W’s above.

anyone else same ?
tx

image

i had the same issue as you all, then i figure out from the documentation: it’s supposed to be a uint16 as type, not int16 :slight_smile:

No more negative values, seems to work correctly, at least for me.

Hopes it’ll help

1 Like

Instruction how to use PZEM_004T_V3 without ESPHome (native Modbus and module Bluetooth TTL):
https://4pda-to.translate.goog/forum/index.php?showtopic=871505&st=33420&_x_tr_sl=ru&_x_tr_tl=en&_x_tr_hl=uk&_x_tr_pto=wapp#entry123597514

1 Like

Hello, I’m using PZEM-004T directly connected on my HA (Pi4).

Initially I had one PZEM connected on /dev/ttyUSB0 and it was working fine for months.

Recently I added a second PZEM on /dev/ttyUSB1 and after working well for some hours, both sensors became unavailable. I’m getting errors in the log: Task exception was never retrieved.

I removed the modbus entries for the 2nd PZEM (so that HA only polls the first one) but the errors continued.
It is only by removing physically the connection of the 2nd PZEM from the USB post that things get back fine for the first one.

Would there be a known limitation that only one USB can be used?

Instructions on how to use energy monitoring PZEM-004T v3 in the Home Assistant system with native Modbus

(without ESPHome)

  1. Home Assistant with Bluetooth support (can be external USB dongle), in Debian-like system installed “sudo apt -y install bluez”

  2. PZEM-004T v3 module itself

  3. Bluetooth module SPP, popular HC-05 and its cheaper analog JDY-33 it can SPP or BLE. Will be suitable and others similar in function. Of course you can still use a direct connection of any kind “/dev/ttyUSB0” UART - but directly connect to the high-voltage board single-board computer is strongly unwanted. It is necessary to use a wireless connection… And not necessarily Bluetooth connection (it has a range enough to swear by) can be a variant of a pair of modules transceiver-receiver (but in this case, one of the modules must be directly connected to the single-board via UART, and the second to PZEM-004T beforehand configuring and checking the two modules to work in tandem) at which the range will be longer, such as HC-12 (it is on the 433Mhz frequency of radio) it has a range of about 600-700 meters in a clear field at a standard speed of 9600 bits.

  4. Create a dialout group and add your Home Assistant user to this group:

sudo newgrp dialout
sudo gpasswd --add <user> dialout
sudo usermod -a -G dialout <user>

(note the <user> - this should be your user)

  1. If we use the HC-05 module, we only have access to the SPP protocol, if we use the JDY-33 module, we have the option to use JDY-33-SPP (Bluetooth 3.0) or JDY-33-BLE (Bluetooth 4.0+), let’s consider the universal SPP protocol first.
Instruction SPP

5.1. For Bluetooth SPP module to automatically connect in Armbian you need to connect to it via bluetoothctl and make it trusted:

sudo bluetoothctl
     scan on
     <During scanning, find the mac address opposite the name HC-05 or JDY-33-SPP.>
     pair <mac>
     trust <mac>
     connect <mac>
     exit

(pay attention to <mac> - this should be the mac address of the detected device, in the process when you make pair - it will ask for pin code, usually by default it is “1234”)

5.2. Next, you need to make a bind so that your /dev/rfcomm0 is detected in the devfs tree:

sudo rfcomm bind rfcomm0 <mac>

(pay attention to <mac> - this should be the mac address of the same SPP device)

5.3. Now it should be tested as a normal UART for example echo commands, does it work as it should or not.
To do this, short TX and RX and open two consoles in parallel in Armbian, one with the command “cat /dev/rfcomm0” running, and the other with the command “echo 12345 > /dev/rfcomm0” if you see the line “12345” in the first console, then the connection works.
If we don’t see anything, then you need to search for the problem and you will not be able to continue point by point.

5.4. After a successful connection check, we need to add the previous command to the /etc/rc.local file, so that when we boot our Bluetooth-UART module will bind automatically after a boot:

sudo nano /etc/rc.local

(here I use nano to edit this file, you can use whatever editor you prefer)

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

rfcomm bind rfcomm0 <mac>

exit 0

(pay attention to <mac> - this should be the mac address of the same SPP device)

5.5. To avoid doing a reboot on running single-board you can start restarting the rc.local boot service with the command:

sudo systemctl restart rc-local.service

Alternative option instead of SPP use BLE on the example of “JDY-33-BLE” (BT 4.0+) - in my case it reduces power consumption and is slightly more stable than compared to JDY-33-SPP (because SPP uses an outdated version of BT 3.0), but the range of BLE is poor:

Instruction BLE

5.1. If you have already bound JDY-33-SPP into the system, JDY-33-BLE will not appear until you unbind and remove SPP by bluetoothctl “remove ” also you need to do “rfcomm unbind rfcomm0” .
For Linux there is a Python utility to create a Serial port via the BLE service: GitHub - Jakeler/ble-serial: "RFCOMM for BLE" a UART over Bluetooth low energy (4+) bridge for Linux, Mac and Windows.
Install ble-serial:

sudo python3 -m pip install ble-serial

(Note that I’m doing it from sudo because I’ll be linking the port to the /dev/* folder - which is where the Home Assistant Supervisor container will see the device. If you still want to link the port from your user, then first of all: install ble-serial without sudo as your user, and secondly: link the port to a folder within Home Assistant’s visibility area, and your user (non-sudo) must have full access to this folder)

5.2. Run a scan to find the mac address of our BLE:

sudo ble-scan

In my case, the output is:

deoptim@homeassistant:~$ sudo ble-scan
Started general BLE scan

28:82:3F:XX:XX:XX (rssi=-91): JDY-33-BLE
...
...

Finished general BLE scan
deoptim@homeassistant:~$

5.3. Now let’s check what services are available to us:

sudo ble-scan -d 28:82:3F:XX:XX:XX

In my case, the output is:

deoptim@homeassistant:~$ sudo ble-scan -d 28:82:3F:XX:XX:XX
Started general BLE scan

28:82:3F:XX:XX:XX (rssi=-93): JDY-33-BLE
...
...
...

Finished general BLE scan

Started deep scan of 28:82:3F:XX:XX:XX

Found device 28:82:3F:XX:XX:XX: JDY-33-BLE (out of 1)
SERVICE 0000ffe0-0000-1000-8000-00805f9b34fb (Handle: 14): Vendor specific
     CHARACTERISTIC 0000ffe2-0000-1000-8000-00805f9b34fb (Handle: 18): Vendor specific ['write-without-response', 'write']
     CHARACTERISTIC 0000ffe1-0000-1000-8000-00805f9b34fb (Handle: 15): Vendor specific ['write-without-response', 'write', 'notify']
         DESCRIPTOR 00002902-0000-1000-8000-00805f9b34fb (Handle: 17): Client Characteristic Configuration
SERVICE 00001801-0000-1000-8000-00805f9b34fb (Handle: 10): Generic Attribute Profile
     CHARACTERISTIC 00002a05-0000-1000-8000-00805f9b34fb (Handle: 11): Service Changed ['indicate']
         DESCRIPTOR 00002902-0000-1000-8000-00805f9b34fb (Handle: 13): Client Characteristic Configuration

Completed deep scan of 28:82:3F:XX:XX:XX
deoptim@homeassistant:~$

5.4. We need the service 0000ffe1-0000-1000-8000-00805f9b34fb for the serial you need to set manually:

sudo ble-serial -d 28:82:3F:XX:XX:XX -w 0000ffe1-0000-1000-8000-00805f9b34fb -r 0000ffe1-0000-1000-8000-00805f9b34fb -p /dev/ttyBLE

(note that I am linking the port to /dev/* instead of the default /tmp/* because Home Assistant container does not see our system /tmp/* and will not be able to use the port, which is why we use ble-serial as root (sudo). If you want to link the port from your user, then first of all: install ble-serial without sudo as your user, and secondly: link the port to a folder within Home Assistant’s visibility area, and your user (non-sudo) must have full access to this folder)

In my case, the output is:

deoptim@homeassistant:~$ sudo ble-serial -d 28:82:3F:XX:XX:XX -w 0000ffe1-0000-1000-8000-00805f9b34fb -r 0000ffe1-0000-1000-8000-00805f9b34fb -p /dev/ttyBLE
10:35:04.590 | INFO | linux_pty.py: Port endpoint created on /dev/ttyBLE -> /dev/pts/2
10:35:04.592 | INFO | ble_interface.py: Receiver set up
10:35:04.952 | INFO | ble_interface.py: Trying to connect with 28:82:3F:XX:XX:XX: JDY-33-BLE
10:35:07.557 | INFO | ble_interface.py: Device 28:82:3F:XX:XX:XX connected
10:35:07.559 | INFO | ble_interface.py: Found write characteristic 0000ffe1-0000-1000-8000-00805f9b34fb (H. 15)
10:35:07.560 | INFO | ble_interface.py: Found notify characteristic 0000ffe1-0000-1000-8000-00805f9b34fb (H. 15)
10:35:08.249 | INFO | main.py: Running main loop!

Voila, so now we check the port to see if it works - it should work.

5.5. To automatically up a BLE port at bootime, you need:

  1. Create a folder as root and navigate to it:
sudo mkdir /etc/ble-serial
cd /etc/ble-serial
  1. Download the missing scripts to the /etc/ble-serial/ folder:
sudo wget https://github.com/Jakeler/ble-serial/raw/main/helper/autoconnect.ini
sudo wget https://github.com/Jakeler/ble-serial/raw/main/helper/ble-autoconnect.py
  1. Edit /etc/ble-serial/autoconnect.ini for our device:
### Example config file

# Values from the DEFAULT section are applied to all devices, other sections with the
# MAC address can override config elements for the specific device.
# Only devices that have a section are considered by the auto detection mechanism, but
# it can be empty to run with pure defaults.

# Key names are identical to the long parameters without dashes:
# specify "mtu = 20" to get "--mtu 20", this works also with flags like "--verbose".
# The only special key is "executable", which specifies the program that is started.

[DEFAULT]
executable = ble-serial
timeout = 10
mtu = 20
port = /dev/ttyBLE

[28:82:3F:XX:XX:XX]
dev = 28:82:3F:XX:XX:XX
address-type = public
port = /dev/ttyBLE
w = 0000ffe1-0000-1000-8000-00805f9b34fb
r = 0000ffe1-0000-1000-8000-00805f9b34fb

(Saving)

  1. Create a system service ble-autoconnect.service:
sudo nano /etc/systemd/system/ble-autoconnect.service

(I use the nano editor, you can use one that is convenient for you)

Contents of ble-autoconnect.service:

[Unit]
Description=Automatically connect to available bluettooth devices from config

[Service]
WorkingDirectory=/etc/ble-serial
ExecStart=/usr/bin/python3 ble-autoconnect.py

[Install]
WantedBy=multi-user.target
  1. Activate and start the system service ble-autoconnect.service:
sudo systemctl enable ble-autoconnect.service
sudo systemctl start ble-autoconnect.service

(to check the status, use the command “sudo systemctl status ble-autoconnect.service”. If port successful brings-up, the last line in the log will be “main.py: Running main loop!” otherwise it will try to connect in a loop).

  1. Next you can connect PZEM-004T with HC-05 (or similar), don’t forget about individual power supply 5V (or 3.3V depending on which SPP you have).
Now what my configuration.yaml looks like
modbus:
  #https://community.home-assistant.io/t/assistance-with-modbus-and-pzem-004t/330723/3
  - name: PZEM_004T_V3
    type: serial
    method: rtu
    port: /dev/rfcomm0
    baudrate: 9600
    stopbits: 1
    bytesize: 8
    parity: N
    sensors:
      - name: "PZEM 004T Voltage [V]"
        unique_id: pzem_004t_voltage_v
        device_class: voltage
        unit_of_measurement: V
        state_class: measurement
        slave: 1
        address: 0
        input_type: input
        scale: 0.1
        offset: 0
        precision: 1
        data_type: uint16
      - name: "PZEM 004T Current [A]"
        unique_id: pzem_004t_current_a
        unit_of_measurement: A
        state_class: measurement
        device_class: current
        slave: 1
        address: 1
        input_type: input
        scale: 0.001
        offset: 0
        precision: 3
        data_type: uint32
        swap: word
      - name: "PZEM 004T Power [W]"
        unique_id: pzem_004t_power_w
        unit_of_measurement: W
        state_class: measurement
        device_class: power
        slave: 1
        address: 3
        input_type: input
        scale: 0.1
        offset: 0
        precision: 1
        data_type: uint32
        swap: word
      - name: "PZEM 004T Energy [Wh]"
        unique_id: pzem_004t_energy_wh
        unit_of_measurement: Wh
        state_class: total_increasing
        device_class: energy
        slave: 1
        address: 5
        input_type: input
        scale: 1
        offset: 0
        precision: 0
        data_type: uint32
        swap: word
      - name: "PZEM 004T Frequency [Hz]"
        unique_id: pzem_004t_frequency_hz
        unit_of_measurement: Hz
        state_class: measurement
        slave: 1
        address: 7
        input_type: input
        scale: 0.1
        offset: 0
        precision: 1
        data_type: uint16
      - name: "PZEM 004T Power factor [PF]"
        unique_id: pzem_004t_power_factor_pf
        unit_of_measurement: PF
        state_class: measurement
        slave: 1
        address: 8
        input_type: input
        scale: 0.01
        offset: 0
        precision: 2
        data_type: uint16
      - name: "PZEM 004T Power Alarm Value [W]"
        unique_id: pzem_004t_power_alarm_value_w
        unit_of_measurement: W
        slave: 1
        address: 1
        #Input Registers - Function Code 0x04
        #Holding Registers - Function Code 0x03 & 0x10
        input_type: holding
        scale: 1
        offset: 0
        precision: 0
        data_type: uint16
    binary_sensors:
      - name: "PZEM 004T Power Alarm Status"
        unique_id: pzem_004t_power_alarm_status
        slave: 1
        address: 9
        input_type: input

template:
#https://community.home-assistant.io/t/use-last-value-instead-of-unknown/614331/5
  - trigger:
      - platform: state
        entity_id: sensor.pzem_004t_energy_wh
        not_to:
          - unknown
          - unavailable
    sensor:
      - name: PZEM 004t Energy Wh Buffer
        state: '{{ trigger.to_state.state }}'
        device_class: energy
        unit_of_measurement: Wh
        state_class: total_increasing
        unique_id: pzem_004t_energy_wh_buffer

input_number:
  pzem_004t_box1:
    name: "PZEM 004T Power Alarm Threshold [W]"
    initial: 1
    min: 1
    #For PZEM-004T-10A use max value 2300 W,
    #for PZEM-004T-100A use max value 23000 W
    max: 23000
    step: 1
    mode: box
    unit_of_measurement: W

input_button:
  pzem_004t_button0:
    name: "PZEM 004T Set Power Alarm"
    icon: mdi:flash-triangle
  pzem_004t_button1:
    name: "PZEM 004T Reset Energy Consumption"
    icon: mdi:reload

switch:
  - platform: template
    switches:
      pzem_004t_turn_modbus:
        unique_id: pzem_004t_turn_modbus
        friendly_name: "PZEM 004T Turn Modbus"
        value_template: >-
          {% if states('sensor.pzem_004t_voltage_v')  != 'unavailable' %}
            on
          {% else %}
            off
          {% endif %}
        turn_on:
          - service: modbus.restart
            data:
              hub: PZEM_004T_V3
        turn_off:
          - service: modbus.stop
            data:
              hub: PZEM_004T_V3

homeassistant:
  name: Home
  unit_system: metric
  customize:
     sensor.pzem_004t_energy_wh:
       last_reset: '1970-01-01T00:00:00+00:00'
     sensor.pzem_004t_frequency_hz:
       icon: mdi:current-ac
     sensor.pzem_004t_power_factor_pf:
       icon: mdi:angle-acute
     sensor.pzem_004t_power_alarm_value_w:
       icon: mdi:meter-electric

shell_command:
  #https://community.home-assistant.io/t/how-to-use-pzem004t-energy-monitor-with-esphome/107083/186
  send_reset_to_pzem_004t: echo -en '\x01\x42\x80\x11' > /dev/rfcomm0

(note that I have not fully posted my configuration file, but only the main parts related to modbus, template and all buttons(input_button), input_number, switch, shell_command) that are involved in this configuration. Also in case you will use ble-serial change in modbus /dev/rfcomm0 → /dev/ttyBLE and don’t forget to change for shell_command also. Pay attention to another sensor “PZEM 004t Energy Wh Buffer” (template) - it duplicates the modbus sensor pzem_004t_energy_wh but keeps the last value (even after reboot) without unknown/unavailable states - in some cases it is necessary, for example if the connection with the energy monitor over SPP/BLE/Radio is lost, the second sensor “PZEM 004t Energy Wh Buffer” will not distort the Utility Meter counting statistics, this sensor can be useful in place of the modbus energy sensor).

Now what my automations.yaml configuration looks like
- id: reset_pzem_004t_on_button
  alias: Reset Energy Consumption on Button
  description: ''
  trigger:
  - platform: state
    entity_id: input_button.pzem_004t_button1
  condition: []
  action:
  - service: automation.trigger
    data:
      skip_condition: true
    target:
      entity_id: automation.reset_energy_consumption_every_month
  initial_state: 'on'
- id: reset_pzem_004t_every_month
  alias: Reset Energy Consumption every Month
  description: ''
  trigger:
  - platform: time
    at: 00:00:01
  - platform: homeassistant
    event: start
  - platform: time_pattern
    hours: "1"
  condition:
  - condition: template
    value_template: "{% if now().day == 1 -%}\n  {{ now() - state_attr('automation.reset_energy_consumption_every_month',
      'last_triggered') > timedelta(hours=24) }}\n{%- else -%}\n  False\n{%- endif
      %}"
  action:
  - service: shell_command.send_reset_to_pzem_004t
    data: {}
  mode: single
- id: set_power_alarm_of_pzem_004t_on_button
  alias: Set Power Alarm on Button
  description: ''
  trigger:
  - platform: state
    entity_id:
    - input_button.pzem_004t_button0
  condition: []
  action:
  - service: modbus.write_register
    data:
      address: 1
      hub: PZEM_004T_V3
      value: '{{ states(''input_number.pzem_004t_box1'') | round(0) }}'
      slave: 1
  mode: single

(here I will explain, in addition to automating the reset the collected energy statistics over input button, the reset is done every first day of the new month at 00:00:01 (first second of the day), also if the reset did not happen for some reason (let’s say Home Assistant was not loaded at that moment or other reasons), the automation will try to reset the collected energy statistics every hour during the first day of the month (24 hours) or after Home Assistant is loaded)

Connection of several PZEM-004T's to one Modbus bus (e.g. for monitoring a three-phase grid)

Important! You can skip these instructions if you use a separate Bluetooth-SPP (or any other module) for each PZEM-004T board.
If you want to use one Modbus module for all PZEM-004T boards (e.g. transceiver-receiver module option where we have only one UART), you need to assign a different address for each PZEM-004T in advance.
Assign an address for each PZEM-004T is quite simple, it can be done through the Home Assistant interface itself, connecting first to each board of the energy monitor separately (it is not necessary to connect to the electricity panel while it can be done at least on the table and indicators when connected shows zero, but the some data must be going - that will indicate communication between PZEM-004T <=> Home Assistant). For one of the PZEM-004T’s we will leave the address unchanged “1” (default), we will configure only the other two PZEM’s.

  1. Connect the configurable PZEM-004T to the Home Assistant (make sure that any data comes from it all the time).
  2. open the tab “Developer tools” → “SERVICES”
  3. Select “Modbus: Write register” service
  4. Assign Address: 2 (this is the write register address, it should be unchanged for all configurable PZEM-004T)
  5. Assign Value: <new address of our current PZEM-004T> (it makes sense to number in order from 1 to …, the default address on all PZEM-004T’s is “1” and therefore they cannot work simultaneously all at once on the same Modbus).
  6. As the Hub name (Modbus hub name) select our Modbus connection for the specific connected PZEM-004T.
  7. Press “CALL SERVICE”

    After that, if everything is done correctly, we should stop updating data from PZEM-004T with settings “slave: 1”.
    To fix this, you need to copy all sensors in the Home Assistant configuration file in the Modbus group of the same PZEM-004T module and add new ones with “slave: 2” (or the address you specified). Accordingly, each sensor must have its own different name and unique ID (it must be renamed so that the sensors are not duplicated).
    If we have three PZEM-004T, then accordingly in configuration.yaml we should have in one common Modbus section (with the same name), three groups of identical copies of sensors but with different slave address, name and unique_id.
  8. Restart Home Assistant.
    After we have restarted Home Assistant we should receive data from the “slave: 2” (or your specified address) sensors, which indicates that the PZEM-004T is correctly configured and it should be disconnected, then connect the next one and so on…
    Important! After we have configured all PZEM-004T’s to a unique address, only then we can connect them in parallel to the same Modbus bus.

To reset the collected energy statistics for slave address “1” we know, but the other two PZEM-004T will have different slave address and now must be different shell_command, these commands (with their CRC sums) can be seen at this link (of course there are not values for all 247 possible addresses, but I think it is enough for most cases).

Dashboard


Photo



Source Link.

1 Like