To reduce our electricity bill, we have installed an island solar system, the central unit of which is a PowMr 5600W All In One hybrid inverter.
Der Original-Artikel kann auch hier auf Deutsch gefunden werden.
In order to make the best possible use of our solar system, we need to monitor the inverter. We need to know how much electricity the solar panel produces or how much energy the battery pack stores.
The PowMr 5600W All In One hybrid inverter also has a USB port, I connected a Raspberry Pi 3 model there, but a reasonably priced Raspberry pi zero can also be perfect for this task.
Using the Python script running on Raspberry Pi, we read the data from the inverter and add it to the mqtt server running on iobroker.
Like many similar inverters (e.g. ESUN, Deye, etc.), PowMr uses SRNE Modbus-RTU communication protocol.
To get python script to communicate with the inverter, we need the MinimalModbus library. This can easily be done with the python package installer. If not already installed, install the pip package installer and then install the MinimalModbus library.
sudo apt-get update
sudo apt-get install python3-pip
pip3 install -U minimalmodbus
To use minimalmodbus, we first import the library in our python script.
import minimalmodbus
Then we create an instance and specify the settings.
# minimalmodbus.Instrument(port, slave_address, mode)
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1, 'rtu')
instrument.serial.baudrate = 9600
instrument.serial.bytesize = 8
instrument.serial.parity = 'N'
instrument.serial.stoppbits = 1
instrument.serial.timeout = 0.2
instrument.mode = minimalmodbus.MODE_RTU
instrument.clear_buffers_before_each_transaction = True
The inverter registers can be read with the read_register function.
# read_register(registeraddress, number_of_decimals, functioncode)
battery_remaining = instrument.read_register(0x100, 1, 3)*10
To communicate with the mqtt server, we will use the paho-mqtt library. If you have not done so, install it as follows.
pip3 install paho-mqtt
We also import the paho-mqtt directory.
from paho.mqtt import client as mqtt_client
Enter connection details to the mqtt server.
broker = '192.168.1.180'
port = 1883
username = ''
password = ''
client_id = 'PowMr-client'
We need a function to connect to the mqtt server.
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to ioBroker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
You also need a function to publish MQTT messages.
def publish(client, topic, payload):
result = client.publish(topic, payload)
status = result[0]
if status == 0:
print(f"Send `{payload}` to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
Finally, the run function. We connect to the mqtt server, read the data from the inverter and send it to the mqtt server.
def run():
client = connect_mqtt()
client.loop_start()
while(1):
try:
battery_remaining = instrument.read_register(0x100, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/parameters/battery_remaining", battery_remaining)
except:
print("Failed to read the battery_remaining")
Create the inverter.py file.
nano inverter.py
Then copy and paste the code below.
#!/usr/bin/python3
import time
import subprocess
import minimalmodbus
from paho.mqtt import client as mqtt_client
delay = 1
broker = '192.168.1.180'
port = 1883
username = ''
password = ''
client_id = 'PowMr-client'
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1, 'rtu')
instrument.serial.baudrate = 9600
instrument.serial.bytesize = 8
instrument.serial.parity = 'N'
instrument.serial.stoppbits = 1
instrument.clear_buffers_before_each_transaction = True
instrument.serial.timeout = 0.2
instrument.mode = minimalmodbus.MODE_RTU
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to ioBroker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.username_pw_set(username, password)
client.on_connect = on_connect
client.connect(broker, port)
return client
def publish(client, topic, payload):
result = client.publish(topic, payload)
status = result[0]
if status == 0:
print(f"Send `{payload}` to topic `{topic}`")
else:
print(f"Failed to send message to topic {topic}")
def run():
client = connect_mqtt()
client.loop_start()
while(1):
try:
battery_remaining = instrument.read_register(0x100, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/parameters/battery_remaining", battery_remaining)
except:
print("Failed to read the battery_remaining")
time.sleep(delay)
try:
battery_voltage = instrument.read_register(0x101, 1, 3)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/battery_voltage", battery_voltage)
except:
print("Failed to read the battery_voltage")
time.sleep(delay)
try:
battery_current = instrument.read_register(0x102, 1, 3, True)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/battery_current", battery_current)
except:
print("Failed to read the battery_current")
time.sleep(delay)
try:
pv_power = instrument.read_register(0x109, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/parameters/pv_power", pv_power)
except:
print("Failed to read the pv_power")
time.sleep(delay)
try:
pv_voltage = instrument.read_register(0x107, 1, 3)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/pv_voltage", pv_voltage)
except:
print("Failed to read the pv_voltage")
time.sleep(delay)
try:
pv_current = instrument.read_register(0x108, 1, 3)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/pv_current", pv_current)
except:
print("Failed to read the pv_current")
time.sleep(delay)
try:
battery_charge_status = instrument.read_register(0x10B, 1, 3)*10
if battery_charge_status == 0: batt_charge_status = "0 - Töltés kikapcsolva"
elif battery_charge_status == 1: batt_charge_status = "1 - Gyorstöltés"
elif battery_charge_status == 2: batt_charge_status = "2 - Állandó feszültségű töltés"
elif battery_charge_status == 3: batt_charge_status = "3 ---"
elif battery_charge_status == 4: batt_charge_status = "4 - Lebegő töltés"
elif battery_charge_status == 5: batt_charge_status = "5 ---"
elif battery_charge_status == 6: batt_charge_status = "6 - Li akkumulátor aktiválása"
elif battery_charge_status == 7: batt_charge_status = "7 ---"
publish(client,"Photovoltaik-Anlage/Inverter/parameters/battery_charge_status", batt_charge_status)
except:
print("Failed to read the battery_charge_status")
time.sleep(delay)
try:
inverter_current_status = instrument.read_register(0x210, 1, 3)*10
if inverter_current_status == 0: inverter_status = "0 - Bekapcsolási késleltetés"
elif inverter_current_status == 1: inverter_status = "1 - Várakozás"
elif inverter_current_status == 2: inverter_status = "2 - Inicializálás"
elif inverter_current_status == 3: inverter_status = "3 - Lágy indítás"
elif inverter_current_status == 4: inverter_status = "4 - Működés hálózatról"
elif inverter_current_status == 5: inverter_status = "5 - Inverteres működés"
elif inverter_current_status == 6: inverter_status = "6 - Inverter a hálózatra"
elif inverter_current_status == 7: inverter_status = "7 - Hálózat az inverterhez"
elif inverter_current_status == 8: inverter_status = "8 - Akkumulátor aktiválva"
elif inverter_current_status == 9: inverter_status = "9 - Felhasználó általi leállítás"
elif inverter_current_status == 10: inverter_status = "10 - Hiba"
publish(client,"Photovoltaik-Anlage/Inverter/parameters/inverter_status", inverter_status)
except:
print("Failed to read the inverter_status")
time.sleep(delay)
try:
load_current = instrument.read_register(0x219, 1, 3)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/load_current", load_current)
except:
print("Failed to read the load_current")
time.sleep(delay)
try:
loadpower = instrument.read_register(0x21B, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/parameters/load_power_W", loadpower)
except:
print("Failed to read the load_power_W")
time.sleep(delay)
try:
mains_charging_current = instrument.read_register(0x21E, 1, 3)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/mains_charging_current", mains_charging_current)
except:
print("Failed to read the mains_charging_current")
time.sleep(delay)
try:
load_rate = instrument.read_register(0x21F, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/parameters/load_rate", load_rate)
except:
print("Failed to read the load_rate")
time.sleep(delay)
try:
temp_dcdc = instrument.read_register(0x220, 1, 3, True)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/temp_dcdc", temp_dcdc)
except:
print("Failed to read the temp_dcdc")
time.sleep(delay)
try:
temp_dcac = instrument.read_register(0x221, 1, 3, True)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/temp_dcac", temp_dcac)
except:
print("Failed to read the temp_dcac")
time.sleep(delay)
try:
temp_trans = instrument.read_register(0x222, 1, 3, True)
publish(client,"Photovoltaik-Anlage/Inverter/parameters/temp_transformer", temp_trans)
except:
print("Failed to read the temp_transformer")
time.sleep(delay)
# fault codes
try:
current_fault_code_1 = instrument.read_register(0x204, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/fault_codes/current_fault_code_1", current_fault_code_1)
except:
print("Failed to read the current_fault_code_1")
time.sleep(delay)
try:
current_fault_code_2 = instrument.read_register(0x205, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/fault_codes/current_fault_code_2", current_fault_code_2)
except:
print("Failed to read the current_fault_code_2")
time.sleep(delay)
try:
current_fault_code_3 = instrument.read_register(0x206, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/fault_codes/current_fault_code_3", current_fault_code_3)
except:
print("Failed to read the current_fault_code_3")
time.sleep(delay)
try:
current_fault_code_4 = instrument.read_register(0x207, 1, 3)*10
publish(client,"Photovoltaik-Anlage/Inverter/fault_codes/current_fault_code_4", current_fault_code_4)
except:
print("Failed to read the current_fault_code_4")
time.sleep(delay)
instrument.serial.close()
if __name__ == '__main__':
run()
When your file is ready, save it. Now we need to make it start automatically when the system boots. To do this we need a new file.
sudo nano /etc/systemd/system/inverter.service
Copy the following lines to the inverter.service file. Don’t forget to enter the file path correctly!
[Unit]
Description=inverter-service
Wants=network-online.target
After=network.target network-online.target
[Service]
Type=idle
User=username
ExecStartPre=/bin/sleep 30
ExecStart=/usr/bin/python3 /home/pi/inverter.py
Restart=always
[Install]
WantedBy=multi-user.target
Set the permissions as follows.
sudo chmod 644 /etc/systemd/system/inverter.service
Restart the systemctl background service.
sudo systemctl daemon-reload
Enable inverter.service.
sudo systemctl enable inverter.service
So every time the system boots, inverter.py will run and send the read data to the mqtt server.
You can find more information about the SRNE modbus protocol and some registers in the document SRNE_ModBus_Protokoll_V1.92.pdf.
You can find the free download link in the original article on my page.
With this, we can modify the inverter.py file according to our individual needs.
Comments
Please log in or sign up to comment.