Sui sistemi SlimLine e Netsyst il protocollo modbus slave è già implementato dal sistema operativo (Vedi articolo), pertanto non occorre inserire blocchi funzione appositi nel programma utente. Questo blocco si utilizza in casi particolari, dove non è possibile utilizzare la gestione implementata nel sistema operativo. Per esempio quando si vuole consentire l’accesso ad un propria area di memoria diversa dalla DB100.
Il blocco funzione esegue la gestione del protocollo modbus slave, per la codifica/decodifica dei frame Modbus viene utilizzato il FB _SModbusFrame. Con Type è possibile selezionare il tipo di protocollo RTU, Ascii ed over IP. Con File è possibile definire il terminale di I/O su cui effettuare la comunicazione.
Occorre definire il nodo modbus Node, e l’eventuale offset di indirizzo frame modbus Offset. I comandi modbus ricevuti operano sul buffer di memoria il cui indirizzo è definito in Buffer e la dimensione in bytes è definita in Size.
Alla ricezione di ogni comando modbus corretto si attiva per un loop l’uscita Done e si incrementa Packets. In caso di errore comando viene attivata per un loop l’uscita Fault ed incrementato il valore in Errors.
Approfondimenti
- In questo topic esempio utilizzo FB con più blocchi di memoria.
- In questo topic considerazioni sull’utilizzo del FB.
Upgrade list
- Se l’oggetto aggiornato non è nell’ultima versione del package, vedi capitolo “Aggiornamento librerie” in questo articolo.
- Gli oggetti obsoleti sono inseriti nella libreria eLLabObsoleteLib fare riferimento al relativo manuale ed al manuale programmazione in formato pdf.
ModbusSlave_v2
Implementa una gestione ottimizzata della acquisizione dei frames modbus di comando evitando la dichiarazione del parametro IFTime. Tutti gli altri parametri in ingresso rimangono invariati, aggiunto i parametri CTime e Packets in uscita.
ModbusSlave_v3
Aggiunta gestione ingresso Absolute, se attivo considera indirizzamento assoluto e non viene sommato 1 all’indirizzo Modbus ricevuto. Visto che è stato aggiunto il solo parametro di ingresso Absolute mantenendo identico il funzionamento può sostituire la ModbusSlave_v2 nei progetti esistenti.
ModbusSlave_v4
Ingresso Type di definizione tipo di protocollo ora è di tipo MODBUS_PROTOCOL. Il parametro in uscita CTime ora è di tipo TIME.
ModbusSlave_v5
Inserito parametro Timeout in ingresso.
Descrizione
Enable (BOOL) Comando di abilitazione blocco funzione.
SpyOn (BOOL) Se attivo permette di spiare il funzionamento della FB (Vedi articolo).
Absolute (BOOL) Il FB somma 1 all’indirizzo Modbus per compensare l’offset -1. Se bit attivo si considera indirizzamento assoluto e non si compensa l’offset.
File (eFILEP) Flusso dati stream da utilizzare per la comunicazione.
Type (MODBUS_PROTOCOL) Tipo di protocollo modbus (Definizione).
Node (USINT) Numero di nodo modbus (Range da 0 a 255).
Offset (UINT) Offset su indirizzo modbus ricevuto nel frame dati (Range da 16#0000 a 16#FFFF).
Buffer (PVOID) Indirizzo buffer dati su cui operano i comandi modbus.
Size (UDINT) Dimensione in byte del buffer dati su cui operano i comandi modbus.
Timeout (TIME) Definizione timeout di esecuzione.
Done (BOOL) Si attiva per un loop di programma al termine della esecuzione richiesta.
Fault (BOOL) Attivo per un loop se errore esecuzione richiesta.
CTime (TIME) Tempo richiesto per la ricezione di una interrogazione Modbus e invio della risposta.
Packets (UDINT) Numero di richieste modbus gestite, incrementato ad ogni richiesta, raggiunto massimo riparte da 0.
Errors (UDINT) Numero di errori, incrementato ad ogni errore, raggiunto massimo riparte da 0.

FCode, funzioni modbus supportate
16#01 Read coil status (Massimo 250 coils)
16#02 Read input status (Massimo 125 inputs)
16#03 Read holding registers (Massimo 125 registri)
16#04 Read input registers (Massimo 125 registri)
+----+-----------+---+---+---+---+ +----+-----------+-----+--...--+ Query |Node|01/02/03/04|Address|Points | Response |Node|01/02/03/04|Bytes| Data | +----+-----------+---+---+---+---+ +----+-----------+-----+--...--+
16#05 Force single coil
16#06 Preset single register
+----+-----+---+---+--+--+ +----+-----+---+---+--+--+ Query |Node|05/06|Address|Data | Response |Node|05/06|Address|Data | +----+-----+---+---+--+--+ +----+-----+---+---+--+--+
16#0F Force Multiple Coils (Massimo 250 coils)
16#10 Preset multiple registers (Massimo 125 registri)
+----+-----+---+---+---+---+-----+--...--+ +----+-----+---+---+---+---+ Query |Node|0F/10|Address|Points |Bytes| Data | Response |Node|0F/10|Address|Points | +----+-----+---+---+---+---+-----+--...--+ +----+-----+---+---+---+---+
16#41 Read memory bytes (Funzione custom, massimo 250 bytes)
+----+--+---+---+---+---+ +----+--+-------+--...--+ Query |Node|41|Address|Points | Response |Node|41|Points | Data | +----+--+---+---+---+---+ +----+--+-------+--...--+
16#42 Write memory bytes (Funzione custom, massimo 250 bytes)
+----+--+---+---+---+---+--...--+ +----+--+-------+ Query |Node|42|Address|Points | Data | Response |Node|42|Points | +----+--+---+---+---+---+--...--+ +----+--+-------+
I codici 16#41 e 16#42 sono stati implementati per compatibilità con i vecchi sistemi programmabili con Remoter.
Messaggi di errore (Eccezione)
Il dispositivo, se non è in grado di eseguire l’operazione richiesta dal comando ricevuto, risponde con un messaggio di errore che prevede il seguente formato:
+-------------+---------------+----------------+---+---+ | Modbus node | Function code | Exception code | CRC | +-------------+---------------+----------------+---+---+
- Modbus node: Indirizzo del dispositivo slave che risponde.
- Function code: Codice funzione con MSB=1 (per indicare l’eccezione); esempio 16#83 (per la lettura 16#03 ) o 16#86 (per la scrittura 16#06).
- Exception code: Codice eccezione.
Codici eccezione
Code | Name | Description |
---|---|---|
16#01 | Illegal function | E’ stato richiesto un codice funzione che il dispositivo non supporta. |
16#02 | Illegal data address | Viene generato in diverse situazioni:
|
16#03 | Illegal data value | Il dato definito nella richiesta non è accettato dal dispositivo. |
16#04 | Slave device failure | Si è verificato un errore irreversibile mentre lo slave stava tentando di eseguire l’azione richiesta. |
16#05 | Acknowledge | Lo slave ha accettato la richiesta e la sta elaborando, ma per farlo sarà necessario un lungo periodo di tempo. Questa risposta viene restituita per evitare che si verifichi un errore di timeout nel master. |
16#06 | Slave device busy | Lo slave è impegnato nell’elaborazione di un comando che richiede una lunga elaborazione. |
16#07 | Negative acknowledge | Lo slave non può eseguire la funzione di programma ricevuta nella query. |
16#08 | Memory parity error | Lo slave ha tentato di leggere la memoria ma ha rilevato un errore di parità. |
Trigger di spy
Se SpyOn attivo è possibile utilizzare utilizzare la console di spionaggio per verificare il funzionamento della FB. Sono previsti vari livelli di triggers.
Livelli di trigger
Trigger | Descrizione |
---|---|
16#00000001 | Rx: Ricezione frame comando modbus. |
16#00000002 | Tx: Invio frame risposta modbus. |
16#10000000 | Lg: Log esecuzione. |
16#40000000 | Er: Errore di esecuzione. |
Esempi
ST_ModbusSlave: E’ possibile utilizzare l’esempio in TCP su di un unico sistema SlimLine definendo come indirizzo IP dello slave il localhost ADR(‘127.0.0.1’). Oppure in RTU o ascii selezionando la comunicazione seriale. Nell’esempio il FB si comporta esattamente come la gestione Modbus del sistema operativo, è possibile utilizzare l’esempio insieme all’esempio del FB ModbusMaster.
LogicLab (Ptp205, ST_ModbusSlave)
PROGRAM ST_ModbusSlave
VAR
SerialOrTCP : BOOL; (* FALSE:Serial, TRUE:TCP communication *)
Fp : eFILEP; (* File pointer *)
Sp : SysSerialPort; (* Serial port *)
TCPServer : SysTCPServer; (* TCPServer management *)
SMdb : ModbusSlave_v5; (* Modbus slave FB *)
END_VAR
// *****************************************************************************
// PROGRAM "ST_ModbusSlave"
// *****************************************************************************
// It's instantiated a Modbus slave FB connected to the defined serial port. It
// operates over the DB100 memory area exactly as the embedded Modbus.
// -----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// INITIALIZATION
// -------------------------------------------------------------------------
// Program initializations.
IF (SysFirstLoop) THEN
// Serial port settings.
Sp.COM:=ADR('COM0'); //COM port definition
Sp.Baudrate:=115200; //Baudrate
Sp.Parity:='E'; //Parity
Sp.DataBits:=8; //Data bits
Sp.StopBits:=1; //Stop bits
Sp.DTRManagement:=DTR_AUTO_WO_TIMES; //DTR management
Sp.DTRComplement:=FALSE; //DTR complement
Sp.EchoFlush:=FALSE; //Received echo flush
Sp.DTROnTime:=0; //DTR On time delay (mS)
Sp.DTROffTime:=0; //DTR Off time delay (mS)
Sp.FlushTm:=0; //Flush time (mS)
Sp.RxSize:=0; //Rx buffer size
Sp.TxSize:=0; //Tx buffer size
// TCP server settings.
TCPServer.FilesArr:=ADR(Fp); //Files array
TCPServer.LocalAdd:=ADR('0.0.0.0'); //Local address
TCPServer.LocalPort:=3000; //Local port
TCPServer.MaxConn:=1; //Accepted connections
TCPServer.FlushTm:=50; //Flush time (mS)
TCPServer.LifeTm:=60; //Life time (S)
TCPServer.RxSize:=256; //Rx buffer size
TCPServer.TxSize:=256; //Tx buffer size
// Modbus slave settings.
SMdb.Absolute:=FALSE; //Absolute addressing
SMdb.Node:=1; //Device modbus node
SMdb.Offset:=40000; //Modbus address offset
SMdb.Buffer:=eToPVoid(ADR(%MX100.0)); //Modbus buffer address
SMdb.Size:=4096; //Modbus buffer size
SMdb.Timeout:=T#1s; //Timeout
END_IF;
// -------------------------------------------------------------------------
// MODBUS MANAGEMENT
// -------------------------------------------------------------------------
// Eseguo selezione canale comunicazione.
IF NOT(SerialOrTCP) THEN
// Serial port management.
Sp(Open:=TRUE); //Serial port management
SMdb.File:=Sp.File; //File pointer
SMdb.Type:=MODBUS_PROTOCOL#MDB_RTU; //Modbus type (RTU)
// SMdb.Type:=MODBUS_PROTOCOL#MDB_ASCII; //Modbus type (Ascii)
ELSE
// TCP server management.
TCPServer(Enable:=TRUE); //TCPServer management
SMdb.File:=Fp; //File pointer
SMdb.Type:=MODBUS_PROTOCOL#MDB_TCP; //Modbus type (TCP)
END_IF;
// Manage the modbus slave communication.
SMdb(Enable:=SysFIsOpen(SMdb.File)); //Modbus slave
// [End of file]