In tutti i PLC una parte di memoria RAM è utilizzata come memoria intermedia per l’accesso alla periferia (I/O). Questa memoria identificata come immagine di processo è divisa in immagine ingressi ed immagine uscite. Durante l’elaborazione del programma, ogni accesso agli I/O non viene riferito al canale fisico ma ad un bit nella immagine di processo. La lettura di un ingresso corrisponde ad un bit di memoria copiato dall’ingresso ad inizio esecuzione loop di programma. La scrittura di una uscita scrive un bit di memoria che verrà trasferito sul canale fisico di uscita a fine esecuzione loop di programma.
L’esecuzione del programma PLC segue Il diagramma a torta della figura. Il microprocessore dovrà dividere il suo tempo tra diversi compiti, eseguire il Sistema operativo, aggiornare l’immagine degli ingressi, eseguire il programma applicativo e trasferire l’immagine delle uscite. Nei nostri sistemi l’immagine di processo è eseguita in task Slow che è il task real time.
Definizione I/O logici
Definizione ingressi
Ecco come vengono definiti gli ingressi logici in LogicLab. Consiglio di definirli sempre nelle variabili GLOBALI.
VAR_GLOBAL Di00M00 AT %IX0.0 : BOOL; (* Di 00 Module 0 *) Start AT %IX0.1 : BOOL; (* Di 01 Module 0 *) Stop AT %IX0.2 : BOOL; (* Di 02 Module 0 *) Di04M02 AT %IX2.4 : BOOL; (* Di 04 Module 2 *) Di00CPU AT %IX255.0 : BOOL; (* Di 00 CPU module *) END_VAR
- Di00M00 è lo mnemonico dato all’ingresso a cui si farà riferimento nel programma, in realtà si utilizzerà uno mnemonico che ne ricorda la funzione (Es. Start, Stop, ecc.).
- %IX(m).(i) è la definizione standard IEC di un ingresso logico, dove (m) indica l’indirizzo del modulo (Da 0 a 15 per i moduli di I/O e 255 per il modulo CPU) e (i) è l’ingresso fisico sul modulo (Da 0 a 31).
Definizione uscite
Ecco come vengono definite le uscite logiche in LogicLab. Consiglio di definirle sempre nelle variabili GLOBALI.
VAR_GLOBAL Do00M00 AT %QX0.0 : BOOL; (* Do 00 Module 0 *) Motor AT %QX0.1 : BOOL; (* Do 01 Module 0 *) Do04M02 AT %QX2.4 : BOOL; (* Do 04 Module 2 *) Do00CPU AT %QX255.0 : BOOL; (* Do 00 CPU module *) END_VAR
- Do00M00 è lo mnemonico dato all’uscita a cui si farà riferimento nel programma, in realtà si utilizzerà uno mnemonico che ne ricorda la funzione (Es. Motor, Lamp, ecc.).
- %QX(m).(i) è la definizione standard IEC di una uscita logica, dove (m) indica l’indirizzo del modulo (Da 0 a 15 per i moduli di I/O e 255 per il modulo CPU) e (i) è l’ingresso fisico sul modulo (Da 0 a 31).

