-
-
Save bandaangosta/134c9d84ae9bd317297e96dcc0b9c860 to your computer and use it in GitHub Desktop.
# Reading PZEM-004t power sensor (new version v3.0) through Modbus-RTU protocol over TTL UART | |
# Run as: | |
# python3 pzem_004t.py | |
# To install dependencies: | |
# pip install modbus-tk | |
# pip install pyserial | |
import serial | |
import modbus_tk.defines as cst | |
from modbus_tk import modbus_rtu | |
# Connect to the sensor | |
sensor = serial.Serial( | |
port='/dev/PZEM_sensor', | |
baudrate=9600, | |
bytesize=8, | |
parity='N', | |
stopbits=1, | |
xonxoff=0 | |
) | |
master = modbus_rtu.RtuMaster(sensor) | |
master.set_timeout(2.0) | |
master.set_verbose(True) | |
data = master.execute(1, cst.READ_INPUT_REGISTERS, 0, 10) | |
voltage = data[0] / 10.0 # [V] | |
current = (data[1] + (data[2] << 16)) / 1000.0 # [A] | |
power = (data[3] + (data[4] << 16)) / 10.0 # [W] | |
energy = data[5] + (data[6] << 16) # [Wh] | |
frequency = data[7] / 10.0 # [Hz] | |
powerFactor = data[8] / 100.0 | |
alarm = data[9] # 0 = no alarm | |
print('Voltage [V]: ', voltage) | |
print('Current [A]: ', current) | |
print('Power [W]: ', power) # active power (V * I * power factor) | |
print('Energy [Wh]: ', energy) | |
print('Frequency [Hz]: ', frequency) | |
print('Power factor []: ', powerFactor) | |
print('Alarm : ', alarm) | |
# Changing power alarm value to 100 W | |
# master.execute(1, cst.WRITE_SINGLE_REGISTER, 1, output_value=100) | |
try: | |
master.close() | |
if sensor.is_open: | |
sensor.close() | |
except: | |
pass |
Hi, @donemuhendislik. I'm happy to hear this code is useful. I remember reading (it's been a couple of years) that this version of the module does not allow for resetting the energy counter, although supposedly the function code 0x42 ("power zero clearing") does the trick. I have never tried it. In general, there is no need to clear the energy count. Just read the value at the beginning and end of a certain period. The difference is the energy consumption of the period.
Thank you so much @bandaangosta for your reply. In deed, i was meaning that 0x42 and i was afraid of trying that data to pzem-004t for may i could break it. So, your solution is best. Saving the initial energy value and saving last one and difference is consumption 👍🏻 or calculating energy consumption with Wh formula that contains voltage and current. Again thank you so much for your helpful idea, i will use it 👍🏻
@bandaangosta Do you happen to have a TCP-version of this script? I'm now trying to access the data through a serial server running on an ESP-module. I can see from the log (of ESP Easy) that my script connects to the serial server, there's a single blink from a red LED on the PZEM-004t, but no data back :(
edit: Got as far as
import socket, sys
socket.setdefaulttimeout(5)
try:
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Failed to create socket')
sys.exit()
print('Socket Created')
ESP_IP= "*.*.*.*"
ESP_PORT = *
client.connect((ESP_IP,ESP_PORT))
print('Socket Connected to ' + ESP_IP )
try:
print("Send command")
client.send(bytes("\x01\x04\x00\x00\x00\x0A\x70\x0D", 'ascii'))
print("Receive data")
data = client.recv(1024)
print(data)
except socket.error as e:
print(e)
The PZEM-module reacts to this (Rx LED goes on, followed by Tx-LED), but not receiving data back.
@bandaangosta
"Regarding the first one, yes, this will work on Windows too"
Check, the script wouldn't run because I missed the bit that the AC-side had to be connected.
I have since then rewritten the script a little, I added for example
to find the comport assigned to the FTDI-cable with a certain serial number.
Also, the
bit is in an if-statement and won't run if comport var is empty, in that same if-statement there\s a variable called Run that is set true, default is false, so if there's no FTDI-cable detected (comport var is empty), then Run = false which will cause the main loop (while Run) to not run.
Inside the main (while) loop I've got
where
so it iterates/loops through the code accessing 5 modules, with try/except.
To do: Copy over some Home Assistant MQTT Auto Discovery code from my P1 DSMR smart meter script, I ended up spreading that one over several files and a whole bunch of functions.