ModbusMaster, modbus master

List

Questa pagina fa parte del Manuale Programmazione IEC 61131-3. Vai all indice.

Questo blocco funzione da eseguire in task Back utilizzabile con modello a cascata, esegue la gestione del protocollo modbus master, 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.

Attivando Enable sul terminale di I/O viene inviato un frame per eseguire la funzione modbus definita in FCode sul nodo definito in Node. Terminata l’esecuzione del comando viene attivata l’uscita Done. Se l’esecuzione comando ha esito positivo si attiva per un loop di programma l’uscita Ok. Disattivando Enable si azzera Done e l’eventuale Fault, per eseguire nuovamente il comando occorre riabilitare l’ingresso Enable. L’ingresso SpyOn se attivo permette di spiare il funzionamento della FB.

Se FCode è una funzione di lettura, il valore delle variabili a partire dall’indirizzo definito in Address per il numero di variabili definito da Points, viene letto dal sistema slave e trasferito nelle variabili indirizzate da Buffer. Se FCode è una funzione di scrittura, il valore delle variabili presenti nel buffer di memoria indirizzato da Buffer per il numero di variabili definito da Points, è inviato al dispositivo slave che lo trasferirà nelle sue variabili a partire dall’indirizzo definito in Address. Sono supportati i seguenti codici modbus.

Ad ogni esecuzione corretta del comando viene attivata per un loop di programma l’uscita Done ed incrementato il valore di Packets. In caso di errore esecuzione o tempo di esecuzione comando superiore al tempo definito in Timeout, viene attivata per un loop di programma l’uscita Fault ed incrementato il valore in Errors.

Utilizzandolo con i FB dedicati alla gestione dei dispositivi Modbus si semplifica notevolmente lo sviluppo delle applicazioni.

Upgrade list

ModbusMaster_v1

Implementa una gestione ottimizzata della acquisizione dei frames modbus di risposta evitando la dichiarazione del parametro IFTime. Tutti gli altri parametri in ingresso rimangono invariati, i parametri Timeout e Delay ora sono definiti di tipo REAL ed occorre impostarne il valore in secondi.

ModbusMaster_v2

Aggiunta gestione ingresso Absolute, se attivo considera indirizzamento assoluto e non viene sottratto 1 all’indirizzo Modbus inviato nel frame di richiesta. Visto che è stato aggiunto il solo parametro di ingresso Absolute mantenendo identico il funzionamento può sostituire la ModbusMaster_v1 nei progetti esistenti.

ModbusMaster_v3

Ingresso Type di definizione tipo di protocollo ora è di tipo MODBUS_PROTOCOL. I parametri in I/O Timeout, Delay e CTime ora sono di tipo TIME.

Information Circle

Blocco funzione

CODESYS: Non disponibile

LogicLab: eLLabModbusLib

Descrizione

