Hi folks!
Short summary of my setup: Pylontech US3000C and 2000C, Epever Tracer 5420AN and a Multiplus 2 GX meeting on a DC block. Raspberry Pi connected via ethernet cable with the multiplus, static configuration. The pylons are connected via original CAN cable. So far so good.
Normal ESS setup for german grid 4105 and pylontech setup.
GX Firmware: 3.62
Multiplus Firmware: 556
Pylontech total SoC >90%
GX Setup: ESS Mode 3 âexternal controlâ, DVCC enabled
Multiplus: ON (display says âESSâ)
I can read and write Modbus registers. GX = 100, Mutliplus = 228
ID 228, Register 38 = 0 (charger enabled)
ID 228, Register 39 = 0 (inverter enabled)
ID 228, Register 57 = 1 (Pylon allows charge)
ID 228, Register 58 = 1 (Plyon allows discharge)
ID 100, Register 2902 = 3 (ESS Mode 3)
When i write a positive power target to register 37 the multiplus starts charging the battery. When i set a negative power target (int16) multiplus goes to âbulkâ and nothing happens. I can write register 37 and there is no Modbus error shown on the GX device. The multiplus just does not feed in to grid no matter what i try. ;(
Any help pointing to my mistake is much appreciated ! If you need more information on specific registers, settings please let me know.
Here is my python script:
#!/usr/bin/env python3
import time
from pymodbus.client.sync import ModbusTcpClient
from pymodbus.payload import BinaryPayloadBuilder, BinaryPayloadDecoder
from pymodbus.constants import Endian
IP = â192.168.1.2â
PORT = 502
UNIT_ID = 228
def clamp_power(value):
# Wert auf -32768..32767 begrenzen
if value < -32768:
return -32768
if value > 32767:
return 32767
return value
def to_unsigned_16bit(value):
# signed int16 zu unsigned int16 fĂźr pymodbus (Registerwerte)
return value & 0xFFFF
def write_signed_power_setpoint(client, power):
builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
builder.add_16bit_int(power) # richtiger signed-Wert
payload = builder.to_registers()
response = client.write_registers(37, payload, unit=UNIT_ID)
if response.isError():
print(f"Fehler beim Schreiben von Register {REGISTER_L1}: {response}â)
return False
return True
def write_power_setpoint(client, power):
power = clamp_power(power)
power_u = to_unsigned_16bit(power)
response = client.write_register(37, power_u, unit=UNIT_ID)
if response.isError():
print(f"Fehler beim Schreiben Register 37â)
return False
return True
###################################################################################################
def main():
print(âStartâ)
client = ModbusTcpClient(IP, port=PORT)
if not client.connect():
print(âVerbindung zum MultiPlus fehlgeschlagen!â)
return # â richtig eingerĂźckt
# VE.Bus Reset
#write_response = client.write_register(62, 0, unit=UNIT_ID)
#if write_response.isError():
# print("Fehler beim Schreiben von Register 62")
#else:
# print("VE.Bus Reset")
# ESS disable charge flag phase
write_response = client.write_register(38, 1, unit=UNIT_ID)
if write_response.isError():
print("Fehler beim Schreiben von Register 38")
else:
print("Charger ON (1)")
# Register 38 auslesen
read_response = client.read_holding_registers(38, 1, unit=UNIT_ID)
if read_response.isError():
print("Fehler beim Lesen von Register 38")
else:
value = read_response.registers[0]
print(f"Charge ON(0): {value}")
# ESS disable feedback flag phase
write_response = client.write_register(39, 0, unit=UNIT_ID)
if write_response.isError():
print("Fehler")
else:
print("Inverter ON (0)")
# Register 39 auslesen
read_response = client.read_holding_registers(39, 1, unit=UNIT_ID)
if read_response.isError():
print("Fehler beim Lesen von Register 39")
else:
value = read_response.registers[0]
print(f"Inverter: {value}")
# Maximum overvoltage feed-in power L1
write_response = client.write_register(66, 0, unit=UNIT_ID)
if write_response.isError():
print("Fehler beim Schreiben von Register 66")
else:
print("Maximum overvoltage feed-in power L1")
# Register 66 auslesen
read_response = client.read_holding_registers(66, 1, unit=UNIT_ID)
if read_response.isError():
print("Fehler beim Lesen von Register 66")
else:
value = read_response.registers[0]
print(f"Maximum overvoltage feed-in power L1: {value}")
# Feed DC overvoltage into grid
write_response = client.write_register(65, 0, unit=UNIT_ID)
if write_response.isError():
print("Fehler 65")
else:
print("Feed DC overvoltage into grid (0)")
# ACPowerSetpoint acts as feed-in limit
write_response = client.write_register(71, 0, unit=UNIT_ID)
if write_response.isError():
print("Fehler beim Schreiben von Register 71")
else:
print("ACPowerSetpoint acts as feed-in limit (1)")
# Switch Position
write_response = client.write_register(33, 3, unit=UNIT_ID)
if write_response.isError():
print("Fehler beim Schreiben von Register 33")
else:
print("Switch Position (3)")
# Power Assist boost factor
write_response = client.write_register(106, 1, unit=UNIT_ID)
if write_response.isError():
print("Fehler beim Schreiben von Register 106")
else:
print("Power Assist boost factor (0)")
# VE.Bus BMS allows battery to be charged
read_response = client.read_holding_registers(57, 1, unit=UNIT_ID)
if read_response.isError():
print("Fehler beim Lesen von Register 57")
else:
value = read_response.registers[0]
print(f"VE.Bus BMS allows battery to be charged: {value}")
# VE.Bus BMS allows battery to be discharged
read_response = client.read_holding_registers(58, 1, unit=UNIT_ID)
if read_response.isError():
print("Fehler beim Lesen von Register 58")
else:
value = read_response.registers[0]
print(f"VE.Bus BMS allows battery to be discharged: {value}")
decoder = BinaryPayloadDecoder.fromRegisters(
read_response.registers,
byteorder=Endian.Big,
wordorder=Endian.Big
)
try:
while True:
power = -211 # Negative Werte = Einspeisung ins Netz
#if write_power_setpoint(client, power):
# print(f"Setpoint erfolgreich gesetzt: {power} W")
#else:
# print("Fehler beim Schreiben des Setpoints")
write_response = client.write_register(37, 65101, unit=UNIT_ID)
if write_response.isError():
print("Fehler beim Schreiben von Register 37")
else:
print("ACSetPoint 37 erfolgeich")
# -------- READ REGISTER 96 (ESS power setpoint phase 1) -----------
read_response = client.read_holding_registers(96, 2, unit=UNIT_ID)
if read_response.isError():
print("Fehler beim Lesen von Register 96")
else:
decoder = BinaryPayloadDecoder.fromRegisters(
read_response.registers,
byteorder=Endian.Big,
wordorder=Endian.Big
)
ess_power_setpoint = decoder.decode_32bit_int()
print(f"Register 96 (ESS power setpoint phase 1): {ess_power_setpoint} W")
time.sleep(4) # Alle 4 Sekunden schreiben (Kommentar stimmt nicht)
except KeyboardInterrupt:
print("Programm beendet durch Benutzer")
finally:
client.close()
if name == âmainâ:
main()
I have another Python script doing a zero feed in with a shelly3em which worked great with a SoySource inverter. I just cant get the multiplus to feed in so i dont have a chance to adapt my zero feed in scriptâŚ