In the movie City Slickers, the old cowboy, Curly (Jack Palance) tells Mitch (Billy Crystal) the secret of life. “One thing. Just one thing,” he says—but that you need to figure it out for yourself. And it’s what makes life meaningful again for Mitch when he realizes that his wife and children are all that really matter to him.
Well, Modbus isn’t the answer to the secret of life. But I can tell you the one pseudo-secret that’s the key to understanding Modbus - data representation. (Actually, it’s the key to understanding DeviceNet, Profibus, EtherNet/IP, Profinet IO and every other protocol). If you understand the data representation for a protocol, you’re 80% of the way to understanding what that communications protocol does and how it does it.
Like everything else about Modbus, the data representation is pretty simple. In fact, data is represented more simply in Modbus than in any other industrial protocol you’ll ever find. There are only two data types in Modbus: coils and registers.
Coils - Coils are simply single bits. The bits can be ON (1) or they can be OFF (0). Some coils represent inputs, meaning they contain the status of some physical discrete input. Or they represent outputs, meaning that they hold the state of some physical discrete output signal.
Registers - Registers are simply 16-bit unsigned register data. Registers can have a value from 0 to 65535 (0 to FFFF hexadecimal). There is no representation for negative values, no representation for values greater than 65535, and no representation for real data like 200.125.
Applications can impose these representations on registers. For example, a register can treat two registers, the first containing 200 and the second containing 125, as 200.125. Or an application can group four registers and place a 64-bit IEEE floating point bit pattern in those registers. Any application can organize and treat register data in any way it may want, but there is no way for any other Modbus device to automatically know what that representation is. A Modbus application that reads registers from a Modbus slave device must have some prior knowledge of how particular registers are treated to process them correctly.
Registers are grouped into input registers and holding registers. Like input coils, input registers report the state of some external input as a value between 0 and 65535. The original intent of an input register was to reflect the value of some analog input. It is a digital representation of an analog signal like a voltage or a current. Most Modbus devices today are not I/O devices, and input registers simply function identically to holding registers. Holding registers were originally designed as temporary program storage for devices like Modbus controllers. Today, holding registers function as data storage for devices.
Both Modbus registers and coils are addressed with the first register or coil as Address 1 and the last as Address 65536. That means that there can be up to 65536 (10000 Hex) input registers, 65536 output registers, 65536 input coils and 65536 status coils, but most devices use far fewer. Often you will find no coils in a device, and sometimes as few as 10 holding registers.
A lot of novice Modbus users find the address space notation used in Modbus confusing. Modbus includes the address space type with the index in the address space. The typical address space notation used in Modbus follows:
0x is Status Coil Address Space from 00000 to 065535
1x is Input Coil Address Space from 10000 to 165535
3x is Input Register Address Space from 30000 to 365535
4x is Holding Register Address Space from 40000 to 465535
So, when you see a notation that some value is at Modbus register 40010, you know that the value is stored in a holding register at offset 10, the 11th value, in the holding register area of the device. The reason that this is important is that there are specific Modbus functions that operate on specific areas of the address space. There is a read holding register command that always reads registers in the 4x address space. There is a write single coil register that only writes coils in the 0x address space.
What’s important to note about this data addressing is that the coil addressing is specifying bit addresses, while register addresses specify 16-bit unsigned integer values. Input coil address 2 is a bit address. It’s the third bit of the coil address space. Input holding register address 2 is the address of a 16-bit value. It’s the third value of the holding register address space.
The commands that operate on these address spaces reflect those data types. A command to read coils specifying a length of 3 is going to return 8 bits, of which only 3 will be valid. Coil address 3 for a length of 3 returns coils 3, 4 and 5. A command to read registers specifying a length of 3 returns three 16-bit values. It returns the values of registers 3, 4 and 5.
Write commands work in the opposite direction. When writing three coils, you must specify the three bits you want to write as the first three bits of the input data in the command. But when writing three registers, you must supply three 16-bit values.
Other than some awkward notation that is a left over from the era when Modicon Inc. designed the protocol, the Modbus data representation is very simple and straightforward. When a Modbus device is designed, the designer makes a decision of not only how many registers or coils are needed, but also which address space to use (input coil, status coil, input register, holding register) and where in that address space to locate those values. A designer may have only 10 bits of coil data and 2 registers. Those bits and registers can be located anywhere in the Modbus address space.
That example points to one of the deficiencies of this data representation. There are no standards. There is no way to communicate to the user of the device any meta-data. If the value of register 40100 is a temperature, there is no standard way to communicate the meaning of register 40100 and how to interpret the data. The user has no information to know if a value of 1001 means 100.1 degrees or 10.01 degrees or 1001 degrees.
There is also no standard regarding device profiles. Another temperature controller may store its temperature at 40200 and use a completely different data interpretation.
>The Modbus data representation is simple and almost standards-free. That is both a blessing and a curse to those of us who still use Modbus on a daily basis.