Um unsere Stromrechnung zu senken, haben wir eine Insel-Solaranlage installiert, deren zentrale Einheit ein PowMr 5600W All In One Hybrid-Wechselrichter ist.
PowMr 5600W All In One hibrid inverter
Reiner Sinuswellen-Solar-Hybrid-Wechselrichter, 48 V DC, 220 V/230 V AC, 5600 W Nennleistung, integrierter 80 A MPPT-Laderegler im Wechselrichter kombiniert.
Der Hybrid-Wechselrichter verfügt über ein LCD-Display, das Systemdaten und Betriebsstatus in Echtzeit anzeigt.
Geeignet für 48 V Blei-Säure- oder Lithium-Batterien.
werbung
Um unsere Solaranlage bestmöglich zu nutzen, müssen wir den Wechselrichter überwachen. Wir müssen wissen, wie viel Strom das Solarpanel produziert oder wie viel Energie der Akku speichert.
Der PowMr 5600W All In One Hybrid-Wechselrichter verfügt auch über einen USB-Anschluss, ich habe dort ein Raspberry Pi 3-Modell angeschlossen, aber auch ein preisgünstiger Raspberry Pi Zero kann für diese Aufgabe perfekt sein.
Mit dem Python-Skript, das auf dem Raspberry Pi läuft, lesen wir die Daten aus dem Wechselrichter und fügen sie dem MQTT-Server hinzu, der auf iobroker läuft.
Der PowMr auch, wie viele ähnliche Wechselrichter (z.B. ESUN, Deye, etc.) verwendet das SRNE Modbus-RTU Kommunikationsprotokoll.
Damit das Python-Skript mit dem Wechselrichter kommunizieren kann, benötigen wir die MinimalModbus-Bibliothek. Wir können dies ganz einfach mit dem Paketinstallationsprogramm von Python tun. Falls noch nicht geschehen, installieren wir das pip-Paket-Installationsprogramm und installieren wir dann die MinimalModbus-Bibliothek.
sudo apt-get update
sudo apt-get install python3-pip
pip3 install -U minimalmodbus
Damit wir minimalmodbus verwenden können, müssen wir die Bibliothek zunächst in unser Python-Skript importieren.
#!/usr/bin/python3
import minimalmodbus
...
Dann erstellen wir eine Instanz und legen die Einstellungen fest.
...
# 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
Mit der Funktion read_register können wir die Register des Wechselrichters gelesen werden.
# read_register(registeraddress, number_of_decimals, functioncode)
battery_remaining = instrument.read_register(0x100, 1, 3)*10
12V 100Ah LiFePO4 Lithiumbatterie
1280 Wh, 100 A BMS, bis zu 15000 Ladezyklen.
Auch für Solaranlagen ist es eine gute Wahl.
werbung
Wir werden die paho-mqtt-Bibliothek verwenden, um mit dem mqtt-Server zu kommunizieren. Wenn wir dies noch nicht getan haben, installieren wir es wie folgt.
pip3 install paho-mqtt
Wir importieren auch die paho-mqtt-Bibliothek.
#!/usr/bin/python3
import minimalmodbus
from paho.mqtt import client as mqtt_client
...
Geben wir Verbindungsdaten für den MQTT-Server ein.
...
broker = '192.168.1.180'
port = 1883
username = ''
password = ''
client_id = 'PowMr-client'
...
Wir benötigen eine Funktion, um eine Verbindung zum MQTT-Server herzustellen.
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
Wir benötigen außerdem eine Funktion, um MQTT-Nachrichten zu veröffentlichen.
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}")
Zum Schluss noch die Run-Funktion. Wir verbinden uns mit dem mqtt-Server, lesen die gewünschten Daten vom Wechselrichter aus und senden diese an den 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")
Diese können erforderlich sein:
werbung
Erstellen wir die Datei inverter.py.
nano inverter.py
Kopieren wir dann den Code unten.
#!/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 - Ladung ausgeschaltet"
elif battery_charge_status == 1: batt_charge_status = "1 - Schnelles Laden"
elif battery_charge_status == 2: batt_charge_status = "2 - Laden mit konstanter Spannung"
elif battery_charge_status == 3: batt_charge_status = "3 ---"
elif battery_charge_status == 4: batt_charge_status = "4 - Schwimmende Ladung"
elif battery_charge_status == 5: batt_charge_status = "5 ---"
elif battery_charge_status == 6: batt_charge_status = "6 - Aktivierung der Li-Batterie"
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 - Einschaltverzögerung"
elif inverter_current_status == 1: inverter_status = "1 - Warten"
elif inverter_current_status == 2: inverter_status = "2 - Initialisierung"
elif inverter_current_status == 3: inverter_status = "3 - Sanfter Start"
elif inverter_current_status == 4: inverter_status = "4 - Netzwerkbetrieb"
elif inverter_current_status == 5: inverter_status = "5 - Wechselrichterbetrieb"
elif inverter_current_status == 6: inverter_status = "6 - Wechselrichter für das Netz"
elif inverter_current_status == 7: inverter_status = "7 - Netzwerk für den Wechselrichter"
elif inverter_current_status == 8: inverter_status = "8 - Batterie aktiviert"
elif inverter_current_status == 9: inverter_status = "9 - Ausschalten durch den Benutzer"
elif inverter_current_status == 10: inverter_status = "10 - Fehler"
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()
Wenn unsere Datei fertig ist, speichern wir sie. Jetzt müssen wir dafür sorgen, dass es beim Systemstart automatisch startet. Dazu benötigen wir eine weitere Datei.
sudo nano /etc/systemd/system/inverter.service
Kopieren wir die folgenden paar Zeilen in die Datei. Vergessen wir nicht, den Dateipfad korrekt einzugeben!
[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
Legen wir die Berechtigungen wie folgt fest.
sudo chmod 644 /etc/systemd/system/inverter.service
Starten wir den Systemctl-Hintergrunddienst neu.
sudo systemctl daemon-reload
Inverter.service aktivieren.
sudo systemctl enable inverter.service
Auf diese Weise wird inverter.py bei jedem Systemstart ausgeführt und die gelesenen Daten werden an den MQTT-Server gesendet.
werbung
Weitere Informationen zum SRNE-Modbus-Protokoll und einigen Registern finden wir im untenstehenden PDF-Dokument. Damit können wir die Datei „inverter.py“ nach unseren individuellen Bedürfnissen modifizieren.