Modbus information storage
With the Modbus protocol, most of the data values you want to transmit or receive are stored in registers. Information is stored in the server device in four different entities. Two store on/off discrete values (coils) and two store numerical values (registers). The four entities include:
-
Coils – 1-bit registers, used to control discrete outputs (including
Boolean Name given a function, the result of which is either true or false. values), read/write.
-
Discrete Input – 1-bit registers, used as inputs, read only.
-
Input Registers – 16-bit registers, used as inputs, read only.
-
Holding Registers – 16-bit registers; used for inputs, output, configuration data, or any requirement for “holding” data; read/write.
See the CRBasic Editor help for detailed instruction information and program examples:
Registers
In a 16-bit memory location, a 4-byte value takes up two registers. The Modbus protocol always refers to data registers with a starting address number, and a length to indicate how many registers to transfer.
Campbell Scientific uses 1-based numbering (a common convention for numbering registers in equipment) in the ModbusClient()
instruction. With 1-based numbering, the first data location is referred to as register number 1. Some equipment uses 0-based numbering (check the equipment documentation). With 0-based numbering, the first register is referred to as 0.
Reading register numbers can be complicated by the fact that register numbers are often written with an offset added. Input registers are written with an offset of 30000. So, the first input register is written as 30001, with 1-based numbering. Holding registers are numbered with an offset of 40000. You must remove the offset before writing the number as the Start
parameter of ModbusClient()
.
There are rare instances when equipment is designed with the registers mapped including the offset. That means 40001 in the documentation is really register number 40001. Those are rare instances, and the equipment is deviating from standards. If 1 or 2 don’t work for the Start parameter, try 40001 and 40002.
Coils
Discrete digital I/O channels in Modbus are referred to as coils. The term coil has its roots in digital outputs operating solenoid coils in an industrial environment. Coils may be read only or read/write. A read only coil would be a digital input. A read/write coil is used as an output. Coils are read and manipulated with their own function codes, apart from the registers. Many modern devices do not use coils at all.
When working with coils, the data logger requires Boolean variables. When reading coils, each Boolean in an array will hold the state of one coil. A value of True will set the coil, a value of False will unset the coil.
Data Types
Modbus does not restrict what data types may be contained within holding and input registers. Equipment manufacturers need to indicate what binary data types they are using to store data. Registers are 16-bit, so 32-bit data types use 2 registers each. Some devices combine more registers together to support longer data types like strings. The ModbusClient()
instruction has a ModbusOption
parameter that supports several different data types.
When data types use more than 1 register per value, the register order within the data value is important. Some devices will swap the high and low bytes between registers. You can compensate for this by selecting the appropriate ModbusOption
.
Byte order is also important when communicating data over Modbus. Big Endian byte order is the reverse of Little Endian byte order. It may not always be apparent which a device uses. If you receive garbled data, try reversing the byte order. Reversing byte order is done using the
instruction. There is an example in CRBasic help for reversing the bytes order of a 32-bit variable.MoveBytes()
After properly reading in a value from a Modbus device, you might have to convert the value to proper engineering units. With integer data types, it is common to have the value transmitted in hundredths or thousandths.
Unsigned 16-bit integer
The most basic data type used with Modbus is unsigned 16-bit integers. It is the original Modbus data type with 1 register per value. On the data logger, declare your destination variable as type Long. A Long is a 32-bit signed integer that contains the value received. Select the appropriate ModbusOption
to avoid post-processing.
Signed 16-bit integer
Signed 16-bit integers use 1 register per value. On the data logger, declare your destination variable as type Long. A Long is a 32-bit signed integer that contains the value received . Select the appropriate ModbusOption
to avoid post-processing.
Signed 32-bit integer
Signed 32-bit integers require two registers per value. This data type corresponds to the native Long variable type in Campbell data loggers. Declare your variables as type Long before using them as the Variable parameter in ModbusClient()
. Select the appropriate ModbusOption
to avoid post-processing.
Unsigned 32-bit integer
Unsigned 32-bit integers require two registers per value. Declare your variables as type Long before using them as the Variable
parameter in ModbusClient()
. The Long data type is a signed integer, and does not have a range equal to that of an unsigned integer. If the integer value exceeds 2,147,483,647 it will display incorrectly as a negative number. If the value does not exceed that number, there are no issues with a variable of type Long holding it.
32-Bit floating point
32-bit floating point values use 2 registers each. This is the default FLOAT data type in Campbell Scientific data loggers. Select the appropriate ModbusOption
to avoid post-processing.