5.3. Modbus Protocol (RS-485)#

Protocol Overview#

The VX60 instrument responds to Modbus RTU requests over the RS-485 data line. Communication parameters such as baud rate, parity, stop bits, and device ID are configured through the PC application or via Modbus itself. The default settings are:

Baud rate: 9600
Data bits: 8
Parity: Even
Stop bits: 1
Slave ID: 1

Modbus is a request-response protocol. A master device (such as a data logger or PLC) sends requests, and the slave device (the VX60 instrument) responds. The master can either read the value of one or more holding registers (using Modbus function code 0x03), or write the value of a holding register (function code 0x06), or write more holding registers (function code 0x10). All registers in the VX60 are Holding Registers (40001-range in Modbus convention).

IMPORTANT: Register Address vs. Register Number

The Modbus protocol uses zero-based register addressing in the actual request and response frames transmitted on the wire. This means that the first holding register is addressed as 0, the second as 1, and so on. However, many tools and documentation refer to one-based register numbers.

register number = register address + 1

For example, the first register has address 0 and register number 1. The modpoll utility and most Modbus configuration tools use the 1-based register number.

To further complicate things, certain PLC software packages use 40001-based addressing. In this convention, holding registers are labeled starting from 40001, so that the register number 40001 corresponds to the first holding register at address 0. It is important to understand that the leading “4” in addresses such as 40001 does not form part of the address transmitted over Modbus. Instead, it indicates the register type (4 = Holding Register, not to be confused with function 3 for reading holding registers). The actual address sent in the Modbus frame is zero-based and does not include this prefix.

PLC register number = register address + 40001

Modbus is a very old protocol, so please do not judge its quirks too harshly.

Throughout this document, both the zero-based register address and the corresponding one-based register number are shown for clarity.

Each Modbus register holds a single 16-bit (2-byte) value. The VX60 uses the following data types:

  • uint16 / int16 (1 register)

    A single 16-bit value occupying one register. Unsigned values (uint16) range from 0 to 65535. Signed values (int16) range from -32768 to 32767.

  • uint32 (2 registers)

    A 32-bit unsigned integer spanning two consecutive registers. The low word is in the first (even-addressed) register, and the high word is in the second (odd-addressed) register.

    Example: Value 0x00000003 would be transmitted as pair of registers 0x0003 and 0x0000.

  • float32 (2 registers)

    A 32-bit IEEE 754 floating-point value spanning two consecutive registers. The encoding uses little-endian word order (low word first, high word second), which is common in industrial Modbus devices.

    Example: The Value 1.5 is encoded per IEEE 754 as 0x3FC00000, and would be transmitted as pair of registers 0x0000 and 0x3FC0.
    A fixed endianness check register at address 62 (register 63) always returns the value
    -123.265625. Read this register to verify your decoder handles the byte/word order correctly. The expected raw register values are 0x8800, 0xC2F6.

Reading Registers with modpoll#

modpoll is a command-line utility for reading and writing Modbus registers from a PC.

To read the first four float32 measurement values (velocity, direction, signed velocity, SNR) from the VX60, run modpoll with the following arguments:

modpoll -m rtu -a 1 -r 1 -c 8 -t 4:float -e -b 9600 -d 8 -p even -s 1 COM3

To read a single uint16 configuration register (e.g., measurement unit at register 130):

modpoll -m rtu -a 1 -r 130 -c 1 -t 4 -b 9600 -d 8 -p even -s 1 COM3

Flag

Meaning

-a 1

Slave address 1

-r 1

Start at register number 1 (address 0x00)

-c 8

Read 8 registers (= 4 float32 values)

-t 4:float

Interpret as 32-bit float

-e

Little-endian word order (low word first)

-b 9600

Baud rate 9600

-d 8

8 data bits

-p even

Even parity

-s 1

1 stop bit

COM3

Serial port (use /dev/ttyUSB0 on Linux)

Registers Overview#

The register address space is divided into three distinct blocks:

  • Block 1 provides high-resolution measurement data as 32-bit floats. This is the recommended block for modern data loggers and SCADA systems.

  • Block 2 provides the same measurement data encoded as 16-bit integers for compatibility with legacy data loggers that cannot decode float32 values. Values are scaled as documented in the register table.

  • Block 3 contains all user-configurable device parameters. Some addresses are reserved, and will read as zero and must not be written.

Block

Address Range

Register Range

Purpose

1

0 - 63
0x00 - 0x3F
1 - 64
0x01 - 0x40

