Skip to content

Modbus RTU Slave

Giampiero Baggiani edited this page Jul 6, 2022 · 50 revisions

This sketch implements a fully functional standard Modbus RTU slave, configurable via serial console and via Modbus, to monitor and control all I/O lines of the Iono Uno, Iono MKR and Iono RP modules. Moreover it allows for reading data from 1-Wire Dallas temperature sensors and Wiegand devices (keypads, card readers, biometric readers, ...).

You can find the source code here.

This app requires the IonoModbusRtu library. Make sure to have it installed together with its dependencies.

Console

The configuration console can be accessed through Iono's RS-485 interface or USB port, using any serial communication application (e.g. the Serial Monitor of the Arduino IDE).

Set the communication speed to 9600, 8 bits, no parity, no flow-control and connect the cable.

When Iono is powered-up or reset, you can enter console mode by sending five or more consecutive space characters within 15 seconds from reset. If any other character is received, Iono will enter the normal Modbus RTU mode.

=== Sfera Labs - Modbus RTU Slave configuration menu - vX.X ===
0. Print current configuration
1. Speed (baud)
2. Parity
3. Modbus device address
4. Input/Output rules
5. Save configuration and restart
Type a menu number (0, 1, 2, 3, 4, 5): 0

Current configuration:
Speed (baud): 115200
Parity: Even
Modbus device address: 2
Input/Output rules: - - - - - -

Enter 0 to show the current configuration, 1 to 3 to set the serial port speed, serial port parity, and the Modbus address.

Enter 4 to define the Input/Output rules. With these rules you can configure each one of the digital inputs to control the corresponding output relay. The rules string consists of six characters, where the leftmost character represents the rule for DI1/DO1 and the rightmost character for DI6/DO6 (for Iono MKR only the the first four rules apply). The possible rules are:

F: follow - the relay is closed when input is high

I: invert - the relay is closed when input is low

H: flip on L>H transition - the relay is flipped at any input transition from low to high

L: flip on H>L transition - the relay is flipped at any input transition from high to low

T: flip on any transition - the relay is flipped at any input transition, both high to low and low to high

-: no rule - no control rule set for this relay.

Enter 5 to review the configuration and confirm to save it. When the new configuration is saved, Iono will automatically reset and restart with the new configuration.

The configuration is persisted in memory and retained across restarts and power cycles.

Modbus address tables and functions

Device ID

Use Modbus function Read Input Registers on register address 99 to read the ID of the module:

  • Iono Uno: 0x10
  • Iono MKR: 0x20
  • Iono RP: 0x30

Configuration

Use function Write Single Register or Write Multiple Registers to set the new configuration parameters, then write 0xABCD at address 3000 to save it.

Address (decimal) Size [word] Description R/W Functions Type Range
3000 1 write 0xABCD to save the new configuration written in the registers below. This register can only be written individually, i.e. using function 6, or function 16 with a single data value. After positive response the unit is restarted and the new configuration is applied w 6,16 unsigned short n/a
3001 1 Modbus unit address r/w 3,6,16 unsigned short 1-247
3002 1 Modbus baud rate:
1 = 1200
2 = 2400
3 = 4800
4 = 9600
5 = 19200
6 = 38400
7 = 57600
8 = 115200
r/w 3,6,16 unsigned short 1-8
3003 1 Modbus parity:
1 = even
2 = odd
3 = none
r/w 3,6,16 unsigned short 1-3
3004 1 DI1/DO1 rule (see below) r/w 3,6,16 unsigned short 'F' (0x46), 'I' (0x49), 'H' (0x48), 'L' (0x4C), 'T' (0x54), '-' (0x2D)
3005 1 DI2/DO2 rule (see below) r/w 3,6,16 unsigned short 'F' (0x46), 'I' (0x49), 'H' (0x48), 'L' (0x4C), 'T' (0x54), '-' (0x2D)
3006 1 DI3/DO3 rule (see below) r/w 3,6,16 unsigned short 'F' (0x46), 'I' (0x49), 'H' (0x48), 'L' (0x4C), 'T' (0x54), '-' (0x2D)
3007 1 DI4/DO4 rule (see below) r/w 3,6,16 unsigned short 'F' (0x46), 'I' (0x49), 'H' (0x48), 'L' (0x4C), 'T' (0x54), '-' (0x2D)
3008 1 DI5/DO5 rule (see below) - Iono Uno only r/w 3,6,16 unsigned short 'F' (0x46), 'I' (0x49), 'H' (0x48), 'L' (0x4C), 'T' (0x54), '-' (0x2D)
3009 1 DI6/DO6 rule (see below) - Iono Uno only r/w 3,6,16 unsigned short 'F' (0x46), 'I' (0x49), 'H' (0x48), 'L' (0x4C), 'T' (0x54), '-' (0x2D)

