Modbus Driver

The ESF Modbus Driver implements the Modbus protocol using the Driver model. The Driver can be used to interact with Modbus devices using different abstractions, such as the Wires framework, the Asset model or by directly using the Driver itself.

Features

The Modbus Driver features include:

  • Support for Modbus protocol over TCP, UDP and serial ports.
  • Support for reading and writing data from Coils, Discrete Inputs, Holding Registers and Input Registers areas.
  • Support for reading/writing numeric data that spans multiple contiguous registers with different size and byte order (for example interpreting the value of two contiguous registers as a 32-bit integer).
  • The driver is capable of automatically aggregating reads/writes for contiguous data in larger bulk requests in order to reduce IO times.

## Installation

The Driver is distributed as a deployment package on Eclipse Marketplace.
It can be installed following the instructions provided here

Instance creation

A new Modbus Driver instance can be created either by clicking the New Driver button in the dedicated Drivers and Assets Web UI section or by clicking on the + button under Services. In both cases, the org.eclipse.kura.driver.modbus factory must be selected and a unique name must be provided for the new instance.

Channel configuration

The Modbus Driver channel configuration is composed of the following parameters:

  • name: the channel name.
  • type: the channel type, (READ, WRITE, or READ_WRITE).
  • value type: the Java type of the channel value.
  • unit.id: the Modbus unit id.
  • primary.table: the Modbus area to be used (COILS, DISCRETE_INPUTS, HOLDING_REGISTERS or INPUT_REGISTERS). If the channel operation involves the COILS or DISCRETE_INPUTS areas, the value type parameter must be set to BOOLEAN.
  • memory.address: the start register, coil or discrete input address of the data involved in the channel operation.
  • data.order: specifies the byte order of the numeric data involved in the channel operation. This parameter is relevant only for register data, and only if the value.type parameter value is FLOAT, DOUBLE, INTEGER or LONG, this parameter is ignored otherwise. See the Byte order section for more details.
  • data.type: specifies the sign and size of the numeric data. This parameter is relevant only for register data, and only if the value.type parameter value is FLOAT, DOUBLE, INTEGER or LONG. This parameter is ignored otherwise. See the Data type section for more details.
  • array.data.length: specifies the length in bytes of the array-like data. This parameter is relevant only for register data, and only if the value.type parameter value is either STRING or BYTE_ARRAY. This parameter is ignored otherwise.

## Byte order

The byte order for numeric data involved in channel operations can be specified using the data.order configuration parameter. The allowed values are the following:

  • MSW: Most significant word first.
  • LSW: Least significant word first.
  • MSB: Most significant byte first.
  • LSB: Least significant byte first.

The register data byte order is defined by the Modbus specification as MSB (the most significant byte of a 16-bit Modbus register is transferred first). When transferring numeric data that spans multiple contiguous registers, the transmission order is not defined by the Modbus specification but is application dependent. For example, a 32-bit integer, that spans two Modbus registers, can be stored either with the MSW in the register having the lower address and the LSW in the other one, or vice versa.

The table below shows illustrates how the 0xaabbccdd 32-bit​ integer value is transferred for each byte order (the leftmost byte in the Transfer order is transferred first):

Byte orderTransfer order
MSW0xaa 0xbb 0xcc 0xdd
LSW0xcc 0xdd 0xaa 0xbb
MSB0xaa 0xbb 0xcc 0xdd
LSB0xdd 0xcc 0xbb 0xaa

Data Type

When performing operations that deal with numeric data, two data types are involved:

  1. The Java primitive type that is used in the ChannelRecords exchanged between the driver and Java applications. (the Java type of the value received/supplied by external applications from/to the Driver in case of a read/write operation). This value type is specified by the value type configuration property.

  2. The type of the data stored on the Modbus device. This value type is specified by the data.type configuration property. The possible values of this configuration property are described in the table below:

Data typeSizeSign
FLOAT32 bitssigned
DOUBLE64 bitssigned
INT88 bitssigned
INT1616 bitssigned
INT3232 bitssigned
INT6464 bitssigned
UINT88 bitsunsigned
UINT1616 bitsunsigned
UINT3232 bitsunsigned
ARRAYn.d (see Array data)n.d (see Array data)

Java numeric types are always signed, while data stored on the device may be signed or unsigned, depending on the application. The Driver automatically adapts the data type used by external applications and the Modbus device depending on the value of the two configuration properties mentioned above.

The adaptation process involves the following steps:

  • Each device data type is internally converted by the driver from/to a Java type large enough to represent the value of the device data without losing precision. The type mappings are the following:
Modbus device data typeJava data type
FLOATfloat
DOUBLEdouble
INT8int
INT16int
INT32int
INT64long
UINT8int
UINT16int
UINT32long

UINT64 data type is not supported by the Driver because there is no Java type large enough to store its values without losing precision.

  • If the value type of the channel does not match the Java type specified in mapping above, a conversion is performed by the Driver to convert it to/from the matching type, choosing appropriately between the Number.toInt(), Number.toLong(), Number.toFloat() or Number.toDouble() methods.
    Precision losses may occur if the Java type used by the external application is not suitable to represent all possible values of the device data type.

Array Data

The driver supports transferring data as raw byte arrays or ASCII strings:

  • Byte arrays: For transferring data as byte arrays the channel value type property must be set to BYTE_ARRAY, the data.type configuration property must be set to ARRAY and the array.data.length property must be set to the data length in bytes.
  • Strings: For transferring data as ASCII strings the channel value type property must be set to STRING, the data.type configuration property must be set to ARRAY and the array.data.length property must be set to the data length in bytes.