Measurement data (float32, read-only)

2

64 - 127
0x40 - 0x7F
65 - 128
0x41 - 0x80

Measurement data (int16 compatibility, read-only)

3

128 - 175
0x80 - 0xAF
129 - 176
0x81 - 0xB0

Configuration parameters (read/write)

Block 1: Measurement Registers (float32)#

Address(es)

Reg #

Data Type

Description

0, 1
0x00, 0x01
1, 2
0x01, 0x02

float32

Absolute surface velocity in the selected measurement unit (always >= 0). The unit is set by configuration register 0x81.

2, 3
0x02, 0x03
3, 4
0x03, 0x04

float32

Flow direction:
+1.0 = incoming (towards sensor),
-1.0 = outgoing (away from sensor),
0.0 = no flow detected.
4, 5
0x04, 0x05
5, 6
0x05, 0x06

float32

Surface velocity in m/s. The value can be positive or negative. Positive values = incoming flow, negative values = outgoing flow. Not unit-converted, always in m/s.

6, 7
0x06, 0x07
7, 8
0x07, 0x08

float32

Signal-to-noise ratio (SNR) of the returned radar signal in dB. Higher values indicate stronger signal quality.

8, 9
0x08, 0x09
9, 10
0x09, 0x0A

float32

Forward tilt angle of the sensor in degrees. Ideally the sensor should be mounted at 60°.

10, 11
0x0A, 0x0B
11, 12
0x0B, 0x0C

float32

Side tilt angle of the sensor in degrees. This angle should be very close to 0°.

12, 13
0x0C, 0x0D
13, 14
0x0D, 0x0E

float32

Device temperature in units of degrees Celsius.

14, 15
0x0E, 0x0F
15, 16
0x0F, 0x10

float32

Relative humidity inside the device enclosure in percent (%).

16, 17
0x10, 0x11
17, 18
0x11, 0x12

uint32

Status flags (0 = all OK), as error bitmask:
Bit 0: forward tilt angle error (tilt angle outside of expected range).
Bit 1: side tilt angle error (tilt is too big).
Bit 2: radar co-processor update failed.
Bit 3: radar co-processor not responding.
Bit 4: radar co-processor needs to be updated.
Bit 5: tilt sensor is not working.
Bit 6: radar self-calibration failed.
Bit 7: DFP data corrupt, needs reset.
Bit 8: standby mode is active.
Bit 9: radar is initializing.
18
0x12
19
0x13

uint16

Firmware upgrade status:
0 = idle,
1 = pending,
2 = active,
3 = done,
4 = failed.
19 - 61
0x13-0x3D
20 - 62
0x14-0x3E

Reserved. Reads as 0.

62, 63
0x3E, 0x3F
63, 64
0x3F, 0x40

float32

Endianness check: This register will always return constant -123.265625, as a pair of values 0x8800, 0xC2F6. Use this to verify float32 decoding in your system.

Block 2: Measurement Registers (int16)#

These registers provide the same measurement data as Block 1, but encoded as 16-bit integers for compatibility with data loggers that do not support float32 decoding. All values are read-only.

Address(es)

Reg #

Data Type

Description

64
0x40
65
0x41

uint16

Absolute surface velocity, integer part, in selected measurement unit. Example: if velocity is 12.3456, this register returns 12.

65
0x41
66
0x42

uint16

Absolute surface velocity, fractional part (4 decimal digits), in selected measurement units. Example: if velocity is 12.3456 this register returns 3456; if velocity is 12.34 then the register returns 3400.

66
0x42
67
0x43

int16

Flow direction:
+1 = incoming,
-1 = outgoing,
0 = no flow.
67
0x43
68
0x44

int16

Surface velocity in mm/s, integer part only. Positive values = incoming flow, negative values = outgoing flow. Clamped to range -16000 .. +16000 mm/s.

68
0x44
69
0x45

uint16

Signal-to-noise ratio (SNR) of the returned radar signal in dB integer part only. Higher values indicate stronger signal quality.

69
0x45
70
0x46

int16

Forward tilt angle of the sensor in degrees. Ideally the sensor should be mounted at 60°.

70
0x46
71
0x47

int16

Side tilt angle of the sensor in degrees. This angle should be very close to 0°.

71
0x47
72
0x48

int16

Device temperature in degrees Celsius x 100. Example: if temperature is 23.456 °C then this register holds 2345.

72
0x48
73
0x49

int16

Relative humidity inside the device enclosure in percent (%) x 100. Example: if relative humidity is 24.17 % then this register holds 2417.

