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 =
66registers - 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:
-
Launch ModbusSimulator & Create Server:
Select Modbus TCP Server, set the IP to127.0.0.1(or0.0.0.0for network access), Port502(or1502), and Slave ID1. -
Populate SunSpec Header (40001–40004):
Set Register 0 to21365(0x5375= "Su") and Register 1 to28243(0x6E53= "nS"). Set Register 2 (Model ID) to103(Three Phase Inverter). -
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=850withW_SF=1(850 * 10^1 = 8500 W)
- Set
-
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. -
Test Inverter Alarm Tripping:
Change Register 107 (I_STATUS) from4(Normal MPPT) to7(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.