Menu Zamknij

Automating modbus communication

Modbus is well known industry protocol for communication between electronic devices. It is an application layer messaging protocol, positioned at level 7 of the OSI model. Despite that it had been developed in 1979, the protocol is still heavily used by many manufacturers. It proved to be very efficient and useful mainly because its simplicity. Even simple devices and control boards will handle the protocol. It is good to know at least basics of how to use Modbus especially in the era of IoT.

In this post I show how to create a simple Windows application for Modbus IP communication. The same logic as described in this post can be used in frameworks for automatic testing of Modbus devices.

Modbus communication schemes

There are many implementations of the protocol in lower level of ISO/OSI model. Two of them are:

RTU (Serial port based)

Uses master-slave architecture, where clients are connected to the same communication medium as the master. Only master can initiate communication to particular slave. Each slave has its own id. The master uses that id to address the message. The communication (according to the protocol description) should be time based. However, today’s devices mostly work well even without that restriction.

IP (Internet Protocol based)

The communication on the high level is very similar to HTTP. It uses request – response paradigm. The device sends a message over the IP network and synchronously waits for the response (confirmation). I will use that type of communication for building sample application.

Application implementation

First of all we need to implement communication according to the protocol itself. As the post can’t take too much space, I won’t show how to develop the protocol from scratch. Instead I will use modbuslib (https://libmodbus.org/) library. The library is LGPL licensed and implements both IP and RTU communication schemes. That is exactly what we need. If you would also like to use modbuslib in your projects, remember that using LGPL has some consequences.

Preparation

The modbuslib library is available in a form of source files and has to be compiled before we can use it. The compilation process is described on the library’s page and I will not repeat it here. If you find it complicated or have difficulties in compiling it, let me know. I will do my best to help. After the compilation process in Windows environment we get modbuslib.dll. That is a windows dynamic link library with all the required functions that we need for our application.

For that project I will use C language. It has always been the language for low level operations. Hence, I will use it as a good fitter to the subject 🙂 My environment consists of Eclipse for C and GCC compiler. You can of course use another technology (see my another post on how to use native DLLs in Java).

First, we need to create C project using C manged build template in Eclipse. Having that, we need to tell the linker where modbuslib is, so that it can link objects’ description into our application. Those settings can be found in Project properties / C/C++ Build / Settings. Depending on what compiler you use, settings names may differ. I use MinGW with GCC. Remember that you have to configure both correct include path (i.e. path where header files are located) and library path (path where modbuslib.dll is located).

Write the code

Our application will read particular holding register and display its value on the screen.  All necessary functions to accomplish this goal are defined in modbus.h header file.

Initialize Modbus context

modbus_t structure keeps information about the context od modbus connection. We need to properly initialize the structure with the IP address and port of the remote device. In my case, the device that I connect to is available under the IP address 192.168.1.2 and listens on port number 502.

modbus_t *mb;
mb = modbus_new_tcp ("192.168.1.2", 502);
if (mb == NULL) {
    fprintf (stderr, "Unable to create connection context");
    return -1;
}

Connect to remote device

After having the context initialized, we can now try to connect to the device.

if (modbus_connect (mb) == -1) {
    fprintf (stderr, "Unable to connect to the device");
    modbus_free (mb);
    return -1;
}

Read register and display value

As in typical C program, values have to be stored in some structures, that have to be already initialized. In my case I’ve prepared structure named tab_reg that is an array of  unit16_t. If you prepare the code on your own, please remember to clear this array before using it. Having the tab_reg defined, we can use it to read a holding register. I will read register with id = 200.

if (modbus_read_registers (mb, 200, 1, tab_reg) == -1) {
    fprintf (stderr, "Error reading register from device");
} else {
    printf("%d\n", tab_reg[0]);
}

Finally, we have to clean up resources

    modbus_close(mb);
    modbus_free (mb);

And that’s it. We have created the application that reads holding register from Modbus device and displays its value on the screen.

I encourage you to create Modbus communication app on your own. It is really satisfying to see that the software can work together with industry level devices.

Conclusions

Modbus is a powerful protocol that is commonly used in different kind of devices. I have presented how to prepare simple application that allows to automatically read holding register from modbus device. Such applications an be combined in the framework for automatic testing of modbus devices. The ability to automatically test the device can significantly speed up the overall product testing process. Moreover, such process becomes more repeatable and human error are minimized.

If you look for framework for automatic testing Modbus devices with configurable workflows, contact me.

Happy coding.