Modbus

Modbus dataSource and dataTargets

Modbus datasources and -targets (laters just dataurls) consists of multiple parts, just like regular http-urls do. Here is an example of modbusrtu dataSource: modbusrtu://ioPorts%2FmodbusRTU%2FP1/1/holding/337&datatype=int16

The dataurl can be split into parts which are separated by / character.

protocol

modbusrtu://

This part tells the modbus library which protocol to use. Possible values for modbus are modbusrtu and modbustcp

Important

The protocol field should be lower case.

ioPort

ioPorts%2FmodbusRTU%2FP1 This is the point name to the ioPort we want to use. The / in point name needs to be replaced with %2F (urlencoding)

address

1

This is the slave address of the device we’re reading from

register type

holding

This is the type of the register we’re interested in possible values are holding, input, coil, discrete

register number

337

This is the register we’re reading Actiweb does not use 1-4 prefixes for different register umbers Actiweb starts counting registers from 0. i.e. the ‘first’ register is in address 0

parameters

Optional parameters can be used to manipulate the raw register value. First parameter is separated form the register with the character ? and subsequent parameters with & Syntax for parameters is parameterName=value, e.g. scale=0.1 Some useful parameters

scale:

multiplies the raw value with scale value. e.g. value of 0.1 makes 100->10

datatype:

datatype for the register value, e.g. int16 or float32

offset:

sets offset for raw value

invert:

invert (raw value is subtracted from this value. Mainly useful for binary data)

x1,y1,x2,y2..xn,yn:

set scaling curve for raw value. Excel or other assistive tools are recommended

hilimit, lolimit:

set high or low limit for the pv value

damping:

floating average between reading rounds

bitmask:

bitmask to select/unselect individual bits from raw. On dataSource, when raw value is read from register, bitwise AND operation is performed between bitmask parameter and raw value, and result is written to pv. For dataTarget, bitmask value is used as raw value, and bitwise OR operation is performed between raw values of all datapoints pointing to this register and has pv greater than zero.

ondelay, offdelay:

Time in milliseconds between raw<->pv change

It’s rarely meaningful to build these dataurls by hand. Excel, IO-profiles or other means are strongly recommended to be used when importing dataUrls to database. Imagination is the only limiting factor :) Manually editing dataUrls makes sense mainly when debugging or testing new devices and finding out the registers.

Modbus-task logic

When Actiweb9 core (re)starts, modbus-task scans the database and finds all datapoints that have modbus related dataSources and -targets. It then matches the points to ioPorts and every ioPort starts its own parallel task. This means that reading different modbus busses happens concurrently and if one modbus task hangs it does not affect other modbus tasks. This also means that if any changes are made to the dataSources or dataTargets the core needs to be restarted for the changes to apply.

Gathering points

When modbus task has all the points gathered it will build a tree-like structure of the registers. It tries to bundle adjacent registers to same queries so that they can be requested in same modbus frame. This behavior reduces the amount of modbus queries and thus makes communication faster. Keeping this in mind, sometimes it might be beneficial to read ‘useless’ registers if it allows registers to be bundled together.

However bundling only applies to reading registers. All dataTargets are written individually for better compatibility for slave devices.

After reading register

When modbus task has read the register it will push that raw value to a field called raw. If the dataUrl has any parameters configured it will then apply those to the raw value. Order of the parameters is as follows:

  1. scale + offset

  2. inline curve

  3. bitmask

  4. datatype casting

The result value will then be stored in pv field. For dataTarget the order is reversed.

Recap

For reading: modbus peripheral device -> raw -> pv

For writing: pv -> raw -> modbus peripheral device

Tip

Overriding pv value

If user wants to override the value of the database point it can be done by first adding priority field and then setting it to 8 and writing wanted value to the pv field. If using graphical UI this behaviour will automated in the value setting dialog when priority field is present