Abstract: Modbus is a very popular communication protocol.

This article is shared by Jackwangcumt from The Huawei Cloud community “Understanding Modbus protocol for Internet of Things!”.

1, an overview of the

With the rapid development of IT technology, IT has entered the era of intelligence, among which the Internet of Things technology will occupy an increasingly important position in the future. According to the definition of Baidu Baike, Internet of Things (IOT for short) refers to the “Internet connected to all things”, which is the extension and expansion of the Network based on the Internet. The Internet of Things organically combines all kinds of information to realize the interconnection of people, machines and things at any time and any place. Technically, the core of the Internet of Things is communication protocol, that is, how to connect computers, things and people with the Internet according to the agreed communication protocol to carry out information communication, so as to realize intelligent identification, positioning, tracking, monitoring and management of people, machines and things.

Generally speaking, there are many common iot communication protocols, such as Bluetooth, Zigbee, WiFi, ModBus, PROFINET, EtherCAT, cellular, etc. Among many communication protocols of the Internet of Things, Modbus is a very popular one. It is a serial communication protocol, Modicon company in 1979 for the use of programmable logic controller (PLC) communication and developed, it can be said that it has become the industry standard of communication protocol in the industrial field. Its advantages are as follows:

  • Free of royalty

  • Easy to deploy

  • Flexible and less restrictive

2. Overview of ModBus protocol

The Modbus protocol uses the request-reply mechanism to exchange information between the Master (Client) and Slave (Server). The client-server principle is a communication protocol model in which a master device controls multiple slave devices. Note that the Master corresponds to the Client, while the Slave corresponds to the Server. The official website for Modbus is **www.modbus.org**. Currently, the official website recommends replacing the master-slave with the client-server. Protocol types include MODbus-RTU (ASCII), Modbus-TCP, and Modbus-plus. This paper mainly introduces the Modbus-RTU (ASCII) communication protocol principle. Standard Physical layer interfaces of Modbus protocol include RS232, RS422, RS485 and Ethernet interfaces.

The communication diagram is as follows:

Generally speaking, Modbus communication protocol has the following characteristics:

  • Only one host (Master) is connected to the network at a time

  • Only the Master device can initiate communication and send requests to the Slave device

  • The Master device can address each Slave individually using its specific address, or address all Slave devices simultaneously using address 0(broadcast)

  • The Slave device can only send replies to the Master device

  • The Slave device cannot start communication with the Master device or other Slave devices

Modbus protocol can exchange information using two communication modes:

  • Unicast mode

  • Broadcasting mode

Whether it is a request packet or a reply packet, the data structure is as follows:

That is, a packet (frame Data) consists of four parts: address (Slave Number)+ Function Codes (Data)+ Check. The address represents the ID address of the slave device as addressing information. The function code indicates what the current request does, such as read or write. Data represents the service data that needs to be communicated and can be determined based on the actual situation. The final check is to see if the data is incorrect. The function codes are described as follows:

For example, 03 means reading one or more binary values from the current register, while 06 means writing binary values to a single register. In order to simulate the Modbus communication protocol process, simulation software can be used here:

  • Modbus Poll (Master)

  • Modbus Slave

The specific installation process is not described here. Firstly, an Iot sensor device needs to be simulated, which is defined by Modbus Slave. Firstly, open this software and define a device with ID 1:

The function code is 03. In addition, to set connection parameters, an example interface is as follows:

Next, Modbus Poll software is used to simulate the host to obtain data from the device. First define a read/write message.

Then define a connection message:

Note: Use different names for the two COM ports.

After the communication is successfully established, the packet format is as follows:

Tx represents a request message and Rx represents a reply message.

3. ModBusJava implementation

Here is how to implement a Modbus TCP communication in Java. Here Java framework uses Spring Boot, first need to introduce Modbus library. Maven dependency library pom.xml is defined as follows:

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion > 4.0.0 < / modelVersion > < the parent > < groupId > org. Springframework. Boot < / groupId > The < artifactId > spring - the boot - starter - parent < / artifactId > < version > 2.5.5 < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name> Demo </name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <! --Modbus Master --> <dependency> <groupId>com.digitalpetri.modbus</groupId> <artifactId>modbus-master-tcp</artifactId> The < version > 1.2.0 < / version > < / dependency > <! --Modbus Slave --> <dependency> <groupId>com.digitalpetri.modbus</groupId> <artifactId>modbus-slave-tcp</artifactId> < version > 1.2.0 < / version > < / dependency > < the dependency > < groupId > org. Springframework. Boot < / groupId > <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