73, 74
0x49, 0x4A
74, 75
0x4A, 0x4B

uint32

Status flags (same encoding as Block 1).

75
0x4B
76
0x4C

uint16

Firmware upgrade status (same as Block 1 register 0x12).

Block 3: Configuration Registers (R/W)#

Addr.

Reg #

Data Type

Description

128
0x80
129
0x81

uint16

Current Firmware Version Number. Read-only. Example: if the firmware version is 1.2.3 this register holds 123.

129
0x81
130
0x82

uint16

Measurement Unit. Affects values in registers 0x00, 0x01, 0x40, 0x41. See Output Unit for the detailed setting description.
Available values:
0 = mm/s,
1 = m/s,
2 = mph,
3 = km/h,
4 = ft/s,
5 = ft/min,
6 = cm/s.
Default value: 1 (m/s)
130-131
0x82-0x83
131-132
0x83-0x84

Reserved.

132
0x84
133
0x85

uint16

Velocity Filter Length. In seconds. Longer values produce smoother but slower-responding readings. See Filter Length for the detailed setting description. Default value: 10

133
0x85
134
0x86

uint16

Direction Filter. See Direction Filter for the detailed setting description.
Available values:
0 = measure both directions,
1 = incoming flow only,
2 = outgoing flow only.
Default value: 0 (both)
134
0x86
135
0x87

uint16

Radar Beam Width Configuration. See Beam Width for the detailed setting description.
Available values:
0 = wide,
1 = narrow.
Default value: 0 (wide)
135
0x87
136
0x88

uint16

Dynamic Flow Profiler (DFP). Enable DFP calculation. See Dynamic Flow Profiler for the detailed setting description.
Available values:
0 = disabled,
1 = enabled.
Default value: 0 (off)
136, 137
0x88, 0x89
137, 138
0x89, 0x8A

float32

Maximum Velocity Threshold. Velocity readings above this threshold are rejected. See Maximum Velocity for the detailed setting description. Default value: 16.0

138
0x8A
139
0x8B

uint16

Maximum Velocity Unit. See Maximum Velocity for the detailed setting description.
Available values:
0 = mm/s,
1 = m/s,
2 = mph,
3 = km/h,
4 = ft/s,
5 = ft/min,
6 = cm/s.
Default value: 1 (m/s)
139
0x8B
140
0x8C

uint16

Radar Beam Offset Configuration. See Beam Position for the detailed setting description.
Available values:
0 = near,
1 = far.
Default value: 0 (near)
140, 141
0x8C, 0x8D
141, 142
0x8D, 0x8E

float32

Minimum Valid Distance. Reflections detected closer than this distance are ignored. Use this parameter to exclude near-field returns e.g., mounting hardware, bridge elements, or other objects close to the sensor. See Minimum Distance for the detailed setting description. Default value: 0

142
0x8E
143
0x8F

uint16

Minimum Valid Distance Unit. See Minimum Distance for the detailed setting description.
Available values:
0 = mm,
1 = cm,
2 = m,
3 = ft,
4 = in.
Default value: 2 (m)
143
0x8F
144
0x90

Reserved.

144, 145
0x90, 0x91
145, 146
0x91, 0x92

float32

Maximum Valid Distance. Reflections detected beyond this distance are ignored. Use this parameter to exclude far-field returns outside the intended measurement zone e.g., opposite bank, structures, or background targets. See Maximum Distance for the detailed setting description. Default value: 30.0

146
0x92
147
0x93

uint16

Maximum Valid Distance Unit. See Maximum Distance for the detailed setting description.
Available values:
0 = mm,
1 = cm,
2 = m,
3 = ft,
4 = in.
Default value: 2 (m)
147
0x93
148
0x94

Reserved.

148
0x94
149
0x95

uint16

RS-232 Serial Port Baud Rate. See RS-232 Baud Rate for the detailed setting description.
Available values:
0 = 4800,
1 = 9600,
2 = 14400,
3 = 19200,
4 = 38400,
5 = 57600,
6 = 115200.
Default value: 6 (115200)
149
0x95
150
0x96

uint16

Modbus RS-485 Baud Rate. Caution: changing this will require the master to reconnect at the new baud rate. See RS-485 Baud Rate for the detailed setting description.
Available values:
0 = 4800,
1 = 9600,
2 = 14400,
3 = 19200,
4 = 38400,
5 = 57600,
6 = 115200.
Default value: 1 (9600)
150
0x96
151
0x97

