Wiznet makers

irina

Published September 24, 2025 ©

112 UCC

5 WCC

89 VAR

0 Contests

0 Followers

0 Following

Original Link

[아두이노#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.

COMPONENTS
PROJECT DESCRIPTION

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, always 0x0000) + 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

  1. 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

  1. Option A – Raw Socket:
    Build MBAP + PDU manually, send via TcpClient, parse response.
  2. Option B – NModbus4 Library:
    Simplifies frame building, parsing, and exception handling.
  3. 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

 

 

Documents
Comments Write