KCSv3 Modbus RTU over TCP Protocol Specification ================================================ 1. Overview ----------- This document specifies the Modbus RTU over TCP protocol exposed by the KCSv3 firmware TCP server when the TCP protocol mode is configured for Modbus RTU frames. This mode transports a complete Modbus RTU ADU over a TCP socket. It does not use the standard Modbus TCP MBAP header. 2. Communication Parameters --------------------------- - Protocol: Modbus RTU ADU transported over TCP - TCP port: configured by tcp_server_port - Slave address: configured by tcp_server_protocol_modbus_local_addr - Register addressing: 0-based Modbus protocol address - Frame format: [Slave Address][PDU][CRC Lo][CRC Hi] - CRC: Modbus CRC16, low byte first - MBAP header: not used Clients should send one complete RTU ADU frame per TCP request. The firmware validates the RTU slave address and CRC before processing the PDU. 3. Supported Function Codes --------------------------- +---------------+---------------------------+-------------------------------+ | Function Code | Name | Usage | +---------------+---------------------------+-------------------------------+ | 0x01 | Read Coils | Read DO output state | | 0x02 | Read Discrete Inputs | Read DI input state | | 0x03 | Read Holding Registers | Read DAC/IR/RF/energy data | | 0x04 | Read Input Registers | Read ADC/temperature/humidity | | 0x05 | Write Single Coil | Set one DO or trigger toggle | | 0x06 | Write Single Register | Set DAC or trigger IR/RF | | 0x0F | Write Multiple Coils | Set multiple DO channels | | 0x10 | Write Multiple Registers | Set multiple DAC channels | +---------------+---------------------------+-------------------------------+ 4. Addressing Notes ------------------- All addresses in this document are 0-based Modbus protocol addresses. Examples: - Holding register address 100 is sent as 0x0064 in the Modbus PDU. - Some Modbus tools display holding register 100 as 40101 or similar. Use the tool's 0-based/1-based setting carefully. 5. Coils (Function Codes 0x01, 0x05, 0x0F) ------------------------------------------- 5.1 DO Output State and Control ------------------------------- +------------------------+----------------------+-----------------------------+ | Address Range | Description | Access | +------------------------+----------------------+-----------------------------+ | 0 .. DO_NUM-1 | DO output channels | 0x01 read, 0x05/0x0F write | +------------------------+----------------------+-----------------------------+ Write value for function code 0x05: - 0xFF00: turn ON - 0x0000: turn OFF Function code 0x0F supports only the normal DO output range starting at address 0. 5.2 DO Toggle Control --------------------- +-----------------------------+----------------------+--------------------------+ | Address Range | Description | Access | +-----------------------------+----------------------+--------------------------+ | 0x0100 .. 0x0100+DO_NUM-1 | Toggle DO channels | 0x05 write only | +-----------------------------+----------------------+--------------------------+ Write 0xFF00 to address 0x0100 + channel_index to toggle that output channel. Writing 0x0000 is accepted but does not toggle the output. 6. Discrete Inputs (Function Code 0x02) --------------------------------------- +------------------------+----------------------+-----------------------------+ | Address Range | Description | Access | +------------------------+----------------------+-----------------------------+ | 0 .. DI_NUM-1 | DI input channels | 0x02 read | +------------------------+----------------------+-----------------------------+ DI inputs are active-low in the firmware mapping: - Hardware low / active input returns 1 - Hardware high / inactive input returns 0 7. Holding Registers (Function Codes 0x03, 0x06, 0x10) ------------------------------------------------------ 7.1 DAC Output Registers ------------------------ +------------------------+----------------------+-----------------------------+ | Address Range | Description | Access | +------------------------+----------------------+-----------------------------+ | 0 .. DAC_NUM-1 | DAC output channels | 0x03 read, 0x06/0x10 write | +------------------------+----------------------+-----------------------------+ DAC write value range: 0 .. 255. Function code 0x10 supports only this DAC register range. 7.2 IR/RF Control Registers --------------------------- +----------+-------------+----------------------+-----------------------------+ | Address | Name | Description | Access | +----------+-------------+----------------------+-----------------------------+ | 0x0040 | IR_SEND | Send learned IR slot | 0x03 read, 0x06 write | | 0x0041 | IR_LEARN | Learn IR slot/port | 0x03 read, 0x06 write | | 0x0042 | IR_DELETE | Delete IR slot | 0x03 read, 0x06 write | | 0x0050 | RF_SEND | Send learned RF slot | 0x03 read, 0x06 write | +----------+-------------+----------------------+-----------------------------+ IR_SEND: - Value: IR memory slot index - Valid range: 0 .. IR_MEM_NUM-1 IR_LEARN: - High byte: IR memory slot index - Low byte: IR send port number, starting from 1 IR_DELETE: - Value: IR memory slot index - Valid range: 0 .. IR_MEM_NUM-1 RF_SEND: - Value: RF memory slot index - The selected RF slot must exist and be learned These registers exist only on board variants with the corresponding IR/RF feature enabled. Otherwise accesses return an illegal data address exception. 7.3 Energy Measurement Registers -------------------------------- Energy data is exposed as read-only Holding Registers and is read with function code 0x03. Each energy chip uses 68 holding registers. The base address is: base = 100 + chip_index * 100 where chip_index starts from 0. +--------------+----------------+----------------+--------------------------+ | Offset Range | Parameter | Format | Resolution / Notes | +--------------+----------------+----------------+--------------------------+ | 0 .. 19 | RMS_1..RMS_10 | uint32 CDAB | Current in A * 1000 | | 20 .. 39 | WATT_1..WATT_10| int32 CDAB | Power in W * 10 | | 40 .. 59 | Energy_1..10 | float32 CDAB | Energy in kWh | | 60 .. 61 | Energy_Sum | float32 CDAB | Total energy in kWh | | 62 | RMS_V | uint16 | Voltage in V * 100 | | 63 | Period | uint16 | Frequency in Hz * 100 | | 64 .. 65 | TPS1 | float32 CDAB | Temperature in deg C | | 66 .. 67 | PF | float32 CDAB | Power factor | +--------------+----------------+----------------+--------------------------+ Per-channel offsets: +----------------+----------------+----------------+--------------------------+ | Channel | Current Offset | Power Offset | Energy Offset | +----------------+----------------+----------------+--------------------------+ | 1 | 0 | 20 | 40 | | 2 | 2 | 22 | 42 | | 3 | 4 | 24 | 44 | | 4 | 6 | 26 | 46 | | 5 | 8 | 28 | 48 | | 6 | 10 | 30 | 50 | | 7 | 12 | 32 | 52 | | 8 | 14 | 34 | 54 | | 9 | 16 | 36 | 56 | | 10 | 18 | 38 | 58 | +----------------+----------------+----------------+--------------------------+ For 32-bit integer and float values, read two consecutive registers. The lower 16-bit word is returned first, followed by the upper 16-bit word. Examples: - Chip 1 current channel 1: read holding registers 100 and 101 - Chip 2 power channel 1: read holding registers 220 and 221 - Chip 1 voltage: read holding register 162 - Chip 1 frequency: read holding register 163 8. Input Registers (Function Code 0x04) --------------------------------------- +-------------------------------+----------------------+--------------------------+ | Address Range | Description | Format | +-------------------------------+----------------------+--------------------------+ | 0 .. ADC_NUM-1 | ADC input channels | uint16 raw ADC value | | 0x0100 .. 0x0100+SENSOR_NUM-1 | Temperature sensors | int16, deg C * 10 | | 0x0120 .. 0x0120+SENSOR_NUM-1 | Humidity sensors | int16, %RH * 10 | +-------------------------------+----------------------+--------------------------+ If a temperature or humidity sensor is invalid or not present, the returned value is 0x7FFF. 9. Board-Dependent Limits ------------------------- The following symbols depend on the compiled board model: - DO_NUM: number of digital outputs - DI_NUM: number of digital inputs - DAC_NUM: number of DAC outputs - ADC_NUM: number of ADC inputs - SENSOR_NUM: maximum temperature/humidity sensor slots - ENERGY_NUM: number of energy measurement chips N-series energy chip bases: +-------+------------+--------------------------------------+ | Board | ENERGY_NUM | Energy Holding Register Bases | +-------+------------+--------------------------------------+ | N10 | 1 | 100 | | N20 | 2 | 100, 200 | | N30 | 3 | 100, 200, 300 | | N60 | 6 | 100, 200, 300, 400, 500, 600 | +-------+------------+--------------------------------------+ 10. Exception Codes ------------------- +----------------+----------------------------+-------------------------------+ | Exception Code | Name | Meaning | +----------------+----------------------------+-------------------------------+ | 0x01 | Illegal Function | Unsupported function code | | 0x02 | Illegal Data Address | Unsupported address/range | | 0x03 | Illegal Data Value | Invalid value or quantity | | 0x04 | Slave Device Failure | Runtime failure or overflow | +----------------+----------------------------+-------------------------------+ 11. Request Size Limits ----------------------- - Read coils/discrete inputs: quantity 1 .. 2000 - Read holding/input registers: quantity 1 .. 125 - Write multiple coils: quantity 1 .. 1968 - Write multiple registers: quantity 1 .. 123