How-To: Building a PLC Project with Modbus Communication
Modbus is a communication protocol stemming from the early days of Modicon PLCs, but is still common today. These two example implementations of Modbus transactions will get you started.
Modbus is a communication protocol commonly used with input/output (I/O) data to share information at this simple device network level. It is neither necessary nor beneficial to rely on protocols that require massive packets of configuration data when only simple data transmissions are requested.
On the other hand, perhaps it is useful to adopt standardized protocols to some limited extent in order to take advantage of the many sockets and plugs that exist in modern equipment, such as Ethernet ports.
Figure 1. Modbus TCP takes advantage of common standards, while still maintaining a simplified code function code and address structure.
I/O and data exist as either discrete (boolean) or multi-bit words (as integers or floating-point values). Therefore, if we wish to share information with I/O devices, it would seem logical to assume that all we must determine is whether the information is discrete or analog, and whether we are reading or writing the information. This isn’t too far off from reality.
Modbus Function Codes
There is a small selection of codes used to identify what type of information we want to use, and what task we wish to perform.
In short, there are 4 things we can do with Modbus:
- Read bits
- Write bits
- Read words (usually words are 16-bit integers)
- Write words
In slightly longer detail, those words are called ‘registers’, and those ‘bits’ may be output coils or input contacts.
So the slightly elaborated list of possible Modbus functions includes:
- Read Contacts
- Read Coils
- Read Registers
- Write Coils
- Write Registers
Note that you cannot write to an input contact - only the real-world device (button, sensor) has the ability to write itself. You can’t force a pushbutton to push.
The complete list of available function codes for Modbus I/O commands is the following:
|Description||Function Code Number|
|Read Contacts (or Inputs)||2|
|Read Output Registers||3|
|Read Input Registers||4|
|Write One Single Coil||5|
|Write One Output Register||6|
|Write Multiple Coils||15|
|Write Multiple Output Registers||16|
The only other factor that must be identified in order to share information is the address of a contact, coil, or register.
When a Modbus device is manufactured, each terminal or task (for example, the first digital output of a remote I/O terminal, or maybe the stop command for a VFD) will have the built-in address of 0. Therefore, if you wish to energize that output, you must use the following structure:
- Function code 5, starting address 0.
If you wish to turn on the first three digital outputs, the structure would look like this:
- Function code 15, starting address 0, now with a length of 3.
The same goes for writing or reading, and for discrete and word information.
Some controllers allow you to choose the Modbus address for each I/O terminal manually. This provides a lot of flexibility and customization over which terminals are accessible easily from other devices.
Modbus for remote terminal units (RTU) is a method of structuring a data packet so that the data transmission includes the following pieces:
Node # (since RS-232 and 485 networks are defined by nodes), the function code, the starting address, and the ending address.
In RTU, all data is formatted as binary equivalents of the decimal codes, but the good news is that the programmer usually doesn’t need to know or care about how it does this.
When you press buttons on a keyboard, each letter, number, and character is given a special standardized code. In the Modbus ASCII system, the same data is provided as for the Modbus RTU, except rather than using binary equivalents of the function codes, it uses the ASCII equivalents.
Again, the good news is that all the programmer needs to understand is whether the device is programmed for Modbus RTU or ASCII, and choose the appropriate format from a list.
In summary, all the programmer needs to know for both RTU and ASCII is the node #, function code, starting address, and length (if multiple).
Not to sound redundant, but the programmer once again only needs to know those same basic elements as before.
However, in the TCP structure, the network communication is handled using industry-standard industrial Ethernet messaging. This means that an Ethernet port can be used as the physical connection for a Modbus TCP device. It can even be on the same network as the rest of the Ethernet devices, as long as the network parameters can be configured properly (the IP address, subnet mask, etc).
The IP address is usually able to be changed with external software, or sometimes by means of DIP switches embedded in the device.
How does this affect the programmer?
She or he must know: the device address (not called a node anymore, but the same thing), the function code, the starting address, and the length (if multiple).
No explanation is complete without a couple of examples as to how this might look.
In an Allen Bradley PLC, such as the Compact or ControlLogix series, an Add-On Instruction (AOI) for Modbus is available from Rockwell Automation for Modbus TCP transactions. This must be imported into the code to be used.
When added, this will create a Controller-Scope tag set for the Modbus Client allowing up to 5 function code tasks (called transactions), each of which can be enabled or disabled with a BOOL tag.
First, the IP address of the client is added into the appropriate tag field, shown in the figure below. In this example, no pre-configured device with an EDS was ever added to the project tree, as the entire reason for this project is for those devices which aren’t simply ‘plug and play’ - we don’t always have that luxury.
Figure 2. Modbus address for Rockwell AOI. Author’s image
To elaborate an example, pretend you have a remote I/O terminal with 8 inputs and 8 outputs.
You wouldn't want to energize all 8 outputs all the time, but you would want to monitor all 8 inputs continuously.
From our function code list, this would be function code #2, with a length of 8.
Figure 3. Rockwell AOI example for reading multiple coils. Author’s image
In this example, the Automation Direct Productivity PLC will be used to demonstrate a Modbus RTU communication over an RS-485 serial interface at node 3.
First, the serial communication ports on this PLC allow either RTU or ASCII - this should be an inherent requirement if you wish to communicate across one of those channels. Figure 4. Illustrates the hardware configuration for choosing RTU or ASCII on either the RS-485 or RS-232 ports.
Figure 4. Hardware configuration for Modbus on RS-232 and RS-485. Author’s image
Once the port is configured, many Modbus devices can be connected.
In this example, a set of the first four consecutive output terminals on a remote I/O block are to be controlled from an HMI screen at the central control station. Those HMI tags are HMI1, 2, 3, and 4, respectively.
Figure 5. Node address, function code, and source tags can be seen in this Automation Direct example. Author’s image
If those terminals are perhaps not the first four, but are still consecutive, simply adjust the starting address.
If the terminals are not consecutive, multiple transactions must be used.
Other Capable Devices
Again, this channel is not simply for remote I/O terminals.
Using Modbus, a PLC may indirectly control another PLC. Many VFDs also contain Modbus support, either embedded or by an add-on bridge. In a VFD, ‘Command Words’ are the 16-bit registers that send start/stop/jog commands as well as frequency references. Parameters can also be accessed and adjusted.