Solar photovoltaic (PV) plants, microgrids, and commercial rooftop installations rely on industrial communication protocols to monitor inverter generation, track Maximum Power Point Tracking (MPPT) performance, and coordinate grid export curtailment. Modbus TCP and Modbus RTU remain the undisputed communication standards connecting solar inverters to SCADA systems, Data Acquisition Gateways, and Energy Management Systems (EMS).

Testing solar monitoring software, SCADA dashboards, or PLC power plant controllers with real high-voltage solar inverters is often dangerous, weather-dependent, and physically impractical in a lab. In this guide, you will learn how to configure ModbusSimulator as a virtual solar inverter — supporting SunSpec Alliance Modbus models, proprietary register maps (SMA, SolarEdge, Huawei SUN2000, Fronius, Sungrow), dynamic daily irradiance curves, and fault injection.

Why Use a Solar Modbus Simulator?

  • Zero Hardware Dependency: Test SCADA, Grafana, ignition, and EMS software 24/7 without waiting for sunny daylight or physical grid tie-in.
  • Realistic Fault Simulation: Test inverter error codes, grid over-voltage trip thresholds, DC ground faults, and high-temperature derating safely.
  • Multi-Inverter Aggregation: Simulate 20+ inverters on a single port to validate network bandwidth, poll cycle timeouts, and total plant yield rollups.

Understanding Solar Inverter Modbus Architecture

Solar inverters act as Modbus Slaves (Servers). The SCADA server, PLC, or IoT edge gateway acts as the Modbus Master (Client) that polls the inverter at regular intervals (typically every 1 to 10 seconds).

Manufacturer / Standard Supported Protocol Default Port / Baud Register Addressing Scheme Data Format
SunSpec Alliance (Standard) Modbus TCP / RTU Port 502 / 1502 • 9600–19200 Holding Registers 40001+ ('SunS' identifier) Signed Int16 + Scale Factor (sunssf)
SolarEdge Modbus TCP (SunSpec) Port 1502 or 502 Holding Registers 40070–40107 (Model 101/103) SunSpec Int16 + Scale Factor
SMA Solar (Sunny Boy / STP) Modbus TCP (Speedwire) & SunSpec Port 502 • Unit ID 3 default Registers 30000+ (SMA) & 40000+ (SunSpec) Big-Endian U32, S32, Float32
Huawei (SUN2000 Series) Modbus RTU / TCP (SmartLogger) Port 502 • 9600 8-N-1 Holding Registers 32000–32106 Big-Endian U16, U32, S32
Fronius (Symo / Primo / Eco) Modbus TCP / RTU (Datamanager) Port 502 • Unit ID 1 SunSpec Float (Model 111/113) or Int+SF IEEE 754 Float32 or SunSpec SF

The SunSpec Modbus Model Structure

The SunSpec Alliance established standardized register models to ensure interoperability across solar hardware. When configuring your simulator, SunSpec models are organized in sequential blocks:

1. Header & Common Model 1 (Base Registers)

SunSpec compliant inverters begin with the 4-byte ASCII string "SunS" (hex 0x5375, 0x6E53) at register 40001 (address 0 in zero-based addressing):

  • Reg 40001–40002: SunSpec ID (0x5375 0x6E53)
  • Reg 40003: Model ID = 1 (Common Model)
  • Reg 40004: Model Length = 66 registers
  • Reg 40005–40020: Manufacturer Name (e.g. "SolarEdge", 16 ASCII chars)
  • Reg 40021–40036: Model String (e.g. "SE10000H-US", 16 ASCII chars)
  • Reg 40045–40060: Serial Number (e.g. "7E12345678")

2. Model 101 / 103 (Inverter Measurements)

Model 101 covers single-phase inverters, while Model 103 covers three-phase inverters. Key measurement registers include:

SunSpec Register Point Name Data Type Units Description & Scale Factor
40072 A uint16 Amps AC Total Current (Scaled by A_SF at 40076)
40084 W int16 Watts AC Active Power Output (Scaled by W_SF at 40085)
40086 Hz uint16 Hz Grid Frequency (Scaled by Hz_SF at 40087)
40094 WH acc32 Watt-hours Lifetime Energy Production (Scaled by WH_SF at 40096)
40097 DCW int16 Watts DC Power Input from Solar Strings (Scaled by DCW_SF)
40108 I_STATUS enum16 Enum Operating State: 1=Off, 2=Sleeping, 4=MPPT Running, 7=Fault

Step-by-Step: Simulating a Solar Inverter in ModbusSimulator

