[아두이노#615] Arduino에 W5500을 연결해서 C#윈폼으로 모드버스(modbus) TCP의 프로토콜에 대해서 이해하고 통신하는 방법 알아보기!(녹칸다의 아두이노 시즌2)
Arduino + W5500 demonstrates Modbus TCP with FC15, FC06, FC04, and 32-bit float data handling for registers and multiple coil control.

1. Overview
In this post, we go beyond a simple Modbus TCP example and dive into practical implementation details using Arduino UNO + W5500 Ethernet and a C# WinForms master application.
You will learn how to:
- Control multiple coils with FC15 (Write Multiple Coils).
- Update variables with FC06 (Write Single Register).
- Read input registers with FC04 (Read Input Registers).
- Safely exchange 32-bit floating-point values.
We also explain the Modbus TCP frame structure, endianness, word-order pitfalls, and provide debugging tips from a chip engineer’s perspective.
2. Modbus TCP Frame Structure
- MBAP Header (7 bytes):
Transaction ID (2) + Protocol ID (2, always0x0000
) + Length (2) + Unit ID (1) - PDU: Function Code (1) + Data (N)
Coils & Registers
- Coils/Discrete Inputs: bit-addressable (mapped to Arduino GPIO).
- Holding/Input Registers: 16-bit word-based (mapped to variables or sensor values).
👉 Important: TCP removes CRC (unlike RTU) and adds MBAP for reliable transport.
3. Function Codes in Action
FC15 – Write Multiple Coils
- Request: Start Address + Quantity + Byte Count + Coil Bits (LSB = lowest address).
- Example: Write 10 coils starting at address 19 with pattern
11001101 00000001
. - Response: Echoes start address and quantity written.
FC06 – Write Single Register
- Writes one 16-bit register.
- Meaning (signed/unsigned, scaling) must be agreed upon by both master & slave.
FC04 – Read Input Registers
- Request: Start address + quantity (1–125).
- Response: Byte count + register data (2 bytes each).
- Floats: 1 float = 2 registers (4 bytes). Request 4 registers for 2 floats.
⚠️ Beware of word-order differences (ABCD, BADC, CDAB, DCBA). Always fix one convention.
4. Endianness & Word Order Pitfalls
- MBAP Header: Always big-endian (network order).
- Registers: Often big-endian by spec, but Arduino/W5500 code may use little-endian internally.
- Coil Packing: LSB of each byte = lowest coil address.
- Floats: Must align word order + byte order consistently between master & slave.
5. Arduino UNO + W5500 Implementation
- Ethernet Init:
Configure MAC, IP, and open Modbus TCP port 502.
Ethernet.begin(mac, ip, gateway, subnet);
EthernetServer modbusServer(502);
2. Receive Loop:
- Read MBAP (7B), then payload according to Length.
- Parse Function Code → handle request.
- Return proper response frame.
3. Error Handling:
- Illegal Function (0x01), Illegal Data Address (0x02), Illegal Data Value (0x03).
4. Performance Notes:
- W5500 has 8 sockets, 32KB total buffer (default 2KB each).
- RX halts if free size < packet size → keep frames small and predictable.
6. C# Master (WinForms) Implementation
- Option A – Raw Socket:
Build MBAP + PDU manually, send viaTcpClient
, parse response. - Option B – NModbus4 Library:
Simplifies frame building, parsing, and exception handling. - Tips:
- Always add timeout & retry logic.
- Parse exception frames (FC | 0x80).
- Display coil/register values in real time.
7. Example Address Map
- Coil 0 → Arduino D2
- Coil 1 → Arduino D3
- Coil 2 → Arduino D4
- Coil 3 → Arduino D5
- Coil 4 → Arduino D6
- Coil 5 → Arduino D7
👉 Use:
- FC15 to batch-control LEDs.
- FC06 to write integer values to Arduino variables.
- FC04 to read sensor registers.
- FC04 with 4 registers to read 32-bit float data.
8. Extended Examples (from C# WinForms Integration)
- Write Multiple Coils (FC15): Toggle multiple LEDs at once.
- Write Single Register (FC06): Update Arduino variable remotely.
- Read Input Registers (FC04): Fetch 32-bit float sensor values.
💡 Mapping rule: Arduino GPIO pins ↔ Modbus coil addresses (e.g., D2 → Coil0).
💡 Use bit operations for packing/unpacking coil data.
9. Troubleshooting Checklist
- Wrong endian/word order → garbage float values.
- Length mismatch → master rejects frame.
- Coil packing error → wrong LED toggles.
- W5500 buffer overflow → incomplete frame, fix with chunked reads.
10. Conclusion
By extending Modbus TCP beyond the basics, you can:
- Control multiple coils at once.
- Write signed/unsigned registers.
- Read input registers in bulk.
- Safely exchange 32-bit floating-point data.
With Arduino UNO + W5500 (slave) and C# WinForms (master), this setup becomes a practical solution for:
- Industrial control
- IoT gateways
- Embedded prototyping
✅ SEO Keywords
Arduino Modbus TCP
W5500 Ethernet module
FC15 multiple coil write
FC06 single register write
FC04 read input registers
32-bit float Modbus data
Modbus RTU vs TCP differences