25. W5100S/W5500+RP2040 Raspberry Pi Pico<Modebus TCP Server Example>
25. W5100S/W5500+RP2040 Raspberry Pi Pico<Modebus TCP Server Example>
1 Introduction
Modbus TCP protocol is a data communication protocol widely used in industrial automation, building automation, energy management and other fields. It is based on the TCP/IP network, encapsulates the Modbus protocol in the TCP/IP protocol stack, uses Ethernet as the physical layer, and implements communication between devices through TCP connections.
W5100S/W5500 is an embedded Ethernet controller integrating a full hardware TCP/IP protocol stack. It is also an industrial-grade Ethernet control chip. This tutorial will introduce the basic principles, usage steps, application examples and precautions of W5100S/W5500 Ethernet FTP application to help readers better master this technology.
2 Protocol Introduction
2.1 What is Modbus TCP?
Modbus TCP is essentially the Modbus protocol (or Modbus RTU) running on an Ethernet TCP/IP network. Like Modbus RTU, Modbus TCP also works on the client/server principle, but in this case the client (master device) initiates requests and responses from the server (slave device). Any device can be a client or server.
Modbus TCP does not need to calculate the checksum because the lower layers already provide checksum protection. It uses the 10 Mbps Ethernet standard to transmit the entire structure of Modbus messages. Modbus TCP protocol provides fast communication between many devices in a single network.
2.2 Introduction to Modbus TCP instructions
The data frame of the Modbus TCP protocol can be divided into two parts: MBAP and PDU.
MBAP (Modbus Application Protocol header):
Transaction identification: an incrementing number, incremented each time a message is sent, and try not to repeat it. Because it occupies 2 bytes, the range is: 0~65535. Protocol identification: Fixed value 0, indicating Modbus TCP protocol. Length: equal to the length of the following field. Unit identifier: slave address, also known as slave id. PDU (Protocol Data Unit):
Function code: Modbus stipulates multiple functions, and each function is set with a function code. What operation do you want to perform on the slave machine? Just set it here. The slave machine will know what to do after reading this data. Data: For the master, it means what data in the slave register it wants to operate.
A variety of function codes are defined in the Modbus TCP protocol, including:
0x01: Read coil 0x05: Write a single coil 0x0F: Write multiple coils 0x02: Read discrete input 0x04: Read input register 0x03: Read holding register 0x06: Write a single holding register 0x10: Write multiple holding registers Each function code corresponds to Both operations and data formats differ.
For example, function code 0x01 is used to read coils, and the request format is "MBAP function code starting address H starting address L quantity H quantity L"
The response format is "MBAP function code data length data".
2.3 Requesting data process
During a typical Modbus TCP communication:
A Modbus TCP client (also called a master device) sends a request to a Modbus TCP server (also called a slave device). This request contains a function code (indicating the type of operation to be performed) and may also include a data address and value, depending on the function code.
After receiving the request, the Modbus TCP server processes it according to the function code. For example, if the function code indicates a read operation, the server will access the specified data address in its memory and prepare the corresponding data in response.
The Modbus TCP server then sends a response to the client. This response contains the function code and the requested data (for read operations) or a confirmation of the performed operation (for write operations).
The Modbus TCP client receives the server's response and processes the data as necessary.
2.4 Advantages of Modbus TCP protocol
The advantages of MODBUS TCP protocol include:
Flexible network topology: MODBUS TCP is based on Ethernet communication, so its network topology is more flexible. From the structure of one master and multiple slaves on the serial link, it has evolved into the structure model of multi-client/multi-server.
Easy to address: Using MODBUS TCP, the master device (client) can find the MODBUS slave device (server) by IP address and connect to another MODBUS RTU network through the MODBUS gateway.
Master-slave mode: The working principle of MODBUS protocol is based on the master-slave mode. In a network, the MODBUS protocol exchanges information through a request-response mechanism between the master device (client) and the slave device (server). This model makes the communication process clear and easy to understand.
Openness: MODBUS is an open protocol, which means it can be supported by equipment from any manufacturer, thereby improving interoperability between devices.
Simplicity: The MODBUS protocol is simple to understand, easy to implement and maintain.
Efficiency: MODBUS TCP protocol runs on the TCP/IP network, taking advantage of the advantages of the TCP/IP protocol, such as efficient data transmission, error detection and repair, etc.
2.5 Modbus TCP application scenarios
The Modbus TCP protocol has a wide range of application scenarios. The following are some main areas:
Industrial automation: Modbus TCP protocol is widely used in the field of industrial automation, especially in smart manufacturing and industrial Internet of Things. It allows reliable communication between devices to automate and control production processes.
Building automation: In the field of building automation, Modbus TCP protocol can be used to connect building equipment (such as temperature controllers, lighting systems, security systems, etc.) to achieve energy saving and comfortable indoor environment.
Energy Management: In the field of energy management, the Modbus TCP protocol can be used to monitor and control energy usage in systems. By connecting energy measurement equipment and control systems, real-time energy monitoring and optimized control can be achieved, reducing energy consumption and improving energy efficiency.
Process control: In the field of process control, Modbus TCP protocol can be used to connect sensors and actuators to achieve real-time monitoring and control. It can be applied in various industrial processes such as chemical industry, pharmaceuticals, food processing, etc.
Smart home: In the field of smart home, Modbus TCP protocol can be used to connect smart home devices (such as smart light bulbs, smart sockets, smart security, etc.) to achieve home automation and smart control.
3 WIZnet Ethernet chip
WIZnet mainstream hardware protocol stack Ethernet chip parameter comparison
Model | Embedded Core | Host I/F | TX/RX Buffer | HW Socket | Network Performance |
---|---|---|---|---|---|
W5100S | TCP/IPv4, MAC & PHY | 8bit BUS, SPI | 16KB | 4 | Max.25Mbps |
W6100 | TCP/IPv4/IPv6, MAC & PHY | 8bit BUS, Fast SPI | 32KB | 8 | Max.25Mbps |
W5500 | TCP/IPv4, MAC & PHY | Fast SPI | 32KB | 8 | Max 15Mbps |
W5100S/W6100 supports 8-bit data bus interface, and the network transmission speed will be better than W5500.
W6100 supports IPV6 and is compatible with W5100S hardware. If users who already use W5100S need to support IPv6, they can be Pin to Pin compatible.
W5500 has more Sockets and send and receive buffers than W5100S.
4 Modbus TCP example overview and usage
4.1 Flowchart
The running block diagram of the program is as follows:
4.2 Core preparation work
Software
Visual Studio Code
WIZnet UartTool
Modbus Poll
Hardware
W5100S IO module + RP2040 Raspberry Pi Pico development board or WIZnet W5100S-EVB-Pico development board
Micro USB interface data cable
TTL to USB
cable
4.3 Connection method
Connect the USB port of the PC through the data cable (mainly used for burning programs, but can also be used as a virtual serial port)
Convert TTL serial port to USB and connect the default pin of UART0:
RP2040 GPIO0 (UART0 TX) <----> USB_TTL_RX
RP2040 GPIO1 (UART0 RX) <----> USB_TTL_TX
When wiring using module connection RP2040
RP2040 GPIO16 <----> W5100S MISO
RP2040 GPIO17 <----> W5100S CS
RP2040 GPIO18 <----> W5100S SCK
RP2040 GPIO19 <----> W5100S MOSI
RP2040 GPIO20 <----> W5100S RST
Connect the PC and device to the router LAN port through network cables
4.4 Main code overview
We are using the official ioLibrary_Driver library of WIZnet. The library supports rich protocols and is easy to operate. The chip integrates the TCP/IP protocol stack on the hardware. The library also encapsulates the protocols above the TCP/IP layer. We only need to simply call the corresponding function to complete the application of the protocol. .
Step 1: Reference the corresponding library file in the modbus_tcp.c file.
Step 2: Define macro constants and define global variables.
Step 3: Define two functions, including a 1-second timer callback function (used to handle DHCP timeout processing) and a function to set the network address.
Step 4: The main function first initializes the serial port and SPI and detects the link. Then set the network address of W5100S. First use DHCP to obtain it. If it fails, use the preset static IP address. Then initialize the LED GPIO. Finally, the Modbus TCP state machine program is run in the main loop.
Step 5: In the state machine, first open a socket in TCP Server mode, and then wait for the client to connect. After the connection is successful, it will wait for the client's request information. After receiving the request information, it will parse the package content and respond with operations and replies.
/* main function */
int main()
{
struct repeating_timer timer; // Define the timer structure
/*mcu init*/
stdio_init_all(); // Initialize the main control periphera
wizchip_initialize(); // spi initialization
wizchip_setnetinfo(&net_info); // Configure once first
/*dhcp init*/
DHCP_init(SOCKET_ID, ethernet_buf); // DHCP initialization
add_repeating_timer_ms(1000, repeating_timer_callback, NULL, &timer); // Add DHCP 1s Tick Timer handler
printf("wiznet chip modbus tcp server example.\r\n");
network_init(&net_info); // Configuring Network Information
print_network_information(&get_info); // Read back the configuration information and print it
/* LED gpio init */
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
while (true)
{
do_Modbus(SOCKET_ID);
}
}
/* Do_Modubs function */
void do_Modbus(uint8_t sn)
{
uint8_t state = 0;
uint16_t len;
getSIPR(lip);
state = getSn_SR(sn);
switch (state)
{
case SOCK_SYNSENT:
break;
case SOCK_INIT:
listen(sn);
if (!b_listening_printed)
{
b_listening_printed = 1;
printf("Listening on %d.%d.%d.%d:%d\r\n",
lip[0], lip[1], lip[2], lip[3], local_port);
}
break;
case SOCK_LISTEN:
break;
case SOCK_ESTABLISHED:
if (getSn_IR(sn) & Sn_IR_CON)
{
setSn_IR(sn, Sn_IR_CON);
printf("Connected\r\n");
getSn_DIPR(sn, rip);
port = getSn_DPORT(sn);
printf("RemoteIP:%d.%d.%d.%d Port:%d\r\n", rip[0], rip[1], rip[2], rip[3], port);
if (b_listening_printed)
b_listening_printed = 0;
}
len = getSn_RX_RSR(sn);
if (len > 0)
{
mbTCPtoEVB(sn);
}
break;
case SOCK_CLOSE_WAIT:
disconnect(sn);
break;
case SOCK_CLOSED:
case SOCK_FIN_WAIT:
close(sn);
socket(sn, Sn_MR_TCP, local_port, Sn_MR_ND); // Sn_MR_ND
break;
default:
break;
}
}
/* mbTCPtoEVB function */
void mbTCPtoEVB(uint8_t sn)
{
int32_t ret;
if (MBtcp2evbFrame() != 0) // Frame received complete
{
uint16_t maxsize = 0;
if (pucASCIIBufferCur[0] == 0x01)//Check whether the device address is 0x01
{
if ((uint8_t)pucASCIIBufferCur[1] == 0x05)//Write to a single device
{
if ((uint8_t)pucASCIIBufferCur[4] == 0xff)
{
gpio_put(PICO_DEFAULT_LED_PIN, 1);
printf("LED ON\r\n");
}
else if ((uint8_t)pucASCIIBufferCur[4] == 0x00)
{
printf("LED OFF\r\n");
gpio_put(PICO_DEFAULT_LED_PIN, 0);
}
send(sn, recv_data, recv_len);
}
else if ((uint8_t)pucASCIIBufferCur[1] == 0x01)//Read Write to a single device
{
if (recv_data[recv_len - 1] != 0x01)
{
printf("len error!\r\n");
}
else
{
printf("Read OK!\r\n");
send_data[0] = recv_data[0];
send_data[1] = recv_data[1];
send_data[2] = recv_data[2];
send_data[3] = recv_data[3];
send_data[4] = 0x00;
send_data[5] = 0x04;
send_data[6] = 0x01;
send_data[7] = 0x01;
send_data[8] = 0x01;
send_data[9] = gpio_get(PICO_DEFAULT_LED_PIN);
send_len = 10;
send(sn, (uint8_t *)send_data, send_len);
memset(send_data, 0, send_len);
}
}
else
{
printf("error code!\r\n");
}
}
else
{
printf("address error!\r\n");
}
}
}
4.5 Results demonstration
1. Connect to W5100S using Modbus Poll
2. Send a write command to turn on the LED light
3. Set the read command to 0x01 and the read number to 1
4. Send a read command
5. The reading is successful and the LED status is displayed on the Modbus Poll.
5 Precautions
The address set and read must be 1, and the number read must be 1, otherwise information cannot be written or read. If you need to modify it, please modify the mbTCPtoEVB function in the mb.c file in the app/MODBUS_TCP_SERVER directory.
If we want to use WIZnet's W5500 to implement the example in this chapter, we only need to modify two places:
(1) Find the wizchip_conf.h header file under library/ioLibrary_Driver/Ethernet/ and modify the WIZCHIP macro definition to W5500.
(2) Find the CMakeLists.txt file under library and set COMPILE_SEL to ON. OFF is W5100S and ON is W5500.