The dependency of Modbus library is com.digitalPetri. Modbus, which is divided into modbus-master-TCP and modbus-slave-TCP. In this example, Java project is used to simulate a Modbus Master terminal, and Modbus Slave software is used to simulate the Slave terminal. Modbus TCP/IP is selected as the communication connection mode, and THE IP address and port limit the Slave device. The schematic diagram is as follows:

The connection mode is Modbus TCP, so you need to adjust the connection mode in the connection configuration of Modbus Slave. The screenshot is as follows:

The Java core code is as follows:

package com.example.demo.modbus; import java.util.List; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import com.digitalpetri.modbus.codec.Modbus; import com.digitalpetri.modbus.master.ModbusTcpMaster; import com.digitalpetri.modbus.master.ModbusTcpMasterConfig; import com.digitalpetri.modbus.requests.ReadHoldingRegistersRequest; import com.digitalpetri.modbus.responses.ReadHoldingRegistersResponse; import io.netty.buffer.ByteBufUtil; import io.netty.util.ReferenceCountUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MBMaster { private final Logger logger = LoggerFactory.getLogger(getClass()); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private final List<ModbusTcpMaster> masters = new CopyOnWriteArrayList<>(); private volatile boolean started = false; private final int nMasters ; private final int nRequests ; public MBMaster(int nMasters, int nRequests) { if (nMasters < 1){ nMasters = 1; } if (nRequests < 1){ nMasters = 1; } this.nMasters = nMasters; this.nRequests = nRequests; Public void start() {started = true; ModbusTcpMasterConfig config = new ModbusTcpMasterConfig. Builder (" 127.0.0.1 "). The setPort (50201). SetInstanceId (" S - 001)" .build(); new Thread(() -> { while (started) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } double mean = 0.0; int mcounter = 0; for (ModbusTcpMaster master : masters) { mean += master.getResponseTimer().getMeanRate(); mcounter += master.getResponseTimer().getCount(); } logger.info("Mean Rate={}, counter={}", mean, mcounter); } }).start(); for (int i = 0; i < nMasters; i++) { ModbusTcpMaster master = new ModbusTcpMaster(config); master.connect(); masters.add(master); for (int j = 0; j < nRequests; j++) { sendAndReceive(master); Private void sendAndReceive(ModbusTcpMaster master) {if (! started) return; / / register 10 CompletableFuture < ReadHoldingRegistersResponse > future = master. The sendRequest (new ReadHoldingRegistersRequest (0, 10, 0); WhenCompleteAsync ((response, ex) -> {if (response! = null) { //System.out.println("Response: " + ByteBufUtil.hexDump(response.getRegisters())); System.out.println("Response: " + ByteBufUtil.prettyHexDump(response.getRegisters())); //[00 31 00 46 00 00 00 b3 00 00 00 00 00 00 00 00] byte[] bytes = ByteBufUtil.getBytes(response.getRegisters()); System.out.println("Response Value = " + bytes[3]); / / register according to the business case for numerical ReferenceCountUtil release (response); } else { logger.error("Error Msg ={}", ex.getMessage(), ex); } scheduler.schedule(() -> sendAndReceive(master), 1, TimeUnit.SECONDS); }, Modbus.sharedExecutor()); } public void stop() { started = false; masters.forEach(ModbusTcpMaster::disconnect); masters.clear(); } public static void main(String[] args) {new MBMaster(1, 1).start(); }}Copy the code

First, ModbusTcpMasterConfig is used to initialize the configuration information of a ModbusTcpMaster, such as the IP address (127.0.0.1) and port number (50201), which must be consistent with that of the Slave. Second, the configuration information Config is passed as a parameter to the ModbusTcpMaster object to build a Master instance. Finally, with the master. The sendRequest (newReadHoldingRegistersRequest (0, 10), 0) objects to query the data, the function code for 03, register data of 10. After Modbus Slave is connected, the setting interface is as follows:

Run the Java program. An example of console output is as follows:

In this way, it can be known that the 15 positions from 0 to F in the returned packets have the required service data. The specific location to obtain the service data depends on the Settings of the Slave device.

Click to follow, the first time to learn about Huawei cloud fresh technology ~