Napelemes hibrid inverter csatlakoztatása ioBrokerhez

A villanyszámlánk csökkentése érdekében kiépítettünk egy szigetüzemű napelemes rendszert, ennek a központi egysége egy PowMr 5600W All In One hibrid inverter.

Hibrid szolár inverter 5600 W, 48 V DC - 220 V 230 V AC 80 A MPPT szoláris töltésvezérlővel, párhuzamos támogatás, 48 ​​V-os ólom-sav vagy lítium akkumulátorhoz

PowMr 5600W All In One hibrid inverter

Tiszta szinuszos napelemes hibrid inverter, 48V DC, 220V/230V AC, 5600W-os névleges teljesítmény beépített 80A MPPT töltésvezérlő egyesítve az inverterben.

A hibrid inverter LCD kijelzővel rendelkezik, amely valós időben mutatja a rendszeradatokat és az üzemállapotot.

Alkalmas 48 ​​V-os ólom-savas vagy lítium akkumulátorhoz.

A napelemes rendszerünk lehető legjobb kihasználásához szükségünk van az inverter monitorozására. Tudnunk kell, hogy mennyi áramot termel a napelem, vagy mennyi energiát tárol az akkumulátorcsomag.

A PowMr 5600W All In One hibrid inverter rendelkezik egy USB portal is, én oda csatlakoztattam egy Raspberry Pi 3 modellt, de erre a feladatra tökéletes lehet egy kedvező árú Raspberry pi zero is.

A Raspberry Pi-n futó Python script segítségével kiolvassuk az adatokat az inverterből és továbbitjuk az iobrokeren futó mqtt szerverre.

A PowMr is mint sok hasonló inverter (pl: ESUN, Deye, stb.) SRNE Modbus-RTU kommunikációs protokollt használ.

Hogy python script komunikáljon az inverterrel, szükségünk van a MinimalModbus könyvtárra. Ezt a python csomagtelepítőjével könnyedén megtehetjük. Ha még nincs telepítve, telepítsük a pip csomagtelepítőt, majd telepítsük a MinimalModbus könyvtárat.

Bash
sudo apt-get update 
sudo apt-get install python3-pip 
 
pip3 install -U minimalmodbus

A minimalmodbus használatához a python scriptünkben elöször importáljuk a könyvtárat.

Python
#!/usr/bin/python3

import minimalmodbus
...

Majd létrehozunk egy példányt és megadjuk a beállításokat.

Python
...

#            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

Az inverter regisztereit a read_register függvénnyel tudjuk kiolvasni.

Python
# read_register(registeraddress, number_of_decimals, functioncode)
battery_remaining = instrument.read_register(0x100, 1, 3)*10
12V 100Ah LiFePO4 Lithium Akku, 1280Wh, 100A BMS, akár 15000 töltési ciklus.

12V 100Ah LiFePO4 Lithium Akku

1280Wh, 100A BMS, akár 15000 töltési ciklus.

Jó választás naplemes rendszerekhez is.

Az mqtt szerverrel való kommunikációhoz a paho-mqtt könyvtárat fogjuk használni. Ha meg nem tettük meg, telepítsük az alábbi módon.

Bash
pip3 install paho-mqtt

Importáljuk a paho-mqtt könyvtárat is.

Python
#!/usr/bin/python3

import minimalmodbus
from paho.mqtt import client as mqtt_client
...

Csatlakozási adatok megadása az mqtt szerverhez.

Python
...
broker = '192.168.1.180'
port = 1883
username = ''
password = ''
client_id = 'PowMr-client'
...

Szükségünk van egy függvényre a csatlakozáshoz az mqtt szerverhez.

Python
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

Az MQTT-üzenetek közzétételéhez is kell egy függvény.

Python
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}")

Végül a run függvény. Csatlakozunk az mqtt szerverhez, kiolvassuk az inverterből a kívánt adatokat és elküldjük az mqtt szerverre.

Python
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")

Hozzuk létre az inverter.py fájlt.

Bash
nano inverter.py

Majd másoljuk be az alábbi kódot.

Python
#!/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()

Ha kész a fájlunk, mentsük el. Most el kell érni, hogy automatikusan elinduljon a rendszer indításakor. Ehez egy újabb fájlra van szükségünk.

Bash
sudo nano /etc/systemd/system/inverter.service

A fájlba másoljuk be az alábbi pár sort. Ne felejtsük el fájl elérési útját helyesen megadni!

Bash
[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

Állítsuk be a jogosultságokat az alábbiak szerint.

Bash
sudo chmod 644 /etc/systemd/system/inverter.service

Indítsuk újra a systemctl háttérszolgáltatást.

Bash
sudo systemctl daemon-reload

Engedélyezzük az inverter.service szolgáltatást.

Bash
sudo systemctl enable inverter.service

Igy már minden rendszerindításkor futni fog az inverter.py és a kiolvasott adatokat elküldi az mqtt szervernek.

Az SRNE modbus protokollról és egyes regiszterekről az alábbi pdf dokumentumban találhatunk bövebb információt. Ennek segítségével egyéni igényeinknek megfelelően alakíthatjuk az inverter.py fájlt.