Quando una macchina si ferma, raramente il problema è soltanto “scrivere il codice”. Servono una logica chiara, ingressi e uscite ben definiti e un programma che un tecnico possa leggere anche mesi dopo. Qui raccolgo esempi pratici di programmazione PLC in Ladder e Structured Text, con applicazioni a motori, nastri trasportatori, serbatoi e sequenze automatiche.
Gli esempi più utili per imparare la logica PLC
- Marcia e arresto con autoritenuta e condizioni di sicurezza.
- Temporizzatori per ritardi, impulsi e gestione dei cicli.
- Controllo di livello con isteresi e protezione della pompa.
- Sequenze automatiche organizzate con stati e transizioni.
- Ladder, ST, FBD e SFC scelti in base al tipo di problema.
Come impostare un esempio PLC prima di scrivere il codice
Io parto sempre dalla mappa degli I/O, non dal linguaggio di programmazione. Prima elenco pulsanti, sensori, finecorsa e segnali di allarme, poi associo a ciascuno un’uscita o una variabile interna. Questo passaggio evita uno degli errori più comuni: costruire una logica elegante che però non corrisponde al cablaggio reale.
| Elemento | Tipo | Esempio di variabile | Funzione |
|---|---|---|---|
| Pulsante di avvio | Ingresso digitale | Start |
Avvia il ciclo |
| Pulsante di arresto | Ingresso digitale | Stop_OK |
Indica che il circuito di arresto è integro |
| Finecorsa | Ingresso digitale | Finecorsa_Superiore |
Blocca il movimento in posizione limite |
| Motore | Uscita digitale | Motore_Avanti |
Comanda il contattore o l’azionamento |
| Pressostato o livello | Ingresso digitale o analogico | Livello_Basso |
Richiede il reintegro |
La variabile Stop_OK è spesso più leggibile di un semplice “Stop”. Se il pulsante è normalmente chiuso, il PLC può ricevere un segnale vero durante il funzionamento normale e falso quando il circuito viene interrotto. Nella pratica distinguo sempre tra il nome fisico del dispositivo e la condizione logica che il programma deve verificare.
Per esercitarsi vanno bene un simulatore, un piccolo PLC didattico o un ambiente IEC 61131-3 come CODESYS. In macchina, però, il programma deve essere verificato anche rispetto a cablaggio, arresto di emergenza, interblocchi e comportamento dopo un riavvio. Un esempio didattico non può sostituire la progettazione della sicurezza.
Marcia e arresto di un motore con autoritenuta
La marcia e l’arresto sono il primo esercizio perché mostrano tre concetti fondamentali: comando, mantenimento dello stato e arresto prioritario. Premendo Start il motore parte e resta attivo anche dopo il rilascio del pulsante; Stop o il finecorsa interrompono il comando.
In Ladder la logica tipica usa un contatto di Start in parallelo al contatto associato al motore. Questa configurazione si chiama autoritenuta. Il contatto di arresto e le condizioni di sicurezza devono invece interrompere la continuità della rete.
|----[ Stop_OK ]----[/ Finecorsa_Superiore ]----+----[ Start ]----( Motore_Avanti )
| |
| +----[ Motore_Avanti ]
La rappresentazione è volutamente generica, perché la sintassi cambia tra Siemens, Schneider, Omron, Rockwell e altri costruttori. Il principio resta lo stesso, ma il significato elettrico di un contatto normalmente aperto o normalmente chiuso deve essere verificato sul progetto reale.
Una versione equivalente in Structured Text può essere scritta così:
IF NOT Stop_OK OR Finecorsa_Superiore THEN
Motore_Avanti := FALSE;
ELSIF Start THEN
Motore_Avanti := TRUE;
END_IF;
Qui l’arresto ha priorità sull’avvio. È una scelta importante: se Start e Stop arrivano nello stesso ciclo PLC, il motore non deve continuare a funzionare per effetto dell’ordine casuale delle istruzioni. In un impianto vero aggiungo anche il consenso del relè termico, la modalità Manuale/Automatico e il feedback del contattore.
Un nastro trasportatore con temporizzatore

