Modbus functions
TapHome script Modbus functions — MODBUSR, MODBUSW, MODBUSWNE and the block functions MODBUSRBLOCK, MODBUSWBLOCK, MODBUSWBLOCKNE — and the Modbus register types C, D, H and A.
Modbus functions read and write the coils and registers of the Modbus device that a script belongs to. They work only in the scripts of a Modbus module or device; anywhere else the script stops with ModbusFunction - unknown modbus device to work with. The data type names (Uint16, BigEndianFloat, …) are on Modbus data types. Setting up the module and templates is described in Modbus integration.
Register types
The first argument of every Modbus function is the register type.
| Type | Modbus object | Function codes | Access |
|---|---|---|---|
C | Coil | FC01 read, FC05 / FC15 write | read and write |
D | Discrete input | FC02 | read only |
H | Holding register | FC03 read, FC06 / FC16 write | read and write |
A | Input register | FC04 | read only |
SC and SH are older values that scripts still accept. They address the same coils and holding registers as C and H, but the module reads them from the device on every call instead of from the cache and writes them one register per request (FC05 / FC06). Use C and H in new scripts. This behaviour is taken from the engine code and was not verified on a device.
MODBUSR
MODBUSR reads one value from a coil, a discrete input or one or more registers and converts it to the given data type.
| |
| Name | Type | Description |
|---|---|---|
registerType | C, D, H, A | See Register types. |
register | number | Register address 0 – 65535, decimal or hexadecimal (0x14). |
dataType | Modbus data type | Decides how many registers are read: 1, 2 or 4. |
numberOfRegisters | number | Required for String, 0 – 123. One register holds 2 characters. |
Returns — a number for the 16- and 32-bit types, Float and Double; bool for Bool; int64 or uint64 for Int64 and UInt64; a string for String, ending at the first zero byte.
Remarks — A multi-register value is read in one request, so all its registers come from the same moment.
Example
MODBUSR(H, 20, Int16) / 100;
# Result: the register as a signed number, divided by 100
MODBUSR(A, 0x0040, Uint32);
MODBUSR(H, 14, String, 4);
# Result: text of up to 8 charactersErrors — Invalid register number: X; String data type must have specified length - number of registers to read.
MODBUSW
MODBUSW writes one value, or up to 101 values to consecutive registers, and returns TRUE.
| |
Remarks
- With several values the register address moves by the size of the data type — 1, 2 or 4 registers per value.
- A coil (
C) accepts only theBooldata type;DandAcannot be written. - How values are rounded and checked is described in Writing values.
Example
MODBUSW(H, 20, Int16, Te * 100);
MODBUSW(H, 100, Uint16, 1, 2, 3);
# Result: TRUE — registers 100, 101 and 102 are written
MODBUSW(C, 5, Bool, St);Errors — WriteInt16: Cannot write Int16 to coils (and the same for other types); Invalid register number: X.
MODBUSWNE
MODBUSWNE (“write if not equal”) writes one value like MODBUSW, but only when it differs from the value the register holds, which saves bus traffic and the EEPROM write cycles of the device.
| |
Remarks
- The value is compared with the module’s register cache. With prefetch on, that is the value read by the last prefetch (the register is added to the prefetch); a register not read yet is read first. With No prefetch the register is read from the device right before the comparison.
- It is never compared with the value written last time: a write does not change the cached value until the register is read again.
- A multi-register value is compared and written as a whole.
Example — configuration in the initialize script
MODBUSWNE(H, 27, Uint16, 0);MODBUSRBLOCK
MODBUSRBLOCK reads a block of consecutive registers or coils in one Modbus transaction and returns them as a collection.
| |
| Register type | Returns | Maximum count |
|---|---|---|
H, A | collection<uint16> | 123 (FC03 / FC04) |
C, D | collection<bool> | 2000 (FC01 / FC02) |
Remarks — With prefetch on, registers already in the cache are not read again; the missing ones are read in one request. Read typed values from the block with UNPACKVALUE. One block read replaces many single reads.
Example
collection<uint16> data := MODBUSRBLOCK(H, 100, 4);
UNPACKVALUE(data, 0, BigEndianFloat);
# Result: the float in registers 100 and 101Errors — MODBUSRBLOCK: count must be between 1 and 123 for 16-bit registers (H); MODBUSRBLOCK: invalid register range X..Y.
Available — Core 2026.1, build 39001 or newer (app build 39016 or newer). The same holds for MODBUSWBLOCK and MODBUSWBLOCKNE.
MODBUSWBLOCK
MODBUSWBLOCK writes a whole collection to consecutive holding registers or coils in one Modbus transaction and returns TRUE. A block longer than the prefetch group size of the module (100 by default) is split into several consecutive requests.
| |
| Register type | Collection | Maximum length |
|---|---|---|
H | collection<uint16> | 123 (FC16) |
C | collection<bool> | 1968 (FC15) |
Example — set coils 0 and 3, clear coils 1, 2 and 4 to 7
collection<bool> coils := BOOLCOLLECTION(8);
SETAT(coils, 0, TRUE);
SETAT(coils, 3, TRUE);
MODBUSWBLOCK(C, 0, coils);Errors — MODBUSWBLOCK: cannot write to read-only registers (D); MODBUSWBLOCK: register type C expects Collection<Bool>, got Collection<UInt16>.
MODBUSWBLOCKNE
MODBUSWBLOCKNE writes a collection like MODBUSWBLOCK, but only when at least one value differs from the current contents of the registers; a changed block is written the same way, split by the same group size.
| |
Remarks — The current contents are read the same way as for MODBUSWNE.
Example — change one register of a block with minimal bus traffic
collection<uint16> c := MODBUSRBLOCK(H, 100, 4);
PACKVALUE(c, 1, Uint16, 9);
MODBUSWBLOCKNE(H, 100, c);See also — Modbus scripts and prefetch, Binary data, Bit operations.