FIFOFile, gestisce registro FIFO su file

List

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

Questo blocco funzione da eseguire in task Back, effettua la gestione di un registro FIFO, il registro può essere appoggiato su un’area di memoria oppur su di un file. Il FB ha esecuzione atomica, può essere eseguito come una funzione.

In FIFOFilename occorre definire il percorso completo del file di appoggio del registro FIFO, se FIFOFilename=NULL i dati del registro FIFO sono salvati in un buffer di memoria RAM allocato automaticamente (RMalloc) anziché su disco. La dimensione del registro FIFO è definita dalla variabile FIFOSize, se si opera con un buffer in memoria si consiglia di tenere un valore inferiore agli 8KBytes. Appoggiando il registro FIFO in memoria i dati non sono mantenuti allo spegnimento del sistema.

In FIFOIDx occorre fornire l’indirizzo di un array di 2 UDINT che devono essere allocati dal programma. Se si desidera che la situazione dei dati nel FIFO sia mantenuta allo spegnimento del sistema occorre allocare questo array in una memoria tampone. Se FIFOFIDx=NULL gli indici del registro FIFO sono salvati internamente al FB. In questo caso i dati non sono mantenuti allo spegnimento del sistema.

Attivando In i dati nel buffer puntato da Dp per la dimensione indicata in Dls sono inseriti nel registro FIFO. In UTCTime è ritornato il valore di Data/Ora UTC di inserimento nel registro FIFO. Attivando Out si hanno due differenti azioni in funzione del valore in Dls.

Se Dp=eNULL e/o Dls=0: Sono valorizzati in uscita UTCTime e Dl con i dati del record che è stato inserito per primo nel registro (Se esiste). Se il registro è vuoto Dl viene ritornato con valore 0.

Se Dls<>0: Sono trasferiti nel buffer di uscita puntato da Dp la cui dimensione è definita in Dls i dati del record che è stato inserito per primo nel registro (Se esiste) e sono valorizzati in uscita UTCTime e Dl con i dati relativi. Se nessun record presente viene attivato Fault.

Attivando Delete il primo record inserito nel FIFO (Se esiste) viene rimosso dal registro. Se nessun record presente viene attivato Fault.

L’uscita DataOn se attiva indica la presenza di almeno un record nel registro FIFO. In FIFOSpace viene ritornato lo spazio disponibile, dati di dimensione inferiore o uguale possono essere inseriti nel registro. L’uscita Ok si attiva per un loop di programma ad ogni esecuzione di un comando se l’esecuzione ha esito positivo. In caso di errore esecuzione viene attivata per un loop l’uscita Fault. Function block

Utility “FIFOViewer”

