TapHome

Funzioni Modbus

Funzioni Modbus degli script TapHome — MODBUSR, MODBUSW, MODBUSWNE e le funzioni a blocchi MODBUSRBLOCK, MODBUSWBLOCK, MODBUSWBLOCKNE — e i tipi di registro Modbus C, D, H e A.

Le funzioni Modbus leggono e scrivono i coil e i registri del dispositivo Modbus a cui appartiene uno script. Funzionano solo negli script di un modulo o di un dispositivo Modbus; altrove lo script si interrompe con ModbusFunction - unknown modbus device to work with. I nomi dei tipi di dati (Uint16, BigEndianFloat, …) si trovano in Tipi di dati Modbus. La configurazione del modulo e dei modelli è descritta in Integrazione Modbus.

Tipi di registro

Il primo argomento di ogni funzione Modbus è il tipo di registro.

TipoOggetto ModbusCodici funzioneAccesso
CCoilFC01 lettura, FC05 / FC15 scritturalettura e scrittura
DDiscrete inputFC02sola lettura
HHolding registerFC03 lettura, FC06 / FC16 scritturalettura e scrittura
AInput registerFC04sola lettura

SC e SH sono valori più vecchi che gli script accettano ancora. Indirizzano gli stessi coil e holding register di C e H, ma il modulo li legge dal dispositivo a ogni chiamata invece che dalla cache e li scrive un registro per richiesta (FC05 / FC06). Negli script nuovi usa C e H. Questo comportamento è ricavato dal codice del motore e non è stato verificato su un dispositivo.

MODBUSR

MODBUSR legge un valore da un coil, da un discrete input o da uno o più registri e lo converte nel tipo di dati indicato.

1
2
MODBUSR(registerType, register, dataType)
MODBUSR(registerType, register, String, numberOfRegisters)
NomeTipoDescrizione
registerTypeC, D, H, AVedi Tipi di registro.
registernumeroIndirizzo del registro 0 – 65535, decimale o esadecimale (0x14).
dataTypetipo di dati ModbusDecide quanti registri vengono letti: 1, 2 o 4.
numberOfRegistersnumeroObbligatorio per String, 0 – 123. Un registro contiene 2 caratteri.

Valore restituito — un numero per i tipi a 16 e 32 bit, Float e Double; bool per Bool; int64 o uint64 per Int64 e UInt64; una stringa per String, che termina al primo byte zero.

Note — Un valore su più registri viene letto in un’unica richiesta, quindi tutti i suoi registri provengono dallo stesso istante.

Esempio

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

Errori — Invalid register number: X; String data type must have specified length - number of registers to read.

MODBUSW

MODBUSW scrive un valore, oppure fino a 101 valori in registri consecutivi, e restituisce TRUE.

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

Note

  • Con più valori l’indirizzo del registro avanza della dimensione del tipo di dati — 1, 2 o 4 registri per valore.
  • Un coil (C) accetta solo il tipo di dati Bool; D e A non si possono scrivere.
  • Come i valori vengono arrotondati e controllati è descritto in Scrittura dei valori.

Esempio

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);

Errori — WriteInt16: Cannot write Int16 to coils (e lo stesso per gli altri tipi); Invalid register number: X.

MODBUSWNE

MODBUSWNE (“write if not equal”, scrivi se diverso) scrive un valore come MODBUSW, ma solo quando è diverso dal valore contenuto nel registro, il che riduce il traffico sul bus e i cicli di scrittura EEPROM del dispositivo.

1
MODBUSWNE(registerType, register, dataType, value)

Note

  • Il valore viene confrontato con la cache dei registri del modulo. Con il prefetch attivo, è il valore letto dall’ultimo prefetch (il registro viene aggiunto al prefetch); un registro non ancora letto viene letto prima. Con No prefetch il registro viene letto dal dispositivo subito prima del confronto.
  • Non viene mai confrontato con il valore scritto l’ultima volta: una scrittura non cambia il valore in cache finché il registro non viene letto di nuovo.
  • Un valore su più registri viene confrontato e scritto per intero.

Esempio — configurazione nello script di inizializzazione

MODBUSWNE(H, 27, Uint16, 0);

MODBUSRBLOCK

MODBUSRBLOCK legge un blocco di registri o coil consecutivi in un’unica transazione Modbus e li restituisce come collezione.

1
MODBUSRBLOCK(registerType, register, count)
Tipo di registroRestituiscecount massimo
H, Acollection<uint16>123 (FC03 / FC04)
C, Dcollection<bool>2000 (FC01 / FC02)

Note — Con il prefetch attivo, i registri già presenti nella cache non vengono letti di nuovo; quelli mancanti vengono letti in un’unica richiesta. Leggi i valori tipizzati dal blocco con UNPACKVALUE. Una lettura a blocco sostituisce molte letture singole.

Esempio

collection<uint16> data := MODBUSRBLOCK(H, 100, 4);
UNPACKVALUE(data, 0, BigEndianFloat);
# Result: the float in registers 100 and 101

Errori — MODBUSRBLOCK: count must be between 1 and 123 for 16-bit registers (H); MODBUSRBLOCK: invalid register range X..Y.

Disponibile — Core 2026.1, build 39001 o più recente (app build 39016 o più recente). Lo stesso vale per MODBUSWBLOCK e MODBUSWBLOCKNE.

MODBUSWBLOCK

MODBUSWBLOCK scrive un’intera collezione in holding register o coil consecutivi in un’unica transazione Modbus e restituisce TRUE. Un blocco più lungo della dimensione del gruppo di prefetch del modulo (100 per impostazione predefinita) viene suddiviso in più richieste consecutive.

1
MODBUSWBLOCK(registerType, register, collection)
Tipo di registroCollezioneLunghezza massima
Hcollection<uint16>123 (FC16)
Ccollection<bool>1968 (FC15)

Esempio — attivare i coil 0 e 3, disattivare i coil 1, 2 e da 4 a 7

collection<bool> coils := BOOLCOLLECTION(8);
SETAT(coils, 0, TRUE);
SETAT(coils, 3, TRUE);
MODBUSWBLOCK(C, 0, coils);

Errori — MODBUSWBLOCK: cannot write to read-only registers (D); MODBUSWBLOCK: register type C expects Collection<Bool>, got Collection<UInt16>.

MODBUSWBLOCKNE

MODBUSWBLOCKNE scrive una collezione come MODBUSWBLOCK, ma solo quando almeno un valore è diverso dal contenuto attuale dei registri; un blocco cambiato viene scritto allo stesso modo, suddiviso con la stessa dimensione del gruppo.

1
MODBUSWBLOCKNE(registerType, register, collection)

Note — Il contenuto attuale viene letto allo stesso modo che per MODBUSWNE.

Esempio — cambiare un registro di un blocco con il minimo traffico sul bus

collection<uint16> c := MODBUSRBLOCK(H, 100, 4);
PACKVALUE(c, 1, Uint16, 9);
MODBUSWBLOCKNE(H, 100, c);

Vedi anche — Script Modbus e prefetch, Dati binari, Operazioni sui bit.