FAQs
Perchè si utilizza l’immagine di processo?
Gestendo gli ingressi tramite l’immagine di processo si garantisce che per tutto il ciclo di esecuzione del programma utente lo stato sia stabile anche se in realtà cambiano di stato in base alla situazione dell’impianto. Così il controllo del suo stato dà lo stesso risultato in ogni punto del programma.
Gestendo le uscite tramite l’immagine di processo si garantisce che se all’interno del programma l’uscita cambia di stato più volte, la reale attivazione sull’impianto avvenga solo a fine programma evitando comandi non corretti. Ecco un marcia arresto realizzato in linguaggio ST che illustra il concetto. E’ evidende che se attivi entrambi i comandi di Start e Stop senza immagine di processo Motor verrebbe attivato e poi disattivato.
IF (Start) THEN Motor:=TRUE; END_IF; IF (Stop) THEN Motor:=FALSE; END_IF;
Posso gestire gli I/O logici senza utilizzare l’immagine di processo?
A volte può essere necessario gestire gli I/O logici direttamente da programma, per l’acquisizione degli ingressi è possibile utilizzare il FB SysGetPhrDI. Per la gestione delle uscite è possibile utilizzare il FB SysSetPhrDO.
Posso accedere all’immagine di processo tramite puntatori?
In programmi strutturati può essere comodo accedere all’immagine di processo tramite puntatori di seguito un esempio, l’esempio funziona correttamente se eseguito nella stessa task dove è eseguita l’immagine di processo per garantire la gestione degli I/O in immagine di processo in tutte le task, LogicLab crea una immagine di processo degli I/O in ogni task. Quindi l’istruzione MyBOOLADR:=ADR(%IX0.0) tornerà indirizzi diversi in base alla task dove è eseguita, per utilizzarne il puntatore occorre prestare attenzione.
VAR
MyBOOL : BOOL; (* BOOL value *)
MyBOOLADR : @BOOL; (* BOOL pointer *)
END_VAR
MyBOOLADR:=ADR(%IX0.0); //Punto l'ingresso nell'immagine di processo
MyBOOL:=@MyBOOLADR; //Copio in MyBOOL lo stato dell'ingresso
Posso scrivere funzione per acquisire immagine di processo di una scheda ingressi?
Siccome è possibile accedere all’immagine di processo degli ingressi tramite puntatori, può essere comodo scrivere una funzione per acquisire l’intera immagine di processo di una scheda di ingressi. Un modulo di ingressi può avere al massimo 32 punti quindi la funzione ritorna una DWORD con lo stato di tutti gli ingressi. La funzione funziona correttamente se eseguita nella stessa task dove è eseguita l’immagine di processo.
FUNCTION IRead: DWORD
VAR
i : UDINT; (* Auxiliary variable *)
END_VAR
VAR_INPUT
IAddress : @BOOL; (* Input address *)
END_VAR
// *****************************************************************************
// FUNCTION "IRead"
// *****************************************************************************
// Sono gestiti 32 inputs immagine di processo a partire da quello indicato.
// Ecco un esempio di utilizzo:
//
// Module[0]:=IRead(ADR(%IX0.0)); //Lettura ingressi modulo 0
// Module[1]:=IRead(ADR(%IX1.0)); //Lettura ingressi modulo 1
// Module[2]:=IRead(ADR(%IX2.0)); //Lettura ingressi modulo 2
// -----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// GESTIONE INGRESSI IN IMMAGINE DI PROCESSO
// -------------------------------------------------------------------------
// Gestione ingressi da immagine di processo.
IRead:=16#00000000; //Function result
FOR i:=0 TO 31 DO
IRead:=SHR(IRead, 1); //Function result
IF (@IAddress) THEN IRead:=IRead OR 16#80000000; END_IF;
IAddress:=IAddress+1; //Input address
END_FOR;
// [End of file]
Posso scrivere funzione per settare immagine di processo di una scheda uscite?
Siccome è possibile accedere all’immagine di processo delle uscite tramite puntatori, può essere comodo scrivere una funzione settare l’intera immagine di processo di una scheda di uscite. Un modulo di uscite può avere al massimo 32 punti quindi la funzione accetta una DWORD con lo stato di tutte le uscite. La funzione funziona correttamente se eseguita nella stessa task dove è eseguita l’immagine di processo.
FUNCTION OWrite: BOOL
VAR
i : UDINT; (* Auxiliary variable *)
END_VAR
VAR_INPUT
OAddress : @BOOL; (* Output address *)
Value : DWORD; (* Set value *)
END_VAR
// *****************************************************************************
// FUNCTION "OWrite"
// *****************************************************************************
// Sono gestiti 32 output immagine di processo a partire da quello indicato.
// Ecco un esempio di utilizzo:
//
// i:=OWrite(ADR(%QX0.0), Module[0]); //Scrittura uscite modulo 0
// i:=OWrite(ADR(%QX1.0), Module[1]); //Scrittura uscite modulo 0
// i:=OWrite(ADR(%QX2.0), Module[2]); //Scrittura uscite modulo 0
// -----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// GESTIONE USCITE IN IMMAGINE DI PROCESSO
// -------------------------------------------------------------------------
// Gestione uscite in immagine di processo.
OWrite:=TRUE; //Function result
FOR i:=0 TO 31 DO
@OAddress:=TO_BOOL(Value AND 16#00000001);
OAddress:=OAddress+1; //Output address
Value:=SHR(Value, 1); //Set value
END_FOR;
// [End of file]