Modbus is a simple communication protocol originally designed in 1979 and intended for use in Industrial Automation systems. The original flavor, Modbus/RTU, was built to utilize serial communications (RS-232 and RS-485 primarily), but it has since been extended to use Ethernet. The Ethernet variant is known as Modbus/TCP. While the core principles remain the same with TCP, the use of TCP/IP communications adds a bit of complexity so we will concentrate on RTU for the remainder of this post. The basic idea behind Modbus communications is incredibly simple. The "master" device issues commands to one or more "slave" devices, instructing them to either read or write their intermal memory. That's it. Every Modbus-enabled device will have a list of 16-bit "registers" (memory locations) that it will make available to the master. To properly interface with the slave, the master needs to know its address on the network as well as a map of that slave's register list. That's really all there is to it. The slave is responsible for determining how it will interpret the data stored in each register, and will typically publicize this in a manual of some sort so the host can make sense out of it. But as far as Modbus is concerned, it's just 16-bit data being sent back and forth.
Note, Modbus also allows writing to "coils" in addition to "registers". Registers are 16-bit pieces of data treated as a coherent value. Coils are individual bits, much like a single sensor will report either "on" or "off". For the purposes of this article we'll be discussing only registers. Coils are treated exactly the same manner, so if you can understand registers, you'll also understand coils. Sound good? Okay. Back to it!
Call and Response
Modbus operates on a very simple call-and-response architecture. The master makes a request (or issues an order, depending on your level of cynicism), and the slave responds.
This is all well and good, but what happens if you want to control multiple slaves? Great question! It turns out Modbus was designed for a networked environment, and the RTU variant really shines when running on an RS-485 physical layer. This topology allows a single master to communicate with multiple slaves over a simple serial link, and is perfect for something like Modbus. That arrangement (by far the most common) would look something like the following image.
Note that every slave device will see the message from the host at the same time. For this reason an address character is included at the beginning of each Modbus message. Even though everyone gets the message, slaves will respond only to messages that carry their unique address. This is actually one of the primary ways in which Modbus/TCP differs from Modbus/RTU: Modbus/TCP slaves only ever receive message intended for that device. Everyone has a unique IP address, so if a message makes it all the way to you, you can assume you're the intended recipient of that message. The Ethernet version utilizes TCP/IP, which includes an additional header containing address information, MAC IDs to further distinguish devices on the network, as well as routing information for each packet. There is also a built-in acknowledgement routine so the master knows that every packet arrived intact. RTU uses none of that, so while it lacks some of the robustness of its Ethernet-enabled cousin it has the benefit of being far simpler to understand at a conceptual level.
So what would you say you do here?
Not much, it turns out. Modbus commands allow the host to read and write data. That's it. Of course, that's hardly a limitation. Remember, your computer only understands two things: 1 and 0. And yet you're doing some amazing things with it; it's hardly a limitation. In the case of Modbus, the host can read and write individual registers, groups of registers, individual data points (coils) or groups of coils. It may not seem like much, but this is actually sufficient to pass any type of data to and from the slave devices. This data can be direct sensor readings, motor settings, encoded commands or model numbers, even display information for an operator panel of some sort. There are two major quirks in the register addressing scheme however, and they can trip a lot of people up when they first see them.
10000? 30000? 40000?
16-bit read/write register addresses (referred to as Holding Registers) start at 40,000. Read-only register addresses (referred to as Input Registers) begin at 30,000. So, 16-bit register 6 would be denoted in the literature as 40006. It's worth noting that 32-bit values are organized as two adjacent 16-bit registers. 64-bit data, as I'm sure you can imagine, would occupy 4 adjacent registers. As far as Modbus is concerned, everything is 16-bit data, so it's up to the master and slave to work out exactly what data is represented in the register map. Coils, or discrete I/O points, typically begin with 10000. In most applications however, I/O is grouped into 16-bit clusters and referenced using register read/write operations. There isn't a rule about this, so it really depends on the specific implementation. Remember that all data is binary (represented as Hex values), and since binary operations are widely documented it's usually sufficient to bundle a group of individual bits into a larger word and just read or write to the whole register in one go.
There are two types of programming errors:
- Off by 1
(Programmer humor. Don't worry if you don't get it, it's not that funny.) Modbus addresses always start at 1, not zero. For example, while internally the slave's firmware will probably reference the first array element as 0, Modbus will map it to 40001. The 4 comes from the fact that this example address is a 16-bit read/write holding register, and the 1 indicates that it's the first one in the list. You can think of this as a more "human readable" address, rather than the more rigid "everything starts at zero" rule that programmers have to learn. While simple enough to fix, it's subtle enough that this is often the biggest problem new users will face when setting up a system. So remember - if you set up a Modbus system but you don't get the data you expect to see, try shifting your register addresses by 1 in either direction. I bet it starts working...
I'm bored. Let's see it in action!
Fine. Here are a few real-world, entirely accurate representations of what a Modbus exchange might look like.
In the above example, our loyal slave receives the read request and responds by relaying the information stored at register location 6. We can also infer something about the slave's personality, but we'll try not to hold that against it.
Here we see a bulk read request, where the master demands to see the values of a block of registers in the slave's memory map.
In this final example we see a bulk write request. 10 registers worth of data are being fed from the host into the slave device. This could represent move data, update display information for an operator, initialize a labeling system, or really anything else.
There's a lot more to know about Modbus, but I hope this has helped to explain the basic idea. It's really a very simple protocol, a fact that has allowed it to grow into one of the dominant players in the industrial communications field. Was any of this unclear? Do you have questions? Leave a comment below, and we'll chat. As always, thanks for reading! Note, there are literally hundreds of Modbus-enabled devices on the market. For the purposes of this document I used a CC-licensed generic image of a PLC which closely resembles a Panasonic FPX series device (more here) as the master, and an image of an Applied Motion STM23 (more at the Applied Motion Products STM23 product page) for the slave. It is important to understand that these devices are generic representations of possible master/slave configurations, and their representation here does not constitute an endorsement of either company or product. (Full disclosure, I work for Applied Motion Products.)