TapHome

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.

TypeModbus objectFunction codesAccess
CCoilFC01 read, FC05 / FC15 writeread and write
DDiscrete inputFC02read only
HHolding registerFC03 read, FC06 / FC16 writeread and write
AInput registerFC04read 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.

1
2
MODBUSR(registerType, register, dataType)
MODBUSR(registerType, register, String, numberOfRegisters)
NameTypeDescription
registerTypeC, D, H, ASee Register types.
registernumberRegister address 0 – 65535, decimal or hexadecimal (0x14).
dataTypeModbus data typeDecides how many registers are read: 1, 2 or 4.
numberOfRegistersnumberRequired 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 characters

Errors — 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.

1
MODBUSW(registerType, register, dataType, value [, value2, …])

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 the Bool data type; D and A cannot 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.

1
MODBUSWNE(registerType, register, dataType, value)

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.

1
MODBUSRBLOCK(registerType, register, count)
Register typeReturnsMaximum count
H, Acollection<uint16>123 (FC03 / FC04)
C, Dcollection<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 101

Errors — 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.

1
MODBUSWBLOCK(registerType, register, collection)
Register typeCollectionMaximum length
Hcollection<uint16>123 (FC16)
Ccollection<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.

1
MODBUSWBLOCKNE(registerType, register, collection)

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.