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: 9600Data bits: 8Parity: EvenStop bits: 1Slave 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 |
|---|---|
|
Slave address 1 |
|
Start at register number 1 (address 0x00) |
|
Read 8 registers (= 4 float32 values) |
|
Interpret as 32-bit float |
|
Little-endian word order (low word first) |
|
Baud rate 9600 |
|
8 data bits |
|
Even parity |
|
1 stop bit |
|
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 |
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 |
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 |
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 |
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 |
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: |
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: |
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: |
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: |
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: |
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: |
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: |
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: |
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. |
168 - 171
0xA8 - 0xAB
|
169 - 172
0xA9 - 0xAC
|
Reserved. |
|
172
0xAC
|
173
0xAD
|
uint16 |
Command register. Write value |
173
0xAD
|
174
0xAE
|
uint16 |
Command register. Write value |
174
0xAE
|
175
0xAF
|
uint16 |
Command register. Write value |