# Example description ## 1. Introduction This example provides functional demonstration of RTU / TCP master and slave. Using `gcc` under `WSL` or `Linux`, you can directly `make all` to compile all examples and run the test program on your computer. Directory Structure: | Name | Description | | ---- | ---- | | common | public source code | | figures | materials | | rtu_master | RTU master example | | tcp_master | TCP master example | | slave | RTU + TCP slave example | | rtu_p2p | RTU peer-to-peer transfer file | | rtu_broadcast | RTU broadcast transmission file (sticky packet processing example) | ## 2. Use The tools you need to prepare are as follows: - Virtual serial port software - Modbus Poll - Modbus Slave Type `make clean` 、 `make all` on the command line. ### 2.1. Host - RTU (rtu_master) - Use virtual serial port software to virtualize a pair of serial ports ![VirtualCom](./figures/VirtualCom.jpg) - Open `Modbus Slave` and set as shown below ![ModbusSlaveSetup](./figures/ModbusSlaveSetup.jpg) - `Modbus Slave` connection, set as shown below ![ModbusSlaveRTUConnection](./figures/ModbusSlaveRTUConnection.jpg) - Enter the `rtu_master` directory, `./RtuMaster /dev/ttySX` to run the `RTU` host example, `ttySX` is the other of a pair of virtual serial ports ![RTUMaster](./figures/RTUMaster.jpg) - TCP (tcp_master) - Open `Modbus Slave`, `SetUp` settings are consistent with `RTU` - `Modbus Slave` connection, set as shown below ![ModbusSlaveTCPConnection](./figures/ModbusSlaveTCPConnection.jpg) - Enter the `tcp_master` directory, `./TcpMaster 127.0.0.1 502` and run the `TCP` host example ![TCPMaster](./figures/TCPMaster.jpg) ### 2.2. Slave machine - This example (slave) provides both `RTU` and `TCP` slave function demonstrations, controlling the same memory. `TCP` can connect to a maximum of 5 clients. Each client has a no-data timeout of 10s and will be automatically disconnected after 10s. - The example supports all function codes (except function code 0x07). - `bit`, `input_bit`, `register`, `input_register` registers are defined separately for each file. - Use `agile_modbus_slave_util_callback`. - Register address field: | Register | Address range | | --- | --- | | Coil register | 0x041A ~ 0x0423 (1050 ~ 1059) | | Discrete input register | 0x041A ~ 0x0423 (1050 ~ 1059) | | Holding register | 0xFFF6 ~ 0xFFFF (65526 ~ 65535) | | Input register | 0xFFF6 ~ 0xFFFF (65526 ~ 65535) | **Note**: Reading and writing other address registers can be successful, but the values ​​are all 0. use: - Use virtual serial port software to virtualize a pair of serial ports ![VirtualCom](./figures/VirtualCom.jpg) - Enter the `slave` directory, `./ModbusSlave /dev/ttyS2 1025` to run the example /dev/ttySX: One of the virtual serial ports 1025: Listening port number. If you do not have `root` permissions, the port number must be greater than `1024` - Open `Modbus Poll` and set and connect RTU as shown below ![ModbusPollSetup](./figures/ModbusPollSetup.jpg) ![ModbusPollRTUConnection](./figures/ModbusPollRTUConnection.jpg) - Open 5 `Modbus Poll`, set the same as RTU, and connect as shown below ![ModbusPollTCPConnection](./figures/ModbusPollTCPConnection.jpg) - Effect demonstration ![ModbusSlaveShow](./figures/ModbusSlaveShow.jpg) - Timeout disconnect demonstration Close the poll interface of `Modbus Poll` and look at the console print to see the close message. ![ModbusSlaveTimeoutShow](./figures/ModbusSlaveTimeoutShow.jpg) ### 2.3. RTU transmission file ![ModbusProtocol](./figures/ModbusProtocol.jpg) Use `0x50` as the special function code for transferring files. File data is transferred in packets, with a maximum size of 1024 bytes per packet. `Data` field protocol definition: - Host request | command | number of bytes | data | | ---- | ---- | ---- | | 2 Bytes | 2 Bytes | N Bytes | Order: | Command | Description | Data | | ---- | ---- | ---- | | 0x0001 | Start sending | File size (4 Bytes) + file name (string) | | 0x0002 | Transmission data | Flag (1 Byte) + file data | Logo: | Status | Description | | ---- | ---- | | 0x00 | The last packet of data | | 0x01 | Not the last packet of data | - Slave response | Command | Status | | ---- | ---- | | 2 Bytes | 1 Byte | state: | Status | Description | | ---- | ---- | | 0x00 | Failure | | 0x01 | Success | - Use virtual serial port software to virtualize 3 serial ports to form a serial port group Here I use the MX virtual serial port ![VirtualComGroup](./figures/VirtualComGroup.jpg) #### 2.3.1. Point-to-point transmission - Enter the `rtu_p2p` directory and open `Linux Shell`. The demonstration effect is as follows **Notice**: - The transferred files must be general files. Executable files, directories, etc. are not supported. - The file path must be the path in `Linux` environment - After the slave receives the data, the file name is modified (slave address_original file name) and written in the current directory. ![rtu_p2p](./figures/rtu_p2p.gif) #### 2.3.2. Broadcast transmission This example mainly demonstrates the use of `frame_length` in `agile_modbus_slave_handle`. In `broadcast_master`, use broadcast address 0 and send data packets every 5ms. At the same time, 100 bytes of dirty data are sent after each packet of data. ```c int send_len = agile_modbus_serialize_raw_request(ctx, raw_req, raw_req_len); serial_send(_fd, ctx->send_buf, send_len); //dirty data serial_send(_fd, _dirty_buf, sizeof(_dirty_buf)); ``` Under such a fast data flow, `broadcast_slave` must use the `frame_length` parameter in `agile_modbus_slave_handle` to handle sticky packets. - Enter the `rtu_broadcast` directory and open `Linux Shell`. The demonstration effect is as follows **Notice**: - The transferred files must be general files. Executable files, directories, etc. are not supported. - The file path must be the path in `Linux` environment - After the slave receives the data, the file name is modified (slave address_original file name) and written in the current directory. ![rtu_broadcast](./figures/rtu_broadcast.gif)