For Input/Output rules (registers 3004 - 3009) the value corresponds to the ASCII value of the character representing the rule, as described above for the Console configuration.

Relays

Use Modbus function Read Coils, at coil address 1 to 6 (4 for MKR and RP), to read the status of the output relays.

Use functions Write Single Coil or Write Multiple Coils to control the relays output.

Address (decimal) Size [bit] Description R/W Functions
1 1 relay 1 status r/w 1,5,15
2 1 relay 2 status r/w 1,5,15
3 1 relay 3 status r/w 1,5,15
4 1 relay 4 status r/w 1,5,15
5 1 relay 5 status r/w 1,5,15
6 1 relay 6 status r/w 1,5,15

Use function Write Single Register or Write Multiple Registers to temporarily close the relays.

Address (decimal) Size [word] Description R/W Functions Type Range Unit
11 1 relay 1 close time w 6,16 unsigned short 1 - 65535 s/10
12 1 relay 2 close time w 6,16 unsigned short 1 - 65535 s/10
13 1 relay 3 close time w 6,16 unsigned short 1 - 65535 s/10
14 1 relay 4 close time w 6,16 unsigned short 1 - 65535 s/10
15 1 relay 5 close time w 6,16 unsigned short 1 - 65535 s/10
16 1 relay 6 close time w 6,16 unsigned short 1 - 65535 s/10

Analog (PWM) output

Use Modbus function Read Holding Registers at address 601 to read the status of the analog output AO1. The returned value is in mV, so the value range is 0 to 10000.

Use function Write Single Register to control the voltage output of AO1.

Address (decimal) Size [word] Description R/W Functions Type Range Unit
601 1 write analog voltage output AO1 r/w 3,6 unsigned short 0 - 10000 mV

Digital inputs

Digital inputs DI1 to DI6 can be read at two different address ranges, using function Read Discrete Inputs. Reading addresses 101 to 106 returns the value of the input pins filtered with a de-bounce function. This filter has a 25 ms time constant, so that a value change is reported only after being stable for at least 25 milliseconds.

Reading addresses 111 to 116 returns the instantaneous value of the input pins, with no de-bounce filter applied.

Address (decimal) Size [bit] Description R/W Functions
101 1 read digital input DI1 (with de-bounce) r 2
102 1 read digital input DI2 (with de-bounce) r 2
103 1 read digital input DI3 (with de-bounce) r 2
104 1 read digital input DI4 (with de-bounce) r 2
105 1 read digital input DI5 (with de-bounce) r 2
106 1 read digital input DI6 (with de-bounce) r 2
111 1 read digital input DI1 (no de-bounce) r 2
112 1 read digital input DI2 (no de-bounce) r 2
113 1 read digital input DI3 (no de-bounce) r 2
114 1 read digital input DI4 (no de-bounce) r 2
115 1 read digital input DI5 (no de-bounce) r 2
116 1 read digital input DI6 (no de-bounce) r 2

Analog inputs and digital counters

Use Modbus function Read Input Registers to read the values of analog inputs. Reading addresses 201 to 204 returns the voltage on AV1 to AV4 in mV, from 0 to 10000 (30000 for MKR). Reading addresses 301 to 304 returns the current on AI1 to AI4 in mA/1000 (µA), from 0 to 20000 (25000 for MKR).

Registers 211 to 214 and 311 to 314 contain the above values averaged on 32 subsequent readings.

This sketch also implements counters on digital inputs. Reading input registers at address 1001 to 1006 returns unsigned short values from 0 to 65535. These counters are incremented by one (and rolled back to 0 after reaching 65535) on the positive rise of their respective inputs, after the de-bounce filter.

