Passa al contenuto principale

ModbusSlave, modbus slave

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

Upgrade list

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​

Immagine FB_ModbusSlave_v5

ParametroTipoDescrizione
EnableBOOLComando di abilitazione blocco funzione.
SpyOnBOOLSe attivo permette di spiare il funzionamento della FB (Vedi articolo).
AbsoluteBOOLIl FB somma 1 all'indirizzo Modbus per compensare l'offset -1. Se bit attivo si considera indirizzamento assoluto e non si compensa l'offset.
Filee_FILEPFlusso dati stream da utilizzare per la comunicazione.
TypeMODBUS_PROTOCOLTipo di protocollo modbus (Definizione).
NodeUSINTNumero di nodo modbus (Range da 0 a 255).
OffsetUINTOffset su indirizzo modbus ricevuto nel frame dati (Range da 16#0000 a 16#FFFF).
BufferPVOIDIndirizzo buffer dati su cui operano i comandi modbus.
SizeUDINTDimensione in byte del buffer dati su cui operano i comandi modbus.
TimeoutTIMEDefinizione timeout di esecuzione.
DoneBOOLSi attiva per un loop di programma al termine della esecuzione richiesta.
FaultBOOLAttivo per un loop se errore esecuzione richiesta.
CTimeTIMETempo richiesto per la ricezione di una interrogazione Modbus e invio della risposta.
PacketsUDINTNumero di richieste modbus gestite, incrementato ad ogni richiesta, raggiunto massimo riparte da 0.
ErrorsUDINTNumero 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

CodeNameDescription
16#01Illegal functionE' stato richiesto un codice funzione che il dispositivo non supporta.
16#02Illegal data addressViene generato in diverse situazioni: - Richiesto un registro non implementato (o un'area inesistente) - Richiesta la lettura di un numero di registri che va oltre l'area implementata (partendo dall'indirizzo richiesto) - Si è tentato di scrivere in un'area read‐only
16#03Illegal data valueIl dato definito nella richiesta non è accettato dal dispositivo.
16#04Slave device failureSi è verificato un errore irreversibile mentre lo slave stava tentando di eseguire l'azione richiesta.
16#05AcknowledgeLo 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#06Slave device busyLo slave è impegnato nell'elaborazione di un comando che richiede una lunga elaborazione.
16#07Negative acknowledgeLo slave non può eseguire la funzione di programma ricevuta nella query.
16#08Memory parity errorLo 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

TriggerDescrizione
16#00000001Rx: Ricezione frame comando modbus.
16#00000002Tx: Invio frame risposta modbus.
16#10000000Lg: Log esecuzione.
16#40000000Er: Errore di esecuzione.

Esempi​

Come utilizzare gli 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]