Follow these steps to set up a virtual SunSpec or custom solar inverter in ModbusSimulator:

  1. Launch ModbusSimulator & Create Server:
    Select Modbus TCP Server, set the IP to 127.0.0.1 (or 0.0.0.0 for network access), Port 502 (or 1502), and Slave ID 1.
  2. Populate SunSpec Header (40001–40004):
    Set Register 0 to 21365 (0x5375 = "Su") and Register 1 to 28243 (0x6E53 = "nS"). Set Register 2 (Model ID) to 103 (Three Phase Inverter).
  3. Set AC Active Power & Scale Factors:
    To simulate 8,500 Watts (8.5 kW) output:
    • Set W (Register 83, zero-based) = 8500
    • Set W_SF (Register 84, zero-based) = 0 (scale factor 10^0 = 1)
    • Or set W = 850 with W_SF = 1 (850 * 10^1 = 8500 W)
  4. Configure Dynamic Irradiance Curve:
    Use ModbusSimulator's built-in Simulation Curves (Sine / Ramp / Random Noise) on the active power register to recreate a realistic dawn-to-dusk solar generation curve.
  5. Test Inverter Alarm Tripping:
    Change Register 107 (I_STATUS) from 4 (Normal MPPT) to 7 (Fault) or set bit 3 in the Inverter Event Bitmask (0x0008 = DC Over-Voltage). Verify your SCADA alarm console turns red immediately.

Testing with Python (pymodbus)

Here is a production-ready Python script using pymodbus to poll SunSpec registers from your simulated solar inverter and decode the scaled values:

from pymodbus.client import ModbusTcpClient
import struct

def read_solar_inverter(host='127.0.0.1', port=502, unit_id=1):
    client = ModbusTcpClient(host, port=port)
    if not client.connect():
        print("[-] Connection failed to solar inverter simulator.")
        return

    # Read SunSpec Model 103 (Three Phase Inverter) starting at register 40070
    # Address 70 (0-based) for 40 registers
    rr = client.read_holding_registers(address=70, count=40, slave=unit_id)
    if rr.isError():
        print("[-] Modbus Error:", rr)
        client.close()
        return

    regs = rr.registers
    
    # Extract Power (W at offset 13) and Power Scale Factor (W_SF at offset 14)
    raw_power = struct.unpack('>h', struct.pack('>H', regs[13]))[0]
    raw_w_sf = struct.unpack('>h', struct.pack('>H', regs[14]))[0]
    actual_power_watts = raw_power * (10 ** raw_w_sf)

    # Extract Operating Status (offset 37)
    status_enum = regs[37]
    status_map = {1: "OFF", 2: "SLEEPING", 3: "STARTING", 4: "MPPT RUNNING", 5: "THROTTLED", 7: "FAULT"}
    status_text = status_map.get(status_enum, f"UNKNOWN ({status_enum})")

    print("========================================")
    print(" ☀️ SOLAR INVERTER TELEMETRY REPORT")
    print("========================================")
    print(f" Inverter Status    : {status_text}")
    print(f" AC Active Power    : {actual_power_watts:,.2f} W ({actual_power_watts/1000:.2f} kW)")
    print(f" Raw W / Scale W_SF : {raw_power} / {raw_w_sf}")
    print("========================================")

    client.close()

if __name__ == '__main__':
    read_solar_inverter()

Common Solar Inverter Modbus Troubleshooting Gotchas

  • 0-Based vs 1-Based Addressing: In PLC software and pymodbus, register 40001 is accessed at address 0. If your readings are shifted by 1 register, check for the classic 1-based offset. Read our Modbus Register Types Guide for a detailed explanation.
  • Scale Factor Sign Interpretation: Scale factors (sunssf) are signed 16-bit integers (e.g. 0xFFFF = -1, 0xFFFE = -2). If your decoder treats them as unsigned (65535), your power calculations will result in astronomical overflow values.
  • Endianness on 32-Bit Energy Totals: Lifetime yield (kWh) is usually stored as a 32-bit integer or IEEE float across two consecutive registers. Ensure word order matches (Big-Endian High-Word First). See Modbus Byte Order & Endianness.
  • TCP Connection Limits: Many physical solar inverters (e.g. SMA Speedwire) support only 1 or 2 simultaneous TCP sockets. Testing with ModbusSimulator avoids socket exhaustion during aggressive polling audits.

Test Your Solar Monitoring System with ModbusSimulator

Download ModbusSimulator for Windows 10/11. Simulate SunSpec inverters, custom register maps, and multi-inverter solar farms effortlessly.