Modbus TCP Client for Kostal Inverter

Hi,

I am using Modbus_master_test Software to read several Registers of Kostal Solar Inverter. However it seems that only adress 4003 (Inverter Modbus On) is working properly. If I try to request adress 40005 I get meaningless values in the result array. (any non defined values). If I try to request higher adresses my Lan gets somehow disturbed..

Can anyone help me out?

regards
Markus

Kostal has SunSpec Modbus like my Fronius. I don't have time to see to Kostal details now, but you can check my project GitHub - JAndrassy/Regulator: DIY Arduino consumption regulator build to use excess solar power for auxiliary 'summer' heating. The solar power data are retrieved over SunSpec Modbus TCP. IoT monitoring with Blynk and local Web server.

SunSpec registers (I could not find Kostal or general version)

Thanks for quick reply.

I did a test using CAS Modbus Scanner, which works properly

Request UID of Inverter, which shall be the value of Addr 04

Request:
$47 = ID of Inverter
$03 = function code
$04= addr
$01=Number of Bytes
[08:24:28] => Poll: 47 03 00 04 00 01

Response:
$47 = ID of Inverter
$03 = function code
$01=Number of Bytes
$47=Content of register
[08:32:49] <= Response: 47 03 02 00 47

Arduino Code: (Is this correct?)

int regs[100];
const int SMA_UID = 71;
res = modbusRequest(SMA_UID, 40003, 1, regs);
reg[0]=??? //shall be 71??

MaggoB:
Thanks for quick reply.

I did a test using CAS Modbus Scanner, which works properly

Request UID of Inverter, which shall be the value of Addr 04

Request:
$47 = ID of Inverter
$03 = function code
$04= addr
$01=Number of Bytes
[08:24:28] => Poll: 47 03 00 04 00 01

Response:
$47 = ID of Inverter
$03 = function code
$01=Number of Bytes
$47=Content of register
[08:32:49] <= Response: 47 03 02 00 47

Arduino Code: (Is this correct?)

int regs[100];
const int SMA_UID = 71;
res = modbusRequest(SMA_UID, 40003, 1, regs);
reg[0]=??? //shall be 71??

if you want the value of register "well-known value. 1 Uniquely identifies this as a SunSpec Common Model block" then use address 40002, because addresses in docs are 1 based and the system has them 0 based

Read Out Register 4
Arduino Code:
res = modbusRequest(SMA_UID, 40003, 1, regs);
Serial.print("Error :");Serial.println(res);
if (modbusError(res)) { return false;}
else { Serial.print("Register 4003 Content:");Serial.println(regs[0]);}

Kostal Doku
Addr (hex) Addr (dec) Description Unit Format N1) Access Function Code

0x04 4 MODBUS Unit-ID - U16 1 R/W 0x03

Result Serial Monitor
Error :0
Register 4003 Content:1 (shall be 71 !!)

MaggoB:
Read Out Register 4
Arduino Code:
res = modbusRequest(SMA_UID, 40003, 1, regs);
Serial.print("Error :");Serial.println(res);
if (modbusError(res)) { return false;}
else { Serial.print("Register 4003 Content:");Serial.println(regs[0]);}

Kostal Doku
Addr (hex) Addr (dec) Description Unit Format N1) Access Function Code

0x04 4 MODBUS Unit-ID - U16 1 R/W 0x03

Result Serial Monitor
Error :0
Register 4003 Content:1 (shall be 71 !!)

read 0x04 or 0x03 not 40003, if you want the uid register

registers over 40000 are SunSpec register

Hello Juraj,

thanks a lot for your great support. I can read the registers now!!!

Just another related problem: how to convert the 4 byte register into float varaible. See attached screenshot. I would need the float32 value in my code.

Screen Shot register100 into float.png

MaggoB:
Hello Juraj,

thanks a lot for your great support. I can read the registers now!!!

Just another related problem: how to convert the 4 byte register into float varaible. See attached screenshot. I would need the float32 value in my code.

  uint16_t reg1 = 28310;
  uint16_t reg2 = 16780;
  union {
    uint16_t ints[2];
    float f;
  } int2fUnion;
  int2fUnion.ints[0] = reg1;
  int2fUnion.ints[1] = reg2;
  float f = int2fUnion.f;

thank you very much for your great support