Normative per PLC
Introduzione
Section titled “Introduzione”Una norma è un insieme di specifiche che servono a standardizzare un certo ambito.
Nell’ambito dell’automazione industriale si è sentita l’esigenza di “normare”: avere una certa standardizzazione e una certa portabilità del software. Avere la possibilità di far girare lo stesso programma su PLC di ditte diverse.
Le normative, in tutto il mondo, sono emesse da due enti normatori:
- ISO: emette norme di orientamento generale in quasi tutti i campi,
- IEC: emette norme nel settore Elettrico ed Elettronico.
In Europa questa struttura si riflette sui due comitati tecnici “equivalenti”:
- CEN: lavora al pari con l’ISO,
- CENELEC: lavora al pari con l’IEC.
In Italia la situazione è praticamente la stessa con questi due enti:
- UNI: lavora al pari con l’ISO, ed il CEN,
- CEI: lavora al pari con l’IEC ed il CENELEC per le nome elettriche
Norma IEC 61131
Section titled “Norma IEC 61131”La parte terza dello Standard, IEC 1131-3, definisce:
- elementi comuni per la configurazione delle applicazioni, la dichiarazione di variabili, la strutturazione dei programmi.
- Quattro linguaggi di programmazione, due di tipo grafico e due di tipo testuale (un quinto linguaggio, l’SFC, è definito in un’altra sezione della norma)
- Funzioni e blocchi funzionali standard, per definire un set minimo di operazioni di conteggio, temporizzazione, elaborazioni matematiche, conversioni di tipo
La norma sconsiglia di scrivere un unico programma che controlla e dirige tutti gli aspetti di una macchina automatica o di un impianto, ma consiglia invece di scomporre il codice in più parti, ciascuna delle quali si occupa di un aspetto della macchina. Le varie parti del codice si scambiano informazioni per mezzo delle variabili in modo da poter gestire al meglio il processo da controllare.
Gli elementi comuni della norma
Section titled “Gli elementi comuni della norma”- tipi di dato e dichiarazioni delle variabili
- POU, gli elementi di organizzazione dell’applicativo (Program Organization Units):
- functions,
- function blocks,
- programs
- Configurazione di sistema,
- Resource
- Tasks
Variabili
Section titled “Variabili”Tipi di dato
Section titled “Tipi di dato”Una variabile è un dato che il mio programma di controllo della macchina automatica deve memorizzare e gestire.
Si può dover gestire dati riferiti a:
- produzione (numerici),
- allarmi (valori booleani),
- presenza pezzi (valori booleani),
- conteggio dei pezzi lavorati (intero),
- timer (tempo),
- ora del giorno (orario),
- valore numerico di grandezze rilevate dai sensori analogici (numeri con la virgola),
- messaggi da visualizzare su HMI (stringe di caratteri alfanumerici).
Ogni variabile risiede in memoria e possiede:
- nome: corrisponde all’indirizzo in memoria,
- tipo: tipo di informazioni contiene e quanto spazio occupa in memoria,
- contenuto: valore attuale della variabile,
- classe di visibilità: chi può vedere la variabile (in programmazione è detta appunto visibility).
Una variabile può avere anche degli attributi.
I tipi di dato possono essere: base o derivati.
I tipi di dato base sono:
- booleani: BOOL,
- interi: INT,
- reali: REAL,
- data e ora: DATE, TIME, DATE AND TIME,
- stringhe di caratteri: STRING.
Ognuno di questi tipi di dato può a sua volta avere sotto-categorie in base a diversi criteri.
In base al numero di bit che occupano, gli interi si suddividono in:
- intero a 8 bit: BYTE,
- intero a 8 bit: SHORT INT,
- intero a 16 bit: INT,
- intero a 32 bit: DOUBLE INTEGER (DINT).
A partire dal numero di bit scelto, lo stesso range di valori utilizzabile potrebbe partire da 0 o essere centrato nello zero.
Nel primo caso si ammettono solo valori positivi, dunque UNSIGNED. Nel secondo caso si ammettono valori sia positivi che negativi, dunque SIGNED. Se non specificato, si sottintende che una variabile sia SIGNED.
Ad esempio: data una variabile INT a 16 bit: . Un INT di tipo SIGNED và da:
Un INT di tipo UNSIGNED và da:
Il “-1” serve per poter mettere anche lo zero tra i valori disponibili.
Si distinguono quindi ulteriori casi per gli interi:
- intero a 8 bit: BYTE,
- intero a 8 bit: SHORT INT (SINT),
- intero a 8 bit: USIGNED SHORT INT (USINT),
- intero a 16 bit: INT (INTEGER),
- intero a 16 bit: UINT (UNSIGNED INTEGER),
- intero a 32 bit: DINT (DOUBLE INTEGER),
- intero a 32 bit: USIGNED DOUBLE INTEGER (UDINT).
Dichiarazione delle variabili
Section titled “Dichiarazione delle variabili”La sintassi per dichiarare una variabile è del tipo:
nome_variabile: TIPO_DI_DATO;Ad esempio:
fotocellula: BOOL;Se in fase di dichiarazione si vuole attribuire un valore iniziale, dopo
il tipo di dato, si può aggiungere := ed il valore iniziale:
fotocellula: BOOL := true;La norma sancisce che ogni variabile deve avere un valore iniziale. Se questo non viene definito nel programma, gli viene assegnato il valore di default nullo (e D#0001-01-01 per le date).
Assegnazione di un valore ad una variabile di tipo TIME
Section titled “Assegnazione di un valore ad una variabile di tipo TIME”L’assegnazione di un valore ad una variabile di tipo TIME prevede una sintassi in cui si usa il carattere T e il carattere speciale #.
Esempio: una variabile di nome mio_tempo di tipo TIME che, come valore iniziale, ha 5 secondi.
VAR mio_tempo: TIME := T#5S;END_VAREsempio: una variabile di nome mio_tempo1 di tipo TIME che, come valore iniziale, ha 300 millisecondi.
VAR mio_tempo1: TIME := T#300ms;END_VARTipi di dato derivati/definiti dall’utente
Section titled “Tipi di dato derivati/definiti dall’utente”La tipizzazione dei dati permette di eliminare incongruenze ed errori già in fase di compilazione e semplifica il compito del programmatore.
L’utilizzo di tipi di dato derivato contribuisce alla leggibilità del software (miglioramento della qualità del software).
I tipi di dato derivato possono essere definiti con la sintassi:
TYPE Nome_Tipo: DescrizioneEND_TYPEIl nuovo tipo può essere:
- ALIAS: un tipo standard che viene ridefinito per comodità,
- subrange di un tipo standard, la descrizione del tipo è: TipoStandard (ValoreIniz..ValoreFin).
- enumerativo: elenco di valori costanti che la variabile può assumere,
- vettore di dimensione finita:
ARRAY [Intervallo di Interi] OF Tipo - struttura: insieme di variabili di tipo non omogeneo, si scrive STRUCT Var1:Tipo1 … VarN:TipoN END_STRUCT
Si vuole definire tre variabili che contengono valori di pressione. Un modo per farlo sarebbe:
VAR pump1, pump2, pump3: REAL;END_VARPer rendere il software più chiaro, si potrebbe definire un nuovo tipo di dato chiamato PRESSURE che sia un alias di REAL. Il codice diventerebbe:
TYPE PRESSURE: REAL;END_TYPE
VAR pump1, pump2, pump3: PRESSURE;END_VAREnumerativo
Section titled “Enumerativo”Si definisce il tipo MACHINE_STATUS per mezzo del costrutto TYPE. MACHINE_STATUS è un set di valori che sono scritti come alfanumerici ma non sono stringhe (non sono racchiusi dagli apici). Si definisce una variabile chiamata STATUS di tipo MACHINE_STATUS che ha un valore compreso (e che può variare) tra quelli definiti nella definizione del tipo MACHINE_STATUS.
TYPE MACHINE_STATUS: (STOP, RUN, FAULT, STANDBY);END_TYPE
VAR STATUS: MACHINE_STATUS;END_VAR
(* a quanto pare questo è un commento *)(* nel algoritmo si può scrivere*)IF STATUS = STOP THEN ... ... ...END_IFIl codice poi controlla che STATUS sia uguale al valore equivalente a STOP e, in tal caso, effettua delle operazioni.
Subrange
Section titled “Subrange”Si può, ad esempio, ridurre il range degli interi. Come detto prima, una variabile intera può assumere valori da -32768 a +32767. Se si vuole ridurre il range di una variabile intera in modo che assuma solo valori tra +6 e +12 si può scrivere:
TYPE MOTOR_VOLTS: INT(-6..+12)END_TYPEIl numero massimo della dimensione dei vettori dipende dalla implementazione e non è definito dalla norma. Nell’esempio che segue, si definisce POINTS come un array di numeri reali.
TYPE POINTS: ARRAY [1..100] OF REAL;END_TYPESi può inoltre definire una matrice, ovvero un array bi-dimensionale che possiede righe e colonne:
TYPE MATRIX_POINTS: ARRAY [1..10, 1..100] OF REAL;END_TYPEOvviamente si possono utilizzare variabili al posto dei valori numeri (se definite di tipo INT) e degli alias al posto del tipo di dato di cui è riempita la matrice o l’array.
Structure
Section titled “Structure”La caratteristica dello struct è che i suoi campi sono generalmente di tipo diverso. Lo struct PRESSURE_SENSOR contiene: un numero reale, un byte, una data e infine un array di interi:
TYPE PRESSURE_SENSOR: STRUCT VALUE : REAL; STATUS : BYTE; CALIBRATION : DATE; CALIBRATION_PARAMETERS : ARRAY[0..10] OF INT; END_STRUCT;END_TYPEClassi di visibilità delle variabili
Section titled “Classi di visibilità delle variabili”Come detto sopra, un unico programma che gestisce tutta la macchina non è tendenzialmente una buona idea. Diversi programmi devono quindi condividere le stesse variabili per gestire varie parti della macchina. Entra in gioco la classe di visibilità delle variabili per definire quali parti di software possono accede a quali variabili e con quali privilegi (lettura o scrittura).
Le variabili di access path sono visibili da configurations remote (quindi da altre CPU) come ad esempio i bus di campo.
Si può definire una variabile di tipo access path come segue:
VAR_ACCESS MY_VAR: INT;END_VARLe variabili globali sono visibili da tutte le parti del codice, da tutti i programmi, le funzioni e i function block:
VAR_GLOBAL MY_VAR: INT;END_VARLe variabili locali sono visibili solo dal modulo di codice che le dichiara:
VAR MY_VAR: INT;END_VARLe variabili di input sono visibili ma non modificabili dal codice chiamante:
VAR_INPUT MY_VAR: INT;END_VARLe variabili di input/output sono visibili e modificabili dal codice chiamante:
VAR_IN_OUT MY_VAR: INT;END_VARLe variabili di output sono… la descrizione non è chiara:
VAR_OUTPUT MY_VAR: INT;END_VARAttributi
Section titled “Attributi”Gli attributi per le variabili sono opzioni da aggiungere dopo la keyword che identifica il tipo di variabile. Questi attributi possono essere:
- RETAIN: indica che il valore delle variabili dichiarate in tale sezione deve essere ricordato anche in caso di caduta di alimentazione del PLC (memoria “tamponata” da batteria),
- CONSTANT: il loro valore non può essere modificato nel programma. Nella dichiarazione occorre quindi anche inizializzarle al valore desiderato,
- AT: seguito da un indirizzo fisico della memoria di sistema, indica che il nome della variabile rappresenta un alias per l’indirizzamento diretto.
Le variabili non indirizzate direttamente, se non hanno l’attributo AT, vengono allocate nella memoria di lavoro del PLC.
Esempi:
VAR_GLOBAL CONSTANT presenza: BOOL := TRUE;END_VAR
VAR_GLOBAL CONSTANT max_pezzi_lavorati: INT := 1000;END_VAR
VAR_GLOBAL RETAIN num_pezzi_lavorati: INT;END_VAR
VAR_GLOBAL proximity_switch: BOOL AT %I0.3;END_VARMemoria dati temporanea e indirizzamento diretto dell’hardware
Section titled “Memoria dati temporanea e indirizzamento diretto dell’hardware”Variabili che riferiscono la memoria dati temporanea e variabili ad indirizzamento diretto dell’hardware.
Se si dichiara come variabile un nome che si riferisce a:
- morsetto fisico di ingresso,
- morsetto fisico di uscita,
- locazione fisica della memoria.
La norma prevede di dover specificare l’indirizzo con:
- simbolo
%seguito da lettera identificativa:- I: ingresso (physical input),
- O o Q: uscita (physical output),
- M: memoria merker (registro di memoria).
- due numeri che codificano la posizione del morsetto o del registro in memoria:
- il primo numero è il byte address,
- il secondo numero è il bit address relativo al byte.
Il prefisso %M si riferisce alla memoria merker (memoria M), un’area di memoria che viene persa al riavvio del PLC, a meno che non sia esplicitamente configurata per essere conservata. Questo approccio è comunemente usato nella programmazione dei PLC quando si lavora con bit di memoria globali, flag o mappatura diretta degli I/O. L’area %M viene spesso utilizzata per:
- variabili temporanee: risultato intermedio, non deve “sprecare” un uscita fisica del PLC,
- segnali di interblocco (interlocking signals).
I merker possono essere sia digitali che analogici. Non tutti gli ambienti di sviluppo di produttori di PLC fanno uso di merker: alcuni utilizzano semplici variabili locali.
VAR myVar: BOOL AT %M0.0;END_VARConfiguration
Section titled “Configuration”Elenco di tutti i moduli hardware collegati al PLC ed i loro parametri (indirizzi, velocità, tempo di watchdog, …). In un sistema di controllo è possibile avere anche diverse configuration comunicanti tra loro, ognuna delle quali gestisce uno o più PLC.
Ogni configuration contiene una o più resource (sinonimo di modulo CPU).
Ogni resource contiene uno o più program, eseguiti sotto il controllo di zero o più task.
Un program può contenere zero o più function block (FB) e la chiamata a zero o più function.
Configurazione dell’applicazione: insieme di tutte le risorse hardware che si usano nell’applicazione.
Caratteristiche di una resource:
- accede alle global ed alle directly represented variables (le variabili con attributo AT),
- è l’interfaccia tra I/O fisici ed il programma.
Situazione comune: un PLC con una CPU (in nero nel disegno).
Situazione: più PLC distinti collegati tramite una rete di bus di campo. Ogni PLC ha una CPU.
Il codice dell’applicativo si suddivide in moduli di codice:
- Program,
- Function Block,
- Function.
Questi moduli di codice sono chiamati POU.
Il program è la POU più “potente” e complessa. La function è la POU più semplice che offre meno possibilità (non può gestire tutti i tipi di variabile e non può essere scritta in tutti i linguaggi).
POU: program
Section titled “POU: program”Si compone di due parti:
- dichiarazione di variabili,
- parte di codice.
Il program può dichiarare ed utilizzare variabili di qualunque tipo e classe di visibilità (anche le VAR_ACCESS).
Il codice del program può essere scritto in qualunque linguaggio di programmazione della norma. Un program può chiamare sia function block che funzioni, ma non viene chiamato da nessuno quindi non restituisce variabili.
Il meccanismo che chiama un programma è il TASK (che si vedrà in seguito).
POU: function block (FB)
Section titled “POU: function block (FB)”POU di tipo intermedio. Si compone di due parti:
- dichiarazione di variabili,
- parte di codice.
Il FB non può dichiarare variabili globali né di tipo ACCESS PATH. Il codice del FB può essere scritto in qualunque linguaggio di programmazione della norma. Un FB può chiamare sia altri FB che funzioni e viene a sua volta chiamato o da FB, o da funzioni o da program. Quando viene chiamato, può restituire n variabili di uscita.
Le variabili di un FB sono statiche, ovvero tra una chiamata e la successiva il loro valore viene mantenuto in memoria. Se si passano sempre le stesse variabili di input, in base al valore delle variabili statiche, l’output del FB potrebbe essere differente.
In fase di programmazione, si può avere bisogno di variabili non statiche anche dentro ad un function block. La norma mette a disposizione un altro costrutto per la dichiarazione delle variabili di un function block, che le rende non statiche.
VAR_TEMP a: REAL; c: TIME;END_VARLa norma prevede che tutti gli IDE per la programmazione dei PLC che si vogliano dichiarare conformi ad essa, debbano fornire al programmatore la possibilità di:
- usare un set di FB già predefiniti,
- scrivere FB autonomamente.
Tra quelli predefiniti, che devono essere già a disposizione del programmatore, devono esserci almeno:
- timer Ton, Toff e Tp,
- contatori avanti e indietro,
- rilevatori dei fronti di salita e discesa.
La spiegazione di questi FB sarà fornita nel modulo didattico che riguarda la programmazione.
Dichiarazione testuale di un FB di nome FF_SERVO di tipo SR (Set Reset):
VAR FF_SERVO: SR;END_VAR
FF_SERVO(S := B, R := C); (* invocation *)A := FF_SERVO.Q; (* assign output *)Siccome un function block non restituisce un unico valore, come invece fa la funzione, per usarlo devo sempre scrivere due istruzioni:
- invocazione del FB,
- assegnazione di una uscita del FB alla variabile del codice.
Dichiarazione grafica:
Esempi di FUNCTION BLOCKS standard definiti dalla norma 61131-3
Section titled “Esempi di FUNCTION BLOCKS standard definiti dalla norma 61131-3”Function block timer on: ritardo all’inserzione.
Ingressi: IN (di tipo BOOL) e PT (di tipo TIME). Uscite: Q (di tipo BOOL) ed ET (di tipo TIME).
Quando ciò che è collegato a IN va a true, dopo PT secondi (o millisecondi) l’uscita Q va a true, e torna a false quando IN torna a false.
Function block timer off: ritardo alla disinserzione.
Ingressi: IN (di tipo BOOL) e PT (di tipo TIME). Uscite: Q (di tipo BOOL) ed ET (di tipo TIME).
Quando ciò che è collegato a IN va a true, Q va subito a true. Quando ciò che è collegato a IN va a false, dopo PT secondi (o ms) l’uscita Q torna a false.
Up counter: contatore in avanti.
Con un fronte di salita su RESET, azzera il termine del conteggio
CV poi conta i fronti di salita su CU. Quando il valore di conteggio raggiunge PV, Q va alto.
Down counter: contatore all’indietro.
Con un fronte di salita su LOAD, inizializza il contatore CV al valore di PV e lo decrementa ad ogni fronte di salita di CU. Quando il valore di conteggio si annulla, Q va alto.
Il LOAD è equivalente al RESET. Invece di resettare, in questo caso si deve ricaricare il valore di partenza.
Un function block è istanziato a livello di program o di un altro function block. Il program è istanziato a livello di resource. Ogni istanza di un program o di un function block condivide lo stesso codice, ma ha la sua area dati privata in memoria.
Nell’ambito dello stesso program, è possibile utilizzare più istanze diverse dello stesso function block.
Cos’è un’istanza? Cosa vuol dire che un function block è istanziato a livello di program o di un altro function block?
Esempio: si prenda il caso di uno struct in linguaggio C.
TYPEDEF struct { primo_campo: int; secondo_campo: char} my_record;Il tipo di dato my_record è definito una sola volta al di fuori di tutte le funzioni e viene istanziato ogni volta che dichiaro una variabile di tipo my_record all’interno di una qualche funzione.
Ogni istanza occupa un’area di memoria dati.
Nel caso del FB per PLC, invece che di variabili si parla di una POU (insieme di variabili e codice).
L’FB si può definire dentro ad un program o dentro ad un altro FB, ma poi ogni volta che si vuole avere la possibilità di richiamare questo FB, lo si deve istanziare.
L’istanziazione è praticamente una dichiarazione:
VAR counter1: counter;END_VARA questo punto, se in qualche riga di codice si invoca counter1, si manderà in esecuzione un codice di tipo counter.
Perché ogni volta che si istanzia un FB si accede sempre alla stessa area di codice ma si riserva un’area dati diversa?
Esempio: contare due tempi diversi. Il sistema ha due controlli:
- quando premi il pulsante P1, dopo 3 secondi accendi la luce L1,
- quando premi il pulsante P2, dopo 5 secondi apri il portello Q2.
Il codice del temporizzatore, ovvero le istruzioni usate per controllare il tempo, è sempre lo stesso. I due tempi non si devono sovrapporre o incrociare, perché le due funzioni devono rimanere distinte. Quindi si hanno due istanze di Ton: l’algoritmo di controllo tempo è sempre lo stesso, ma i due tempi sono memorizzati nelle due aree diverse assegnate alle due istanze del timer ON.
I due tempi partono e terminano in due istanti diversi, quindi ognuno deve essere separato e avere una sua locazione indipendente di memoria.
Sul concetto di istanza si è innestata la terza edizione della norma IEC61131 per estendere il function block ad un modello ad oggetti. L’ultima edizione della norma infatti incoraggia l’OOP.
POU: function
Section titled “POU: function”Si compone di una parte di dichiarazione di variabili e di una parte di codice. La funzione può dichiarare solo variabili locali e di input. Il codice di una funzione non può essere scritto nel linguaggio SFC.
Quando viene chiamata, la funzione restituisce al chiamante solo una variabile. Le variabili locali della funzione si resettano ad ogni chiamata, quindi sono volatili. Una funzione non ha memoria dell’esecuzione precedente. Ne consegue che ogni volta che si richiama una function passandole gli stessi parametri di ingresso, essa produrrà potenzialmente sempre la stessa uscita.
La definizione di una function creata dal programmatore richiede:
- lista di variabili d’ingresso ed interne (temporanee),
- descrizione dell’algoritmo implementato dalla funzione.
Tale algoritmo può essere implementato in un qualunque linguaggio della norma ad esclusione dell’SFC.
Esempio di function scritta in modo testuale:
FUNCTION SIMPLE_FUN : REAL VAR_INPUT A,B: REAL; C: REAL := 1.0; END_VAR
(* body specification: set the return value of the function *) SIMPLE_FUN := A * B / C;END_FUNCTIONLa norma prevede che tutti gli IDE per la programmazione dei PLC che si vogliano dichiarare conformi ad essa, debbano fornire al programmatore la possibilità di:
- usare un set di funzioni già predefinite,
- scrivere funzioni proprie.
Tra quelle predefinite, che devono essere già a disposizione del programmatore, devono esserci almeno:
- tutte le funzioni aritmetico/logico/matematiche (somma, sottrazione, moltiplicazione, divisione, AND, OR, NOT, seno, coseno, …),
- tutte le funzioni di confronto (›=, ›, ‹=, ‹, =, ‹› per il “diverso”),
- tutte le funzioni di manipolazione di bit (SHL, SHR, ROL, ROR, …),
- tutte le funzioni per gestire le stringhe (INSERT, CONCAT, …),
- tutte le funzioni per convertire il formato dei numeri (INT TO REAL, BCD TO INT).
Differenze tra POU
Section titled “Differenze tra POU”Program:
- può essere scritto in qualsiasi linguaggio,
- gestisce tutti i tipi di variabile,
- non restituisce alcun valore di ritorno,
- opera con variabili statiche,
- può chiamare function e function block,
- è eseguita quando chiamata da un task.
Function Block:
- può essere scritto in qualsiasi linguaggio,
- non gestisce variabili di tipo
globaleaccess, - restituisce n variabili di output,
- opera con variabili statiche,
- può chiamare function e function block,
- è eseguita quando chiamata da un’altra POU.
Function:
- non può essere scritta in lingiaggio SFC,
- può gestire solo variabili di tipo
localeinput, - restituisce una sola variabile,
- opera con variabili volatili,
- può chiamare function e function block,
- è eseguita quando chiamata da un’altra POU.
Il task è un processo software che si occupa di controllare e mettere in esecuzione un program, facendo in modo di assegnarlo al processore.
Può essere di due tipi:
- INTERVAL: periodico,
- SINGLE: mandato in esecuzione al verificarsi di un determinato evento.
N.B. Un program è solo un insieme di righe di codice e di dichiarazioni di variabili, che non interagisce con l’hardware se non viene mandato in esecuzione da un task.
Priorità del task: task a priorità maggiore possono interrompere task a priorità minore. La priority si identifica con un numero intero a partire dallo zero.
Eccezioni alla norma. Non tutti i PLC funzionano allo stesso modo. Ad esempio, l’ambiente di sviluppo dei PLC B&R non ammette task ad evento, ma solo ciclici (chiamati Cyclic). Sarà cura del programmatore associare ai task più veloci i compiti più critici.
Codesys ammette, oltre ai task interval (chiamati Cyclic) e single (chiamati Triggered by event), anche il task freewheeling che prevede la riesecuzione a ciclo continuo di un program senza aspettare un determinato tempo fisso. Appena l’esecuzione è terminata, riprende.
La norma IEC61131 è una norma mondiale, in continua evoluzione, che definisce le caratteristiche dell’ambiente di programmazione (IDE, Integrated Development Environment) tipico per la programmazione dei PLC. Alcuni produttori seguono la norma praticamente alla lettera, altri la seguono parzialmente. Anche i produttori che seguono scrupolosamente la norma possono comunque avere, nel loro ambiente di sviluppo, opzioni in numero maggiore rispetto a quanto espresso dalla norma stessa.
La maggior parte delle volte, cambiando marca di PLC e quindi ambiente di sviluppo, si devono fare degli aggiustamenti nel software. Siemens, leader di mercato, soddisfa la norma per quel che riguarda i linguaggi di programmazione, ma è totalmente diverso dalla norma per quel che riguarda l’architettura di un progetto software. POU e task sono gestiti in modo completamente diverso.
I più importanti IDE per la programmazione di PLC delle maggiori famiglie sono riportati di sotto. Una stessa marca può avere più IDE diversi per famiglie diverse dei suoi prodotti. Ad esempio, Siemens ha TIA Portal per le CPU più moderne e performanti, mentre per la serie dei PLC compatti Logo! ha un IDE che si chiama Logo Soft Comfort.
- TIA Portal: Siemens,
- RSLogix: Rockwell – Allen Bradley,
- Automation Studio: B&R,
- Twincat: Beckhoff,
- CX-One: Omron