Se i dati del registro sono memorizzati su di un file di appoggio è possibile scaricare dal sistema il file, aprirlo con l’utility FIFOViewer (https://utilities.elsist.biz/FIFOViewer.html) che lo decodifica e ne visualizza il contenuto ordinato per Data/Ora. L’indicazione di Data/Ora è stata automaticamente abbinata dal FB nel momento in cui il record è stato inserito nel registro.

Utilizzando il tasto di download è possibile salvare il contenuto del file decodificato così come visualizzato.

Information Circle

Blocco funzione

CODESYS: Non disponibile

LogicLab: eLLabLogLib

Descrizione

In (BOOL) Comando di inserimento record nel registro FIFO. Il record viene inserito solo se lo spazio è sufficente FIFOSpace maggiore/uguale a dimensione record.
Out (BOOL) Comando di lettura record dal registro FIFO. Se Dp=eNULL e/o Dls=0 sono valorizzati in uscita UTCTime e Dl con i dati del record nel registro (Se esiste). Se il registro è vuoto Dl viene ritornato con valore 0.
Delete (BOOL) Comando di cancellazione record dal registro FIFO.
FIFOIDx (@UDINT) Pointer alla variabile indici registro FIFO (Deve essere un array di 2 UDINT). Se definito NULL sono utilizzati indici all’interno del FB, in questo caso non sono mantenuti i dati nel registro FIFO allo spegnimento del sistema.
FIFOFilename (@STRING) Percorso e nome del file in cui memorizzare i dati del registro FIFO (es.: ‘C:/FIFO.bin‘). Se definito eNULL viene utilizzata memoria (RMalloc) per memorizzare i dati nel registro, in questo caso non sono mantenuti i dati allo spegnimento del sistema.
FIFOSize (UDINT) Lunghezza massima del registro FIFO. Se definito file di appoggio sarà la dimensione massima del file, se si utilizza memoria è la dimensione del buffer di memoria allocato, in questo caso si consiglia di non superare 8Kb.
Dp (PVOID) Pointer al buffer dati sia ingresso che in uscita dal FIFO.
Dls (UDINT) Su comando In definisce lunghezza record dati in ingresso al FIFO. Su comando Out definisce dimensione buffer dati in uscita dal FIFO (Vedi descrizione in comando Out).
Ok (BOOL) Attivo per un loop se comando riuscito.
Fault (BOOL) Attivo per un loop su errore esecuzione comando.
DataOn (BOOL) Attivo se almeno un record dati è presente nel registro FIFO.
FIFOSpace (UDINT) Spazio disponibile nel registro FIFO.
UTCTime (UDINT) Data/Ora in UTC di inserimento record nel FIFO.
Dl (UDINT) Lunghezza record letto da FIFO.
Errors (UDINT) Numero errori di gestione.

Immagine FB FIFOFile_v1

Esempi

Come utilizzare gli esempi, per eseguire l’esempio importare l’oggetto o la libreria nel progetto (Articolo).

ST_FIFOFile_v1: Viene dimostrato l’utilizzo del registro FIFO, forzando da debug la variabile In viene inserito nel registro FIFO un record del tipo “Counter=1234“. Forzando da debug la variabile Out viene estratto dal registro FIFO il primo record inserito che viene poi eliminato. Se si desidera mantenere i dati nel registro FIFO anche allo spegnimento del sistema la variabile FIFOIDx và dichiarata RETAIN.

ST_FIFO_DataLog: Si utilizza un registro FIFO in memoria per salvare records di log. Quando i records occupano più della metà del registro o comunque ogni tempo definito, vengono letti dal FIFO e accodati in un file su disco. Il vantaggio di utilizzare un FIFO di appoggio permette di storicizzare velocemente i dati in memoria e non stressare i disco con continue scritture di records.

LogicLab (Ptp136, ST_FIFOFile)
PROGRAM ST_FIFOFile
VAR
    Out : BOOL; (* Extract record from FIFO *)
    In : BOOL; (* Insert record on FIFO *)
    i : UDINT; (* Auxiliary variable *)
    FIFOIn : STRING[ 32 ]; (* FIFO data Input *)
    Counter : UDINT; (* Counter *)
    FIFOIDx : ARRAY[0..1] OF UDINT; (* FIFO indexes *)
    FIFOOut : STRING[ 32 ]; (* FIFO data Output *)
    FIFO : FIFOFile_v1; (* FIFO file FB instance *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_FIFOFile"
// *****************************************************************************
// By setting In command a record is inserted on the FIFO register. By setting
// Out command if present a record is extracted from the FIFO register.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // Execute program initialization.

    IF (SysFirstLoop) THEN
         FIFO.FIFOFilename:=ADR('C:/FIFO.bin'); //Filename
    //    FIFO.FIFOFilename:=ADR('D:/FIFO.bin'); //Filename
   //     FIFO.FIFOFilename:=eNULL; //Filename
        FIFO.FIFOIDx:=ADR(FIFOIDx); //FIFO indexes
        FIFO.FIFOSize:=10000; //FIFO register size

        // Wear leveling, if the two indexes have the same value delete
        // the FIFO file. I'll be created in a new disk position.

        IF (SysGetFileLen(FIFO.FIFOFilename) <> -1) THEN
            IF (FIFOIDx[0] = FIFOIDx[1]) THEN i:=SysFileRemove(FIFO.FIFOFilename); FIFOIDx[0]:=0; FIFOIDx[1]:=0; END_IF;
        END_IF;
    END_IF;

    // Execute FIFO register, to manage the output variables.

    FIFO(); //FIFO file FB instance

    // -------------------------------------------------------------------------
    // INSERT DATA ON FIFO REGISTER
    // -------------------------------------------------------------------------
    // If In command is set counter is increased and its value stored on FIFO.

    IF (In) THEN
        In:=FALSE; //Insert record on FIFO

        // Increase the counter and add value to FIFO.

        Counter:=Counter+1; //Counter
        i:=SysVsnprintf(ADR(FIFOIn), SIZEOF(FIFOIn), ADR('Counter=%d'), UDINT_TYPE, ADR(Counter));
        FIFO(In:=TRUE, Dp:=ADR(FIFOIn), Dls:=LEN(FIFOIn)); //Write record on FIFO
    END_IF;

    // -------------------------------------------------------------------------
    // EXTRACT DATA FROM FIFO REGISTER
    // -------------------------------------------------------------------------
    // If Out command is set a record is extracted from FIFO register.

    IF (Out AND FIFO.DataOn) THEN
        Out:=FALSE; //Extract record from FIFO

        FIFO(Out:=TRUE, Dp:=ADR(FIFOOut), Dls:=SIZEOF(FIFOOut)); //Read record from FIFO
        FIFO(Delete:=TRUE); //Delete record from FIFO
    END_IF;

// [End of file]
LogicLab (Ptp136, ST_FIFO_DataLog)
PROGRAM ST_FIFO_DataLog
VAR
    Store : BOOL; (* Store command *)
    i : UDINT; (* Auxiliary variable *)
    Fp : eFILEP; (* File pointer *)
    TimeBf : UDINT; (* Time buffer (uS) *)
    AStr : STRING[ 64 ]; (* Auxiliary string *)
    FIFO : FIFOFile_v1; (* FIFO file FB instance *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_FIFO_DataLog"
// *****************************************************************************
// By setting In command a record is inserted on the FIFO register. By setting
// Out command if present a record is extracted from the FIFO register.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // INITIALIZATION
    // -------------------------------------------------------------------------
    // Execute program initialization.

    IF (SysFirstLoop) THEN
        FIFO.FIFOFilename:=NULL; //Filename
        FIFO.FIFOIDx:=NULL; //FIFO indexes
        FIFO.FIFOSize:=4096; //FIFO register size
    END_IF;

    // Execute FIFO register, to manage the output variables.

    FIFO(); //FIFO file FB instance

    // -------------------------------------------------------------------------
    // STORE LOG RECORD ON FIFO
    // -------------------------------------------------------------------------
    // On Store command, prepares the log record and store it on FIFO. The 
    // record is: "14/02/2020 10:30:02 Back execution time:138 (uS)". 

    IF (Store) THEN
        Store:=FALSE; //Store command
        i:=DateTimeFormat(TO_LDATE_AND_TIME(SysDateGetNs()), ADR('^d/m/Y H\:i\:s'), ADR(AStr), SIZEOF(AStr));
        i:=SysCVsnprintf(ADR(AStr), SIZEOF(AStr), ADR('Back execution time:%d (uS)'), UDINT_TYPE, ADR(SysTBackExTm));
        FIFO(In:=TRUE, Dp:=ADR(AStr), Dls:=Sysstrlen(FIFO.Dp)); //Write record on FIFO
    END_IF;

    // -------------------------------------------------------------------------
    // WRITE LOG RECORD ON FILE
    // -------------------------------------------------------------------------
    // When FIFO as an considerable amount of data on it, the data are written
    // on disk. So the disk access is optimized. If the data stored on FIFO
    // don't reach the write threshold, they are written after a time.

    IF NOT(FIFO.DataOn) THEN TimeBf:=SysTimeGetMs(); RETURN; END_IF;
    IF ((SysTimeGetMs()-TimeBf) < TO_UDINT(T#2s)) AND (FIFO.FIFOSpace > (FIFO.FIFOSize/2)) THEN RETURN; END_IF;

    // Open the file on append, if not present it will be created.

    Fp:=SysFfopen(ADR('D:/Log.txt'), ADR('a')); //File pointer
    IF (Fp = NULL) THEN RETURN; END_IF;

    // Extract data from FIFO.

    WHILE (FIFO.DataOn) DO
        FIFO(Out:=TRUE, Dp:=ADR(AStr), Dls:=SIZEOF(AStr));

        // Write data on file.

        i:=Sysfwrite(ADR(AStr), TO_INT(Sysstrlen(ADR(AStr))), 1, Fp);
        i:=Sysfwrite(ADR('$r$n'), 2, 1, Fp);
        FIFO(Delete:=TRUE); //Delete record from FIFO
    END_WHILE;

    // Close the file.

    i:=Sysfclose(Fp); //Eseguo chiusura file

// [End of file]

Was this article helpful?