Programmare i PLC: IEC 61131-3, tempo di risposta e blocchi funzionali
I cinque linguaggi, tempo di risposta nel caso peggiore dimostrato con esempio, compiti e priorità, blocco funzionale in testo strutturato, buone pratiche di progetto e prova.
Il software di un impianto moderno può avere centinaia di migliaia di righe e restare in servizio per decenni, modificato da persone diverse. La norma IEC 61131-3 fissa i linguaggi dei PLC, ma scrivere un buon programma richiede anche le regole dell’ingegneria del software. In questa lezione vediamo i linguaggi della norma, il tempo di risposta del PLC nel caso peggiore con la dimostrazione e un esempio, i compiti e le priorità, i blocchi funzionali con un esempio in testo strutturato, e le buone pratiche di progetto e di prova.
I linguaggi
La IEC 61131-3 definisce cinque linguaggi, che possono convivere nello stesso progetto:
- LD (ladder diagram, a contatti): lo schema a relè, leggibile dagli elettricisti, adatto alla logica booleana semplice (lezione sui PLC di Controllo dei processi);
- FBD (function block diagram): blocchi collegati da fili, naturale per le regolazioni;
- ST (structured text): un linguaggio testuale simile al Pascal, con espressioni, cicli e strutture; il più adatto ad algoritmi, calcoli e macchine a stati;
- SFC: le sequenze (lezione sulle sequenze);
- IL (instruction list), simile all’assembly, dichiarato obsoleto nella terza edizione della norma.
La terza edizione (2013) ha aggiunto la programmazione a oggetti: metodi, interfacce, ereditarietà dei blocchi funzionali.
Il ciclo e il tempo di risposta
Un PLC esegue in ciclo: legge tutti gli ingressi in un’immagine di memoria, esegue il programma su quell’immagine, scrive tutte le uscite. Il ciclo dura
, da meno di un millisecondo a qualche decina.

Teorema. Il tempo tra il cambiamento di un ingresso e il cambiamento dell’uscita che ne dipende è al massimo circa
, più i ritardi del filtro d’ingresso e dell’uscita.
Dimostrazione. Nel caso peggiore l’ingresso cambia subito dopo la lettura degli ingressi: il programma di quel ciclo usa ancora il valore vecchio, e il nuovo viene letto all’inizio del ciclo successivo, dopo quasi
. Il programma lo elabora e l’uscita viene scritta alla fine di quel ciclo, dopo un altro
. In totale quasi
, cui si sommano il filtro dell’ingresso (contro i rimbalzi e i disturbi) e il tempo di commutazione dell’uscita. ∎
Esempio. Ciclo di 10 ms, filtro d’ingresso di 3 ms, uscita a relè di 10 ms: fino a
ms. Un impulso d’ingresso più breve di un ciclo può addirittura non essere mai visto. Per eventi veloci si usano ingressi a interruzione, contatori veloci in hardware o compiti con ciclo più breve.
Compiti e priorità
Il programma si divide in compiti (task) con periodi e priorità diversi: un compito veloce (1-2 ms) per le funzioni critiche, uno normale (10-20 ms) per la logica, uno lento (100 ms o più) per le funzioni di servizio, più compiti attivati da eventi. È la stessa pianificazione a priorità fisse dei sistemi in tempo reale (lezione sui sistemi in tempo reale di Sistemi operativi): il carico dei compiti veloci va tenuto basso, e il PLC sorveglia il tempo di ciclo con un watchdog che porta le uscite in uno stato sicuro se viene superato.
Blocchi funzionali
Un blocco funzionale (FB) è un modulo con ingressi, uscite e memoria interna; se ne creano tante istanze quante sono le macchine uguali. La norma ne fornisce alcuni standard, come i temporizzatori (TON, TOF, TP) e i rilevatori di fronte (R_TRIG). Un esempio in testo strutturato: il comando di una pompa come macchina a stati, con protezione termica e riarmo.
FUNCTION_BLOCK FB_Pompa
VAR_INPUT
Avvio, Arresto, Termico : BOOL; (* Termico = relè termico scattato *)
END_VAR
VAR_OUTPUT
Contattore, Allarme : BOOL;
END_VAR
VAR
Stato : INT := 0; (* 0 ferma, 1 in marcia, 2 guasto *)
END_VAR
CASE Stato OF
0: Contattore := FALSE;
IF Avvio AND NOT Arresto AND NOT Termico THEN Stato := 1; END_IF;
1: Contattore := TRUE;
IF Termico THEN Stato := 2;
ELSIF Arresto THEN Stato := 0; END_IF;
2: Contattore := FALSE;
Allarme := TRUE;
IF NOT Termico AND Arresto THEN (* riarmo: guasto sparito e conferma *)
Allarme := FALSE; Stato := 0;
END_IF;
END_CASE;
END_FUNCTION_BLOCK
Ogni stato dichiara esplicitamente le uscite; il guasto ha la precedenza sull’arresto; il riarmo richiede che la causa sia sparita e un’azione dell’operatore, così la pompa non riparte da sola. Dieci pompe sono dieci istanze dello stesso blocco, provato una volta.
Buone pratiche
- Struttura: blocchi piccoli con un compito chiaro; niente variabili globali usate ovunque; nomi parlanti e una convenzione condivisa.
- Separazione tra logica di processo, gestione dei modi, allarmi e interfaccia con l’operatore.
- Librerie di blocchi provati per i componenti ricorrenti (motori, valvole, regolatori), che rendono il codice uniforme e riducono gli errori.
- Controllo delle versioni del codice, con la storia delle modifiche: gli ambienti moderni esportano i progetti in formato testuale (PLCopen XML) proprio per questo.
- Prove: prove dei blocchi su simulatore, prove automatiche di regressione, e messa in servizio virtuale con un modello dell’impianto (lezione sulla messa in servizio).
- Commenti che spiegano il perché, non il come.
- Per il controllo del moto, le specifiche PLCopen standardizzano i blocchi (MC_MoveAbsolute e simili) tra costruttori diversi (lezione sugli azionamenti).





