ModBus Protocol - tkubec/GoodWe GitHub Wiki

The communication is based on the ModBus protocol. Unfortunately, the register mapping differs among inverter models.

Request

Every message is wrapped in the following envelope:

Byte Value
0 modbus address (0xF7 by default)
1 function code
2 ... n message itself
(n +1) (n + 2) 16 bit CRC checksum of the entire envelope (without CRC itself)

Response

The response from the inverter uses the same envelope as the request, preceded by bytes 0xAA 0x55.

If the response is not sent within 1 - 2 seconds, it was either lost (it happens in approx 1% cases) or the request was not recognized.

CRC algorithm

 static UInt16 CalculateCrc(byte[] buf, int len)
    {
        UInt16 crc = 0xFFFF;

        for (int pos = 0; pos < len; pos++)
        {
            crc ^= (UInt16)buf[pos];          // XOR byte into least sig. byte of crc

            for (int i = 8; i != 0; i--)
            {    // Loop over each bit
                if ((crc & 0x0001) != 0)
                {      // If the LSB is set
                    crc >>= 1;                    // Shift right and XOR 0xA001
                    crc ^= 0xA001;
                }
                else                            // Else LSB is not set
                    crc >>= 1;                    // Just shift right
            }
        }
        // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
        return crc;
    }

Known commands

The inverter accepts these function codes:

  • 3 - read multiple registers
  • 6 - write single register
  • 9 - write multiple registers

Read multiple registers (function code 3)

Request message:

Byte Value
0 - 1 first requested modbus register address (16bit MSB first)
2 - 3 count of registers to read (16bit MSB first)

In case of a full success, the returned function code in the envelope is 3, otherwise greater then 128 (e.g. 0x83]

The message in the response:

Byte Value
0 length (i.e. count of returned registers * 2)
1 ... array of the read registers (16bit MSB first)