uint16

Modbus Parity Setting. See Modbus Parity for the detailed setting description.
Available values:
0 = none,
1 = odd,
2 = even.
Default value: 2 (even)
151
0x97
152
0x98

uint16

Modbus Stop Bits. See RS-485 Stop Bits for the detailed setting description.
Available values:
0 = one stop bit,
1 = two stop bits.
Default value: 0 (one)
152
0x98
153
0x99

uint16

Modbus Slave Address. Must be unique on the RS-485 bus. See Modbus ID for the detailed setting description. Default value: 1

153
0x99
154
0x9A

uint16

SDI-12 Sensor Address. The value is stored as a numeric integer (0 - 61) in the register. SDI-12 addressing is character-based, so the numeric value from the register is converted to the corresponding SDI-12 address character according to the following mapping: 0 - 9 -> characters 0-9, 10 - 35 -> characters A-Z, 36 - 61 -> characters a-z. See SDI-12 ID for the detailed setting description. Default value: 0

154
0x9A
155
0x9B

uint16

Power Management Mode. Gets / sets the automatic SDI-12 sleep mode parameter. When SDI-12 sleep is enabled, the device enters low-power sleep between SDI-12 transactions. When disabled, the sensor runs continuously and is ready at all times. See Power Management for the detailed setting description.
Available values:
0 = sleep enabled (low power),
1 = sleep disabled (continuous scanning).
Default value: 1 (off)
155
0x9B
156
0x9C

Reserved.

156, 157
0x9C, 0x9D
157, 158
0x9D, 0x9E

float32

Minimum Value for Analog Output. Measurements at or below this value produce minimum current. See 4 - 20 mA Minimum Value for the detailed setting description. Default value: 0

158
0x9E
159
0x9F

uint16

Minimum Value Unit for Analog Output. See 4 - 20 mA Minimum Value for the detailed setting description.
Available values:
0 = mm/s,
1 = m/s,
2 = mph,
3 = km/h,
4 = ft/s,
5 = ft/min,
6 = cm/s.
Default value: 1 (m/s)
159
0x9F
160
0xA0

Reserved.

160, 161
0xA0, 0xA1
161, 162
0xA1, 0xA2

float32

Maximum Value for Analog Output. Measurements at or above this value produce maximum current. See 4 - 20 mA Maximum Value for the detailed setting description. Default value: 16.0

162
0xA2
163
0xA3

uint16

Maximum Value Unit for Analog Output. See 4 - 20 mA Maximum Value for the detailed setting description.
Available values:
0 = mm/s,
1 = m/s,
2 = mph,
3 = km/h,
4 = ft/s,
5 = ft/min,
6 = cm/s.
Default value: 1 (m/s)
163
0xA3
164
0xA4

Reserved.

164
0xA4
165
0xA5

uint16

Operation Mode. When the operation mode is set to standby, the device will communicate on all communication interfaces, but the radar transmitters will be turned off to reduce the power, and the instrument will not be making any measurements. See Operation Mode for the detailed setting description.
Available values:
0 = off (normal operation),
1 = on (standby operation).
Default value: 0 (off)
165
0xA5
166
0xA6

uint16

Disable NMEA Sentence Output. On RS-232.
Available values:
0 = NMEA enabled,
1 = NMEA disabled.
Default value: 0 (off)
166
0xA6
167
0xA7

uint16

Show Data on Error. Continue reporting velocity data even when angle errors are detected.
Available values:
0 = clear velocity on error (send 0 as velocity instead of measured value),
1 = keep velocity.
Default value: 0 (off)
167
0xA7
168
0xA8

uint16

Fixed Mounting Angle. Override measured pitch angle with a fixed value (degrees). Changing this parameter will affect the reported velocity as cosine correction behaviour will be changed. Use this parameter only during tow-tank testing. 0 = use measured angle. Default value: 0 (off)

168 - 171
0xA8 - 0xAB
169 - 172
0xA9 - 0xAC

Reserved.

172
0xAC
173
0xAD

uint16

Command register. Write value 0xAD10 to this register to perform a software reset. The device will restart immediately. The magic value prevents accidental resets.

173
0xAD
174
0xAE

uint16

Command register. Write value 0xBAC1 to this register to restore all parameters to factory defaults and restart. The magic value prevents accidental resets.

174
0xAE
175
0xAF

uint16

Command register. Write value 0xCDF0 to this register to clear the DFP (Dynamic Flow Profiler) learned data. The magic value prevents accidental resets.