Address (decimal) Size [word] Description R/W Functions Type Range Unit
201 1 read analog voltage input AV1 r 4 unsigned short 0-30000 mV
202 1 read analog voltage input AV2 r 4 unsigned short 0-30000 mV
203 1 read analog voltage input AV3 r 4 unsigned short 0-30000 mV
204 1 read analog voltage input AV4 r 4 unsigned short 0-30000 mV
211 1 read analog voltage input AV1 (averaged) r 4 unsigned short 0-30000 mV
212 1 read analog voltage input AV2 (averaged) r 4 unsigned short 0-30000 mV
213 1 read analog voltage input AV3 (averaged) r 4 unsigned short 0-30000 mV
214 1 read analog voltage input AV4 (averaged) r 4 unsigned short 0-30000 mV
301 1 read analog current input AI1 r 4 unsigned short 0-25000 µA
302 1 read analog current input AI2 r 4 unsigned short 0-25000 µA
303 1 read analog current input AI3 r 4 unsigned short 0-25000 µA
304 1 read analog current input AI4 r 4 unsigned short 0-25000 µA
311 1 read analog current input AI1 (averaged) r 4 unsigned short 0-25000 µA
312 1 read analog current input AI2 (averaged) r 4 unsigned short 0-25000 µA
313 1 read analog current input AI3 (averaged) r 4 unsigned short 0-25000 µA
314 1 read analog current input AI4 (averaged) r 4 unsigned short 0-25000 µA
1001 1 read digital input DI1 counter r 4 unsigned short 0-65535 n/a
1002 1 read digital input DI2 counter r 4 unsigned short 0-65535 n/a
1003 1 read digital input DI3 counter r 4 unsigned short 0-65535 n/a
1004 1 read digital input DI4 counter r 4 unsigned short 0-65535 n/a
1005 1 read digital input DI5 counter r 4 unsigned short 0-65535 n/a
1006 1 read digital input DI6 counter r 4 unsigned short 0-65535 n/a

1-Wire Dallas temperature sensors

Note: Not supported on Iono RP

Inputs DI5 and DI6 (with internal jumpers set to BYP position) can alternatively be used as 1-Wire bus lines. This sketch supports up to 8 Dallas temperature sensors connected to each bus line.

Each bus is activated by performing a read of registers 5000 (DI5 bus) and 6000 (DI6 bus) which return the number of detected devices.

Once enabled, discovered devices' addresses are available at registers 5001-5064 for DI5 and 6001-6064 for DI6. Each address consists of 8 bytes split in 8 consecutive registers, i.e. the first device address of bus DI5 is contained in registers 5001-5008, the second in 5009-5016, and so on.

Temperature values are requested every 10 seconds and available at registers 5101-5108 for bus DI5 and 6101-6108 for bus DI6.

Address (decimal) Size [word] Description R/W Functions Type Range Unit
5000 1 enable bus DI5 and get number of discovered devices r 3 unsigned short 0-8 n/a
6000 1 enable bus DI6 and get number of discovered devices r 3 unsigned short 0-8 n/a
5001-5064 1 devices' addresses bytes (DI5 bus) r 3 unsigned short 0-255 n/a
6001-6064 1 devices' addresses bytes (DI6 bus) r 3 unsigned short 0-255 n/a
5101-5108 1 read temperature (DI5 bus) r 4 signed short device dependent. Error = -12700 °C/100
6101-6108 1 read temperature (DI6 bus) r 4 signed short device dependent. Error = -12700 °C/100

Wiegand devices

Inputs DI5 and DI6 (with internal jumpers set to BYP position) can alternatively be used as Wiegand interface lines, DATA0 and DATA1 respectively.

The Wiegand interface is enabled upon the first reading of register 8001.

When new data is available on the interface, register 8001 is updated with the number of bits read. Reading register 8001 triggers the update of register 8002 with the read data; after a positive number is returned, subsequent reads will return 0 until new data is available. If -1 is returned it indicates that data is currently being received so it will be shortly available.

Register 8002 contains up to 64 bits split in 4 words, starting from the 16 least significant bits. Therefore, to collect Wiegand data, periodically read register 8001 and when a positive value is returned read the necessary number of words (or all 4) from register 8002.

Address (decimal) Size [word] Description R/W Functions Type
8001 1 new data bits number r 4 signed short
8002 1 - 4 new data r 4 bits
8010 1 latest noise event (see below), reset to 0 after read r 4 unsigned short

Noise detected on the DATA0/DATA1 lines:

Noise value Description
0 No noise
10 Fast pulses on lines
11 Pulses interval too short
12/13 Concurrent movement on both DATA0/DATA1 lines (possibly short circuit between lines)
14 Pulse too short
15 Pulse too long
Clone this wiki locally