Introduction
Data exchange between controllers is very important to easily control a system, and using the Modbus protocol is one of the best solutions.
The Modbus RTU protocol is used worldwide in many areas, such as automation and industry, and is very useful in master-slave systems.
If you are interested in how Modbus works, see the following post for an in-depth understanding of the protocol. This post will explain the communication between a M-Duino PLC as master and the ESP32 PLC as slave.
Requirements
Connection between industrial PLCs
You will need a pair of twisted wires to connect both controllers. Using Half Duplex configuration on the M-Duino PLC, connect both wires to RS485 pins B- and A+ pins. These two wires must be connected to the RS485 pins of the ESP32 as well, like this:
M-Duino PLC pin B- to ESP32 PLC pin B-
M-Duino PLC pin A+ to M-Duino PLC pin A+
Remember: You will need to configure the switches to work with RS485 and ESP32 PLC . Turning off the third switch will enable RS485 communication.
Check the serigraphy of the PLC if having any doubt.
M-Duino code
As the M-Duino based PLC will act as a master, you need to program it to make requests every few seconds. The program will make two types of requests: Write Single Coil or Write Multiple Coils.
Before uploading the code, install the Industrial Shields boards for Arduino IDE and change the board to your M-Duino PLC model. Remember also to install the Modbus library here.
Let's focus our attention on the loop function. Every 1.5 seconds, there is a 50% chance the program sends a writeMultipleCoils() request or a writeSingleCoil() one.
On the one hand, if a writeMultipleCoils() is chosen, it first creates an array with 5 random values, one for each digital output of the slave controller. Then the request is made with the slave address (31), the first coil to write (addres 0), the array and the number of outputs to trigger.
On the other hand, if a writeSingleCoil() is chosen, it makes a request with the slave address number (31), the coil to write (address 0) and the value to write (0 or 1).
ESP32 code
Before getting into the ESP32 code, let's use a simple code to see what is the M-Duino PLC (master) sending.
First, change the board to your ESP32 PLC model in the Arduino IDE. Then, go to File -> Examples -> RS485 -> Receive. Upload it and open the Serial Monitor. If you have programmed the M-Duino PLC correctly, it will look something like this:
This is a Modbus ADU (Application Data Unit). The first byte shows the slave address, 31 (0x1F) in the example, and the second tells us what type of request the master is trying to do, writeMultipleCoils (0x0F) in this case.
Then 2 bytes are used to tell the first address to write to (0x0000 in this case). The next two shows how many outputs the master is trying to write to (0x0005).
The next one (0x01) gives you the byte count, and the following tells you what to write at every coil (0x05). 0x05 in binary is 00000101, so only output 0 and 2 will be turned on (bits number 0 and 2 are set to 1). The last 2 bytes are for the crc redundancy.
Now that you know what every byte is for in a Modbus ADU, let's get into the code. Notice that no extra libraries have been used, as you only have 2 types of requests and it is very easy to implement the functions:
First, define the slave address, 31, just like in the master code. After that, define all 5 output pins you want to trigger. An ESP32 38R PLC was used in the example, but maybe your PLC model does not any have relay outputs, so take that into consideration and change the array to match your output pins.
In the setup function Serial and RS485 are started with their own baudrates (both the baudrates of the Modbus object of the M-Duino PLC, and the RS485 of the ESP32 must be the same).). Having said that, let's jump straight into the loop function.
There, you call the readModbus() function which will get all the Modbus ADUs from the master and store them in the array called aux. It already identifies between 8 byte ADUs (writeSingleCoil()) and 10 byte ADUs (writeMultipleCoils()).
Then, all that is left is to differentiate between Single and Multiple writes and call the proper function with the necessary parameters.
If you want to implement ,ore types of Modbus requests, simply check the function code for that request and add an "else if (aux[1] == function code)" below the last one and create another function to do the job, following the structure of the already created functions. To implement a read request, remember that you will need to send some data back to the master controller.
And that's all!
In this post you have learned how Modbus ADU works and how easy it is to process requests and act accordingly without the need for external libraries.
Now it is time to review Part 2 to learn the opposite case, ESP32 PLC as master and M-Duino PLC as slave.
How to communicate M-Duino PLC and ESP32 PLC with Modbus RTU - Part 1