Enable (BOOL) Comando abilitazione esecuzione comando modbus. Per rieseguire il comando disabilitare e poi riabilitare questo ingresso.
SpyOn (BOOL) Se attivo permette di spiare il funzionamento della FB (Vedi articolo).
Absolute (BOOL) Per compatibilità con la specifica Modbus il FB sottrae 1 all’indirizzo Modbus. Se bit attivo si considera indirizzamento assoluto e non si esegue la sottrazione.
File (eFILEP) Flusso dati stream da utilizzare per la comunicazione.
Type (MODBUS_PROTOCOL) Tipo di protocollo modbus (Definizione).
Node (USINT) Numero di nodo modbus su cui effettuare il comando (Range da 0 a 255).
FCode (USINT) Codice funzione modbus da eseguire nel comando (Vedi tabella sotto).
Address (UINT) Indirizzo di allocazione variabili su sistema slave. In accordo alle specifiche modbus l’indirizzo inviato nel frame dati è (Address-1) (Range da 16#0001 a 16#FFFF).
Points (USINT) Numero di variabili consecutive su cui opera il comando.
Buffer (PVOID) Indirizzo buffer dati letti o da scrivere.
Timeout (TIME) Tempo massimo esecuzione comando. Se il comando non termina nel tempo definito viene abortito ed attivata l’uscita Fault.
Delay (TIME) Tempo di pausa dopo l’esecuzione del comando modbus.
Done (BOOL) Si attiva al termine della esecuzione comando e rimane attiva fino alla disabilitazione di Enable.
Ok (BOOL) Attivo per un loop se esecuzione comando corretta.
Fault (BOOL) Attivo per un loop se errore esecuzione comando.
CTime (TIME) Tempo di esecuzione comando, invio comando e ricezione risposta.
Packets (UDINT) Numero di comandi modbus eseguiti, incrementato ad ogni comando, raggiunto massimo riparte da 0.
Errors (UDINT) Numero di errori, incrementato ad ogni errore, raggiunto massimo riparte da 0.

Immagine FB_ModbusMaster
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 la console di spionaggio per verificare il funzionamento della FB. Sono previsti vari livelli di triggers.

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

Esempi

Come utilizzare gli esempi
ST_ModbusMaster: Vengono eseguiti comandi Modbus di lettura/scrittura sia di coils che di registri. E’ possibile utilizzare l’esempio su di un unico sistema SlimLine se usato in seriale collegando tra di loro le porte seriali COM0 e COM1 di un modulo CPU (Usare un cavo cross). Se usato in TCP definendo come indirizzo IP dello slave il localhost ADR(‘127.0.0.1′). E’ possibile utilizzare l’esempio insieme a quello del FB ModbusSlave.

LogicLab (Ptp205, ST_ModbusMaster)
PROGRAM ST_ModbusMaster
VAR
    i : UDINT; (* Aux counter *)
    SerialOrTCP : BOOL := FALSE; (* FALSE:Serial, TRUE:TCP communication *)
    CaseNr : USINT; (* Program case *)
    Sp : SysSerialPort; (* Serial port *)
    TCPClient : SysTCPClient; (* TCP client management *)
    MMdb : ModbusMaster_v3; (* Modbus master FB *)
    RCoils : ARRAY[0..15] OF BOOL; (* Coil status (Read) *)
    RHRegs : ARRAY[0..15] OF WORD; (* Holding registers (Read) *)
    WCoils : ARRAY[0..15] OF BOOL; (* Coil status (Write) *)
    WHRegs : ARRAY[0..15] OF WORD; (* Holding registers (Write) *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_ModbusMaster"
// *****************************************************************************
// Are executed all possible Modbus commands with a connection over another
// SlimLine. It's possible to test all the three possible Modbus types (Serial
// RTU, serial ascii, TCP).
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // 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 client settings.
        // Port 502 to connect to embed Modbus slave.
        // Port 3000 to connect to ModbusSlave FB example.

        TCPClient.PeerAdd:=ADR('127.0.0.1'); //Peer address
        TCPClient.PeerPort:=3000; //Peer port
        TCPClient.LocalAdd:=ADR('0.0.0.0'); //Local address
        TCPClient.LocalPort:=0; //Local port
        TCPClient.FlushTm:=50; //Flush time (mS)
        TCPClient.LifeTm:=20; //Life time (S)
        TCPClient.RxSize:=128; //Rx buffer size
        TCPClient.TxSize:=128; //Tx buffer size

        // Modbus master settings.

        MMdb.Absolute:=FALSE; //Absolute addressing
        MMdb.Node:=1; //Node number
        MMdb.Timeout:=T#1s; //Timeout time
        MMdb.Delay:=T#100ms; //Delay time
    END_IF;

    // -------------------------------------------------------------------------
    // MODBUS MANAGEMENT
    // -------------------------------------------------------------------------
    // Eseguo selezione canale comunicazione.

    IF NOT(SerialOrTCP) THEN

        // Serial port management.

        Sp(Open:=TRUE); //Serial port management
        MMdb.File:=Sp.File; //File pointer
        MMdb.Type:=MODBUS_PROTOCOL#MDB_RTU; //Modbus protocol type
      //  MMdb.Type:=MODBUS_PROTOCOL#MDB_ASCII; //Modbus protocol type
    ELSE

        // TCP client management.

        TCPClient(Connect:=TRUE); //TCPClient management
        MMdb.File:=TCPClient.File; //File pointer
        MMdb.Type:=MODBUS_PROTOCOL#MDB_TCP; //Modbus protocol type
    END_IF;

    // Manage the modbus master communication.

    MMdb(); //Modbus master
    IF NOT(SysFIsOpen(MMdb.File)) THEN MMdb.Enable:=FALSE; CaseNr:=0; RETURN; END_IF;

    // -------------------------------------------------------------------------
    // PROGRAM CASES
    // -------------------------------------------------------------------------
    // Manage the program cases.

    CASE (CaseNr) OF    

        // ---------------------------------------------------------------------
        // Execute a Force multiple coils.

        0:
        MMdb.Enable:=TRUE; //Modbus enable
        MMdb.FCode:=16#0F; //Modbus function code
        MMdb.Address:=40000; //Modbus register address
        MMdb.Points:=SIZEOF(WCoils); //Modbus register points
        MMdb.Buffer:=ADR(WCoils); //Memory buffer address
        IF NOT(MMdb.Done) THEN RETURN; END_IF;
        MMdb.Enable:=FALSE; //Modbus enable
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Execute a Force single coil.

        1:
        MMdb.Enable:=TRUE; //Modbus enable
        MMdb.FCode:=16#05; //Modbus function code
        MMdb.Address:=40000+0; //Modbus register address
        MMdb.Points:=0; //Modbus register points
        MMdb.Buffer:=ADR(WCoils); //Memory buffer address
        IF NOT(MMdb.Done) THEN RETURN; END_IF;
        MMdb.Enable:=FALSE; //Modbus enable
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Execute a Read coil status.

        2:
        MMdb.Enable:=TRUE; //Modbus enable
        MMdb.FCode:=16#01; //Modbus function code
        MMdb.Address:=40000+0; //Modbus register address
        MMdb.Points:=SIZEOF(RCoils); //Modbus register points
        MMdb.Buffer:=ADR(RCoils); //Memory buffer address
        IF NOT(MMdb.Done) THEN RETURN; END_IF;
        MMdb.Enable:=FALSE; //Modbus enable
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Execute a Preset multiple registers.

        3:
        MMdb.Enable:=TRUE; //Modbus enable
        MMdb.FCode:=16#10; //Modbus function code
        MMdb.Address:=40000+(16/2); //Modbus register address
        MMdb.Points:=SIZEOF(WHRegs)/2; //Modbus register points
        MMdb.Buffer:=ADR(WHRegs); //Memory buffer address
        IF NOT(MMdb.Done) THEN RETURN; END_IF;
        MMdb.Enable:=FALSE; //Modbus enable
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Execute a Preset single register.

        4:
        MMdb.Enable:=TRUE; //Modbus enable
        MMdb.FCode:=16#06; //Modbus function code
        MMdb.Address:=40000+(16/2); //Modbus register address
        MMdb.Points:=0; //Modbus register points
        MMdb.Buffer:=ADR(WHRegs[0]); //Memory buffer address    
        IF NOT(MMdb.Done) THEN RETURN; END_IF;
        MMdb.Enable:=FALSE; //Modbus enable
        CaseNr:=CaseNr+1; //Program case

        // ---------------------------------------------------------------------
        // Execute a Read holding registers.

        5:
        MMdb.Enable:=TRUE; //Modbus enable
        MMdb.FCode:=16#03; //Modbus function code
        MMdb.Address:=40000+(16/2); //Modbus register address
        MMdb.Points:=SIZEOF(RHRegs)/2; //Modbus register points
        MMdb.Buffer:=ADR(RHRegs); //Memory buffer address
        IF NOT(MMdb.Done) THEN RETURN; END_IF;
        MMdb.Enable:=FALSE; //Modbus enable
        CaseNr:=0; //Program case
    END_CASE;

// [End of file]
Was this article helpful?