Revolution Pi goes Modbus

Our system upgrade from Raspbian Wheezy to Jessie comes with a great bonus: We added master and slave functionalities for the popular Modbus RTU and Modbus TCP protocols. So you no longer need to use any external gateway modules for Modbus communication.

Visitors of our booth at Hannover Fair could already watch a RevPi Core communicating with several Modbus slave devices without using any external modules:

We connected an RFID reader via Modbus RTU. Its status and the last read ID of an RFID card was written into the central process image of a RevPi Core. Visitors could choose one of a bunch of cards each one labeled with an EU country’s flag and hold the card in front of the reader. Our Python software reacted by displaying the country’s data and map on a 5” HDMI screen and playing the national hymn over headphones. A huge ticker display, connected via Modbus TCP to the RevPi Core showed the country’s name. When there was no card to be read the ticker display showed the hall’s temperature measured by a Modbus TCP thermometer which transmitted its values to the central process image.

Modbus TCP uses the Ethernet connector of the RevPi Core (the RJ45 connector at the front panel) or any other added Ethernet connection (e.g. USB WLAN adapter) supporting TCP/IP. Modbus RTU uses any TTY device mounted under Linux. But you can’t use the internal Compute Module’s UART interface because this is reserved for the PiBridge. So RTU only works with (3rd party) USB to serial converters.

Data exchange with our Modbus functionality is always done via the central process image. Any incoming data is written to this memory area and outgoing data is read from there. The Modbus protocol is operated totally self-contained by “virtual adapters”. Your control software or other applications just need to put the data into the process image or get it from there. You do this the same way you would exchange data with DIO modules, etc.

You just need to search the list of virtual adapters in PiCtory (our browser operated configuration tool) for the Modbus adapter of your choice (master or slave, TCP or RTU). Drag and drop the adapter on the workbench, configure it, save the configuration and restart PiBridge: That’s all to start Modbus communication running completely independent automatically in the background. You could even use multiple adapters e.g. if 32 registers per adapter are not enough for your devices or if you need to communicate to more than one IP address (only one slave IP per virtual master adapter is possible).

How can you configure such a virtual adapter? Let’s start with Modbus RTU master:

Such a virtual master adapter offers you a maximum of 32 16-bit words plus 32 1-bit values for incoming data into the process image and a maximum of 32 16-bit words plus 32 1-bit values for outgoing data from the process image. Like with all modules you can give these addresses individual symbolic names of your choice. You also need to configure the TTY interface for each RTU device (device name under Linux, bitrate, parity, etc.). It’s the business of a Modbus master to cyclically transport data to or from a slave device. This tasks are configured in a separate window which will be described soon. There are additional status bytes for each of the tasks in the process image which contain possible Modbus error status information. 32 additional output bool values are used to reset the status bytes.

But let’s talk about the tasks which need to be configured. To define a maximum of 32 of such tasks you need to right click on the virtual module and then on “extended data”. This will open a new window with an empty list. You can up to 32 tasks to this list which each need values for the following columns:
Modbus slave address, Modbus function code (“read coil” etc.), Modbus register address, number of registers for data exchange, time interval in ms. So this will define how often the master adapter will send requests to a specific slave to send back the content of N registers, starting with the defined address. Or (by using the respective function code) you define a cyclical write task. All register function codes work with 16 bit wide registers of the slave and therefore for each task using a register function code you need to select a 16 bit data word of the process image from a drop down selector. For coil function codes which work with 1 bit you can only select 1-bit values from the process image. You can choose one of the following function codes for each task:
READ COILS, READ DISCRETE INPUTS, READ HOLDING REGISTERS, READ INPUT REGISTERS, WRITE SINGLE COIL, WRITE SINGLE REGISTER, WRITE MULTIPLE COILS, WRITE_MULTIPLE_REGISTERS
Modbus TCP master modules are configured quite similar. You need to define one slave IP address per master adapter. This is why there is no slave address column in the task list but instead you can define a unit ID according to Modbus specifications.

Using a Modbus slave adapter is even easier. There are simply 32 input and 32 output registers which are respective 16-bit values of the process image. If a Modbus master is sending his request to the RevPi Core the virtual slave module only answers if its configured slave address matches the request. It then sends the content of a process image value which matches the register address. Writing to the process image when receiving a write request works similar. When using a Modbus TCP slave adapter the Ip address of the RevPi’s Ethernet connection must fit to the request just like the Ethernet’s service port which can be configured for each TCP slave adapter. Virtual Modbus slave modules only support the function codes “read input registers”, “write single registers”, “write multiple registers” and “read holding registers“. Coil functions are not implemented.

Let us close this newsletter talking about limits: While the maximum of 32 tasks per adapter is given by code and can only be extended by using more than one adapter, the maximum number of registers is only limited by the RAP file definitions of the virtual adapter. You could change this number by editing the RAP file as long as you keep the 4k limit of the process image in mind.
Cycle times of 1 ms are theoretically possible but this value can’t be reached by complex Modbus RTU configurations: Transmission of all data packages over the serial line alone would take more time than 1 ms. In reality it is hard to predict any minimum cycle time which can be achieved with a specific constellation as there are many limiting parameters to be taken in account.

Then who should still use an external Modbus gateway module?

It is generally not easy to use RevPi gate modules with a RevPi core: The gateway does a self-contained cyclical data exchange with the field bus (in our case the Modbus). There is no possibility to do any programming or (with Modbus slave modules) even configuration of this process (a Modbus slave has just the slave address to be configured, there is nothing else configurable). Any data for this exchange with the field bus is done with a memory area of the gateway slave module.
There is another, second cyclical data exchange which is running asynchronously to the first using the PiBridge and copying the data to and from the central process image of the RevPi Core. While there is a constant relation between Modbus register addresses and address offset of the data memory area of the gateway module there is no such fix relation to the offset at which you can find the Modbus values in the central process image. This offset depends on the module configuration of the complete modular system. Yes this is a bit tricky but you must keep in mind that our gate modules were not specifically developed for use with RevPi Core but had been developed long before for use as modular gateway pairs: Two of them attached together can translate one field bus into another.
Using the Modbus RTU gateway module together with RevPi Core only makes sense when you do not want to use USB to RS485 convertes. Using the Modbus TCP gateway module together with RevPi Core only makes sense when you strictly want to separate Modbus from other Ethernet connections (like the Internet) and do not want to use USB WLAN or LAN adapters.