Un secondo esempio utile è un nastro che parte con un comando, trasporta il pezzo per alcuni secondi e poi attiva un espulsore pneumatico. È un caso semplice, ma introduce il TON, cioè un temporizzatore con ritardo all’eccitazione.
La sequenza può essere descritta in modo concreto:
- l’operatore abilita il ciclo;
- il nastro avanza finché il sensore rileva il pezzo;
- il timer conta 3 secondi;
- l’espulsore resta attivo per 500 millisecondi;
- il ciclo torna allo stato iniziale.
Un esempio in Structured Text, semplificato per la simulazione, potrebbe essere:
Timer_Posizione(
IN := Ciclo_Attivo AND Sensore_Pezzo,
PT := T#3s
);
Timer_Espulsione(
IN := Timer_Posizione.Q,
PT := T#500ms
);
Nastro_Avanti := Ciclo_Attivo AND NOT Timer_Posizione.Q;
Espulsore := Timer_Espulsione.IN AND NOT Timer_Espulsione.Q;
La logica mostra il funzionamento, ma non è ancora pronta per una macchina. In produzione controllerei anche che il sensore non resti bloccato, che il pezzo non venga rilevato due volte e che l’espulsore abbia raggiunto la posizione prevista. Un timer non conferma che un movimento sia realmente avvenuto: misura soltanto il tempo trascorso.
Per questo motivo, quando il movimento è importante, preferisco usare un finecorsa o un sensore di posizione insieme al temporizzatore. Il timer diventa così un controllo di timeout: se entro 3 secondi non arriva il consenso, il PLC genera un allarme invece di proseguire alla cieca.
Controllo del livello di un serbatoio
Il riempimento automatico di un serbatoio è uno degli esempi più istruttivi perché obbliga a gestire stati opposti. La pompa deve partire con il livello basso e fermarsi con il livello alto, senza oscillare continuamente quando il liquido si trova vicino alla soglia.
Con due sensori digitali, la logica può essere scritta in questo modo:
IF Emergenza OR NOT Termica_Pompa THEN
Pompa := FALSE;
ELSIF Livello_Alto THEN
Pompa := FALSE;
ELSIF Livello_Basso THEN
Pompa := TRUE;
END_IF;
La pompa resta quindi nello stato precedente quando nessuno dei due sensori cambia condizione. Questa è una forma di memoria logica, simile a un set/reset, e impedisce che il comando venga riscritto inutilmente a ogni scansione.
La distanza tra il sensore di livello basso e quello alto crea un’isteresi naturale. Se invece si usa un trasmettitore analogico, per esempio 0-10 V o 4-20 mA, si possono impostare soglie numeriche:
IF Livello_Percentuale >= 90.0 THEN
Pompa := FALSE;
ELSIF Livello_Percentuale <= 30.0 THEN
Pompa := TRUE;
END_IF;
Nel caso analogico bisogna aggiungere il controllo del segnale fuori scala. Un valore inferiore al minimo o superiore al massimo può indicare un cavo interrotto, un sensore guasto o un errore di configurazione. Senza questa verifica il PLC potrebbe interpretare un guasto come un livello reale e avviare la pompa nel momento sbagliato.
Questo schema è adatto a un semplice reintegro, ma non basta per fluidi pericolosi o processi critici. In quei casi servono ridondanza, protezioni indipendenti e una valutazione specifica dei rischi, oltre alla logica ordinaria del PLC.
Sequenze automatiche con stati e transizioni
Quando una macchina deve eseguire più passaggi, la logica fatta soltanto di contatti tende a diventare difficile da seguire. Io preferisco descrivere il ciclo come una serie di stati espliciti, ognuno con una condizione di uscita. È l’approccio tipico dei sequencer e dei diagrammi SFC.
Un ciclo di lavorazione potrebbe avere questi stati:
| Stato | Azione | Transizione |
|---|---|---|
| 0 - Attesa | Tutti gli attuatori spenti | Start e condizioni sicure |
| 10 - Chiusura | Attiva il cilindro di serraggio | Finecorsa chiuso |
| 20 - Lavorazione | Avvia mandrino o utensile | Timer completato |
| 30 - Apertura | Rilascia il pezzo | Finecorsa aperto |
| 100 - Allarme | Ferma il ciclo e segnala il guasto | Reset autorizzato |
In Structured Text, una struttura minima può essere:
CASE Stato OF
0:
Cilindro_Chiudi := FALSE;
Mandrino := FALSE;
IF Start AND Sicurezze_OK THEN
Stato := 10;
END_IF;
10:
Cilindro_Chiudi := TRUE;
IF Finecorsa_Chiuso THEN
Stato := 20;
ELSIF Timer_Sicurezza.Q THEN
Stato := 100;
END_IF;
20:
Mandrino := TRUE;
IF Timer_Lavorazione.Q THEN
Stato := 30;
END_IF;
30:
Cilindro_Chiudi := FALSE;
IF Finecorsa_Aperto THEN
Stato := 0;
END_IF;
100:
Cilindro_Chiudi := FALSE;
Mandrino := FALSE;
IF Reset AND Sicurezze_OK THEN
Stato := 0;
END_IF;
END_CASE;
Il vantaggio è immediato durante il debug: dal valore di Stato si capisce in quale fase si trova la macchina. Il limite è che bisogna impedire transizioni contraddittorie e definire bene cosa succede dopo un arresto, una perdita di alimentazione o il ripristino di un allarme.
Quale linguaggio scegliere per gli esempi PLC
Non esiste un linguaggio migliore in assoluto. La scelta dipende dalla complessità del processo, dalle competenze della manutenzione e dagli strumenti supportati dal costruttore. In una linea con molti segnali digitali, il Ladder rimane spesso più immediato per chi deve diagnosticare il quadro elettrico.
| Linguaggio | Quando lo uso | Punto di forza | Limite principale |
|---|---|---|---|
| Ladder o LD | Marcia/arresto, interblocchi, logica digitale | Molto leggibile durante la manutenzione | Può diventare dispersivo nelle sequenze complesse |
| Structured Text o ST | Calcoli, array, ricette e algoritmi | Compatto e adatto alla programmazione strutturata | Richiede maggiore familiarità con il codice |
| FBD | Regolazioni, segnali analogici e blocchi funzionali | Rende visibili i collegamenti tra funzioni | Gli schemi molto grandi diventano difficili da seguire |
| SFC | Sequenze con fasi e transizioni | Descrive bene il ciclo automatico | Non tutti i team lo usano allo stesso modo |
La soluzione più efficace è spesso ibrida. Uso Ladder per gli interblocchi e i consensi, blocchi funzione per motori e valvole, Structured Text per calcoli o gestione dati e SFC per una sequenza articolata. La coerenza del progetto conta più della preferenza personale: nomi, commenti, struttura dei blocchi e regole di diagnostica devono restare uniformi.
Per esempio, in un progetto Siemens si può incontrare LAD per la logica tradizionale e SCL per il testo strutturato; in altri ambienti i nomi o le librerie cambiano. Prima di copiare un esempio bisogna quindi verificare la sintassi del proprio IDE, il tipo di CPU e il comportamento dei temporizzatori.
Gli errori che trasformano un buon esempio in un problema reale
Il primo errore è usare indirizzi come I0.0 e Q0.0 ovunque senza commenti. Per una prova rapida può funzionare, ma in manutenzione è molto più utile lavorare con nomi come Start_Nastro e Valvola_Serraggio, collegati agli indirizzi in una tabella I/O documentata.
- Confondere il segnale fisico con la condizione logica, soprattutto sui contatti normalmente chiusi.
- Dimenticare il riavvio dopo una caduta di tensione o il passaggio da Manuale ad Automatico.
- Usare timer come conferma di movimento senza un sensore di posizione.
- Scrivere la stessa uscita in più reti, rendendo difficile capire quale istruzione abbia l’ultima parola.
- Mescolare sicurezza e comando ordinario senza separare arresto di emergenza e logica di processo.
Durante il collaudo provo sempre almeno quattro condizioni: avvio normale, arresto durante il ciclo, sensore che non cambia stato e ripristino dopo un guasto. Se il programma funziona solo nello scenario ideale, non è ancora pronto per la produzione. Anche la simulazione deve includere sensori bloccati, tempi scaduti e comandi simultanei.
Un altro aspetto spesso sottovalutato è la leggibilità. Un programma leggermente più lungo, ma diviso in funzioni chiare e con allarmi nominati correttamente, riduce molto i tempi di fermo rispetto a una soluzione compatta piena di eccezioni nascoste.
Dal codice di prova a una macchina affidabile
Gli esempi di programmazione PLC servono soprattutto a imparare un metodo: definire gli I/O, descrivere il comportamento atteso, scegliere il linguaggio più adatto e verificare ogni condizione anomala. La marcia e l’arresto insegnano la memoria, il nastro introduce i tempi, il serbatoio mostra l’isteresi e la sequenza chiarisce il valore degli stati.
Io considero pronto un esercizio solo quando riesco a spiegare cosa accade in ogni scansione del PLC e cosa succede se un sensore resta attivo, se un motore non parte o se l’operatore preme Reset nel momento sbagliato. È questo passaggio, più del semplice codice copiato, che trasforma un esempio didattico in una base utile per l’automazione industriale.