Documentation Index
Fetch the complete documentation index at: https://fop-50527c4b.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
The SUN2000 register map is organized into functional groups. You read all registers with FC 03 (Read Holding Registers). INT32 and UINT32 values span two consecutive registers — always request both in a single transaction to guarantee consistency. Divide each raw integer by its gain to obtain the real physical value.
Register addresses differ between SUN2000 series (L0, L1, M0, M1, M2, M3, MA, MB0). The addresses below match the SUN2000MA and SUN2000-M1/M3 Modbus Interface Definitions (Issue 08, 2024-11-07). Verify every address against the Modbus Interface Definitions for your specific model before deploying to production.
| Register | Description | Type | Gain |
|---|
| 30000 | Inverter model | String | — |
| 30015 | Serial number (SN) | String | — |
| 32089 | Run state | U16 | 1 |
Register 32089 returns one of the coded integers in the state decode table below.
DC side registers (solar panels)
| Register | Description | Type | Gain | Unit |
|---|
| 32016 | PV1 voltage | I16 | 10 | V |
| 32017 | PV1 current | I16 | 100 | A |
| 32064 | DC input power | I32 | 1 | W |
AC side registers (grid)
| Register | Description | Type | Gain | Unit |
|---|
| 32066 | Line voltage L1-L2 (AB) | U16 | 10 | V |
| 32069 | Phase voltage A (L1-N) | U16 | 10 | V |
| 32070 | Phase voltage B (L2-N) | U16 | 10 | V |
| 32071 | Phase voltage C (L3-N) | U16 | 10 | V |
| 32072 | Phase A current | I16 | 10 | A |
| 32074 | Phase B current | I16 | 10 | A |
| 32076 | Phase C current | I16 | 10 | A |
| 32078 | Reactive power | I32 | 1 | var |
| 32080 | Active power | I32 | 1 | W |
| 32082 | Power factor | I16 | 1000 | — |
| 32085 | Grid frequency | U16 | 100 | Hz |
Register 32080 (Active power) is signed: positive values indicate generation, negative values indicate consumption from the grid.
Energy and temperature registers
| Register | Description | Type | Gain | Unit |
|---|
| 32106 | Daily yield | U32 | 100 | kWh |
| 32109 | Total yield | U32 | 100 | kWh |
| 32087 | Internal temperature | I16 | 10 | °C |
Inverter state decode (register 32089)
| Raw value | State |
|---|
| 0 | Idle: Initializing |
| 1 | Idle: Detecting ISO |
| 2 | Idle: Detecting irradiation |
| 3 | Idle: Grid Detecting |
| 256 | Starting |
| 512 | On-Grid (normal operation) |
| 513 | On-Grid: Power Limit |
| 514 | On-Grid: Self-derating |
| 768 | Shutdown: Fault |
| 769 | Shutdown: Command |
| 770 | Shutdown: OVGR |
| 771 | Shutdown: Comm. disconnected |
| 772 | Shutdown: Power Limit |
| 1280 | Spot-check |
| 2048 | IV Scanning |
| 40960 | Idle: No irradiation |
Top 10 registers for Home Assistant, Node-RED, and SCADA
These registers cover the most common monitoring requirements with minimal polling overhead:
| Register | Parameter | Type | Gain | Notes |
|---|
| 32064 | DC input power | I32 | 1 | Total power from panels (W) |
| 32069 | Phase voltage A (L1-N) | U16 | 10 | |
| 32070 | Phase voltage B (L2-N) | U16 | 10 | |
| 32071 | Phase voltage C (L3-N) | U16 | 10 | |
| 32080 | Active power AC | I32 | 1 | positive = generation, negative = consumption |
| 32085 | Grid frequency | U16 | 100 | |
| 32087 | Internal temperature | I16 | 10 | °C |
| 32089 | Inverter run state | U16 | 1 | 512 = On-Grid |
| 32106 | Daily yield | U32 | 100 | kWh |
| 32109 | Total yield | U32 | 100 | kWh |
Python example: reading key registers
The example below uses the pymodbus library to connect over Modbus TCP and read a selection of the registers above.
from pymodbus.client import ModbusTcpClient
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
HOST = "192.168.200.1" # Inverter Wi-Fi AP address
PORT = 6607 # New-firmware SDongle port; use 502 for old firmware
SLAVE_ID = 1
client = ModbusTcpClient(HOST, port=PORT)
client.connect()
def read_u16(address):
result = client.read_holding_registers(address, count=1, slave=SLAVE_ID)
return result.registers[0]
def read_i16(address):
raw = read_u16(address)
return raw if raw < 0x8000 else raw - 0x10000
def read_i32(address):
result = client.read_holding_registers(address, count=2, slave=SLAVE_ID)
decoder = BinaryPayloadDecoder.fromRegisters(
result.registers, byteorder=Endian.BIG, wordorder=Endian.BIG
)
return decoder.decode_32bit_int()
def read_u32(address):
result = client.read_holding_registers(address, count=2, slave=SLAVE_ID)
decoder = BinaryPayloadDecoder.fromRegisters(
result.registers, byteorder=Endian.BIG, wordorder=Endian.BIG
)
return decoder.decode_32bit_uint()
# DC side
dc_power_w = read_i32(32064)
# AC side
phase_a_v = read_u16(32069) / 10 # Volts
active_power_w = read_i32(32080) # W, positive = generation
grid_freq_hz = read_u16(32085) / 100 # Hz
temperature_c = read_i16(32087) / 10 # °C
run_state = read_u16(32089)
# Energy
daily_kwh = read_u32(32106) / 100
total_kwh = read_u32(32109) / 100
print(f"DC input power : {dc_power_w} W")
print(f"Phase A voltage: {phase_a_v} V")
print(f"Active power : {active_power_w} W")
print(f"Grid frequency : {grid_freq_hz} Hz")
print(f"Temperature : {temperature_c} °C")
print(f"Run state : {run_state} (512 = On-Grid)")
print(f"Daily yield : {daily_kwh} kWh")
print(f"Total yield : {total_kwh} kWh")
client.close()