Strumento online per programmare i motori lineari integrati NILAB (famiglia NLi) usando la sintassi IEC 61131-3 Structured Text. Lo strumento compila il sorgente ST nel formato Instruction List (IL) compatibile con il firmware NILAB µPLC (>= 5E41).
Accesso allo strumento: ni-lab.online → Strumenti → ST Converter
Il µPLC NILAB è una soft-PLC embedded che gira dentro ogni motore lineare integrato NLi. Esegue un programma scritto nel formato Instruction List (IL) — un linguaggio di basso livello, riga per riga, simile all'assembly. Scrivere IL direttamente è soggetto a errori e difficile da leggere. Il convertitore ST-to-IL ti permette di scrivere programmi in Structured Text (ST), un linguaggio ad alto livello IEC 61131-3 simile a Pascal, e li compila automaticamente in IL.
| Parametro | Valore |
| Firmware richiesto | >= 5E41 |
| Max istruzioni | 64 |
| Ciclo di scan | 6 ms (fisso) |
| Profondità stack | 1 (niente AND/OR annidati in un IF) |
| Timer | 2 timer hardware (R8028, R8029) |
Fatti chiave sul µPLC NILAB:
Figura 1: Interfaccia principale. Colonna sinistra: editor ST. Colonna destra: output IL generato. Pannelli inferiori: Symbol Table e IL Simulator (quando attivo).
Lo strumento è diviso in tre aree principali:
① Toolbar — campo nome progetto, pulsante Convert, Download IL, Salva/Carica file ST, checkbox Optimize, toggle Simulator, Mostra/Nascondi pannello Reference.
② ST Editor (colonna sinistra, ~65% larghezza) — Scrivi qui il tuo programma Structured Text. Caratteristiche:
| Voce |
| Evidenziazione sintassi (parole chiave in rosso, registri in blu, nomi tipo in viola, commenti in grigio) |
Numeri riga con marcatori errore nella gutter (rosso ! = errore, giallo W = avviso) |
| Tasto Tab inserisce 2 spazi |
| Ctrl+Invio attiva la conversione |
③ IL Output (colonna destra, ~35% larghezza) — L'Instruction List compilato appare qui dopo aver premuto Convert. I numeri di passo sono mostrati in grigio a sinistra; il registro di destinazione delle istruzioni matematiche è evidenziato in arancione.
④ Message Panel — Situato sotto l'editor ST. Mostra errori di compilazione (rosso), avvisi (giallo) e suggerimenti dell'ottimizzatore (blu). Clicca qualsiasi tag posizione L## per saltare a quella riga nell'editor.
⑤ Symbol Table — Appare in fondo alla pagina quando è presente un blocco VAR. Mostra tutte le variabili dichiarate con i loro indirizzi di registro assegnati automaticamente.
⑥ IL Simulator — Appare sotto la Symbol Table quando il pulsante Simulator è attivato. Consente esecuzione passo-passo o continua dell'IL compilato.
⑦ Reference Panel — Nascosto di default. Premi Mostra Reference nella toolbar per aprire una barra laterale di quick-reference della sintassi.
Usa VAR_ALIAS per dare nomi leggibili a registri hardware e indirizzi di bit. Queste sono semplici sostituzioni di testo — nessun registro viene assegnato automaticamente.
\ VAR_ALIAS\ DI0 := R4620.0; (* Digital Input 0, bit 0 di R4620 *)\ DI1 := R4620.1; (* Digital Input 1, bit 1 di R4620 *)\ ACTV := R8684.1; (* flag sequenza attiva *)\ TIMER1 := R8028; (* registro Timer 1 *)\ END_VAR_ALIAS\
Usa VAR per dichiarare variabili tipizzate. Il compilatore assegna automaticamente il prossimo registro libero dal pool di allocazione — non devi conoscere gli indirizzi dei registri.
\VAR counter : INT := 0; (* assegnato automaticamente a R8683 *) enable : BOOL; (* assegnato automaticamente a R8681.0 *) done : BOOL := TRUE;(* assegnato automaticamente a R8681.1, init *) T1 : TON; (* assegnato automaticamente a Timer1 R8028 *) edge1 : R_TRIG; (* assegnati automaticamente 2 slot BOOL *) \END_VAR
Tipi supportati:
| Tipo | Pool registri IL | Max | Valore iniziale |
| BOOL | R8681 bit 0-15, poi R8682 bit 0-15 | 32 | 0/1/TRUE/FALSE |
| INT | R8683, R8684, R8685, R8686, R8687, R8688 | 6 | 0, 1, 10, 100, 1000 |
| DWORD | stesso pool di INT | 6 | uguale |
| TON | R8028 (Timer1), R8029 (Timer2) | 2 | - |
| CTD | R8028 (Timer1), R8029 (Timer2) | 2 | - |
| CTU | uno slot INT per valore contatore | 16 | - |
| R_TRIG | 2 slot BOOL (memoria + uscita Q) | 16 | - |
| F_TRIG | 2 slot BOOL (memoria + uscita Q) | 16 | - |
Nota: Le costanti R8675–R8680 sono di sola lettura e non possono essere usate come destinazioni di scrittura. Il compilatore lo impone con un errore.
I seguenti registri costanti sono sempre disponibili senza dichiarazione:
| Registro | Valore | Esempio di utilizzo |
| R8675 | 0 | Azzera un registro a zero |
| R8676 | 1 | Incrementa, booleano TRUE |
| R8678 | 10 | Moltiplica o confronta |
| R8679 | 100 | Valore ricarica timer (600 ms) |
| R8680 | 1000 | Costante grande |
I letterali interi 0, 1, 10, 100 e 1000 sono mappati automaticamente a questi registri nel compilatore. Qualsiasi altro valore letterale produrrà un errore di compilazione — carica prima il valore in un registro utente.
\ IF condition THEN\ statement(s);\ ELSE (* opzionale *)\ statement(s);\ END_IF;\
Operatori di condizione:
| Operatore | Istruzione IL | Note |
| AND | AND / ANDn | Contatto in serie |
| OR | OR / ORn | Contatto in parallelo |
| NOT | LDn / ANDn / ORn | Inverte il termine seguente |
Miscelare AND e OR è supportato con valutazione strettamente da sinistra a destra (nessuna precedenza operatori): * A AND B OR C → IL: LD A, AND B, OR C → risultato: (A AND B) OR C * A OR B AND C → IL: LD A, OR B, AND C → risultato: (A OR B) AND C * Un avviso viene mostrato quando AND e OR sono miscelati nella stessa condizione.
Limite profondità stack = 1: Ogni condizione IF usa lo stack a livello singolo. Non puoi usare(A AND B) OR (C AND D)in un IF — dividilo in due blocchi IF o usa un flag BOOL intermedio.
SET(R4621.0); (* latch bit ON *)\ RESET(R4621.0); (* latch bit OFF *)\ R4621.0 := 1; (* equivalente a SET *)\ R4621.0 := 0; (* equivalente a RESET *)\
(* Quattro operazioni aritmetiche *) Rc := Ra + Rb; (* IL: ADD Ra, Rb, Rc *) Rc := Ra - Rb; (* IL: SUB Ra, Rb, Rc *) Rc := Ra * Rb; (* IL: MUL Ra, Rb, Rc *) Rc := Ra / Rb; (* IL: DIV Ra, Rb, Rc — divisione intera *) (* Copia *) Rb := Ra; (* IL: MOV Ra, Rb *) (* Confronto — imposta flag in R8671 *) CMP(Ra, Rb);
Flag risultato CMP in R8671:
| Bit | Flag | Significato |
| .0 | T1 | Timer1 (R8028) scaduto |
| .1 | T2 | Timer2 (R8029) scaduto |
| .2 | LT | Pa < Pb |
| .3 | EQ | Pa = Pb |
| .4 | GT | Pa > Pb |
I blocchi funzione vengono chiamati per nome con assegnazioni di porte con nome. Sono espansi inline in istruzioni IL.
\ VAR\ edge1 : R_TRIG;\ END_VAR\ VAR_ALIAS\ DI1 := R4620.1;\ END_VAR_ALIAS edge1(CLK := DI1); (* edge1.Q è TRUE per esattamente uno scan sul fronte di salita di DI1 *)\ IF edge1.Q AND NOT ACTV THEN\ SET(ACTV);\ END_IF;\
IL generato (4 istruzioni): LD / ANDn / OUT / LD / OUT
Uguale a R_TRIG ma scatta sul fronte di discesa. Porta: CLK.
\VAR T1 : TON; END_VAR T1(IN := ACTV, PT := 100); (* PT=100 scan × 6ms = 600ms di ritardo *) (* T1 scaduto quando R8671.0 = 1 *) IF R8671.0 AND ACTV \THEN (* azione timer scaduto *) R8028 := R8679; (* ricarica timer *) END_IF;
\VAR C1 : CTU; END_VAR C1(CU := pulse_bit, PV := 5); (* C1.Q = TRUE quando il conteggio >= 5 *)
Abilita la checkbox Optimize IL prima di premere Convert per attivare l'ottimizzatore. Esegue fino a 12 passaggi iterativi e applica quattro trasformazioni:
OPT-1 — Hoisting della condizione (risparmio maggiore)
Ogni istruzione dentro un blocco IF normalmente ripete la condizione completa. L'ottimizzatore rileva condizioni ripetute consecutive e le emette solo una volta, mantenendo lo stack attivo su più azioni.
Prima: LD 8671.2 AND 8671,0 ADD 4622,8683,4622 (3+1 = 4 istruzioni)
LD 8671.2 AND 8671,0 MOV 8679,8028 (3+1 = 4 istruzioni)
Dopo: LD 8671.2 AND 8671,0 ADD 4622,8683,4622 (3+1+1 = 5 istruzioni)
MOV 8679,\8028
Per un IF con N istruzioni e una condizione di lunghezza C, il risparmio è (N-1) × C istruzioni.
OPT-2 — IF/ELSE SET/RES → OUT
IF A THEN SET(Q); ELSE RESET(Q); END_IF; è semanticamente identico a OUT Q — il bit riceve esattamente il valore dello stack.
Prima: LD 4620.1 SET 8684,0 (2 istruzioni)
LDn 4620.1 RES 8684,0 (2 istruzioni)
Dopo: LD 4620.1 OUT 8684,0 (2 istruzioni totali)
OPT-3 — Eliminazione MOV morto
MOV Pa, Pa (copiare registro su se stesso) viene rimosso silenziosamente.
OPT-4 — Eliminazione doppio NOT
LDn + OUTn → LD + OUT (la doppia negazione si cancella).
Risparmi tipici: 30–45% su programmi con più blocchi IF. Il pannello messaggi mostra una ripartizione: es. Optimizer: 38 → 22 passi (-42%). OPT-1:-14, OPT-2:-2. Passaggi: 2.
La Symbol Table appare automaticamente in fondo alla pagina quando il programma contiene un blocco VAR. Mostra:
Il badge del conteggio (es. 3 vars) mostra quante variabili tipizzate sono state dichiarate.
Usa la Symbol Table per sapere esattamente quale registro corrisponde a ogni variabile quando si monitora il motore con MODBUS o NILAB Starter.
L'IL Simulator esegue il programma IL compilato ciclo per ciclo direttamente nel browser, consentendo la verifica funzionale senza collegarsi all'hardware.
Se modifichi il programma ST e premi di nuovo Convert mentre il Simulator è attivo, l'IL viene ricaricato e la simulazione si reimposta automaticamente.
Input R4620 — Tre pulsanti toggle (IN0, IN1, IN2) che rappresentano i bit 0-2 del registro ingressi digitali R4620. Clicca per commutare il bit. Evidenziazione verde = bit è 1.
Output R4621 — Quattro LED che mostrano i bit 0-2 di R4621 (uscite digitali) e il bit 0 di R4096 (abilitazione drive). Arancione = attivo.
R4622 — Mostra il valore corrente del registro di uscita utente R4622 (indice tabella motion controller, comando posizione, ecc.).
Flags R8671 — Pillole indicatore per ogni bit di flag. Verde = attivo: * T1, T2 — timer scaduto * LT, EQ, GT — risultato dell'ultima istruzione CMP
Controlli: * Reset — Ricarica IL dal pannello di output e inizializza tutti i registri * Step — Esegue un ciclo di scan completo (o premi Spazio quando in pausa) * Run / Pause — Esecuzione continua alla velocità selezionata * Slow / Med / Fast / 6ms — Intervallo di scan: 1000ms / 300ms / 80ms / 6ms (velocità hardware reale)
Registers — Un elenco di tutti i registri referenziati nell'IL compilato, mostrati come campi modificabili. I valori si aggiornano a ogni ciclo di scan. Puoi anche digitare un nuovo valore per sovrascrivere un registro (utile per iniettare un valore di posizione o simulare una scrittura MODBUS).
Entrambi i timer hardware (R8028, R8029) vengono decrementati di 1 all'inizio di ogni ciclo di scan. I flag T1/T2 in R8671 vengono impostati quando il timer raggiunge zero. Per simulare un timer di 600ms:
| Pulsante | Azione |
| CONVERT | Compila il programma ST. Scorciatoia: Ctrl+Invio |
| DOWNLOAD .IL | Salva l'IL compilato come file di testo .il. Bloccato se ci sono errori |
| SAVE .ST | Salva il sorgente ST corrente come file .st |
| LOAD .ST | Apre un file .st salvato in precedenza nell'editor. Attiva la conversione automatica |
| OPTIMIZE IL | checkbox — abilita prima di Convert per attivare l'ottimizzatore IL a 4 passaggi |
| SIMULATOR | Toggle del pannello IL Simulator |
| SHOW REFERENCE | Toggle della barra laterale di riferimento sintassi |
| PROJECT NAME FIELD | Imposta il nome file usato dai pulsanti Download/Save |
Dopo aver scaricato il file .il:
La dimensione massima del programma è 64 istruzioni (incluso l'obbligatorioEND). Il contatore passi nella toolbar mostra l'utilizzo corrente e diventa giallo sopra 48 passi e rosso sopra 64.
| Vincolo | Dettagli |
| Max istruzioni | 64 passi (incluso END) |
| Profondità stack | 1 — nessun AND/OR annidato in una condizione IF |
| No loop FOR / WHILE | Usa invece sequenze basate su timer o logica srotolata |
| No IF annidato | Usa bit di flag (variabili BOOL) per stati complessi |
| No aritmetica nelle condizioni | Valuta con CMP prima, poi testa i bit flag R8671 |
| Letterali costanti | Solo 0, 1, 10, 100, 1000 sono mappati a registri costanti |
| MAX variabili BOOL | 32 (bit 0-15 di R8681 e R8682) |
| MAX variabili INT | 6 (R8683 a R8688) |
| MAX timer (TON/CTD) | 2 (R8028 e R8029) |
| Intervallo indice bit | solo 0 a 15 |
| Registri di sola lettura | R8675–R8680 non possono essere destinazioni di scrittura |
Questo programma seleziona uno di quattro voci della tabella di movimento in base allo stato di due ingressi digitali. È tipicamente usato con il motion controller NILAB configurato per 5 mappe con 2 posizioni per mappa (parametro 1792 = 5).
\ (* NILAB uPLC - Sequenza di movimento a 4 passi con 2 Ingressi Digitali *)\ (* *)\ (* Parametro 1792 = 5 Mappe, 2 posizioni per mappa *)\ (* Motion controller: 10 task di posizione configurati *) VAR_ALIAS\ DI0 := R4620.0; (* Digital Input 0 *)\ DI1 := R4620.1; (* Digital Input 1 *)\ END_VAR_ALIAS (* Pre-calcola le costanti dell'indice tabella *)\ R8683 := R8676 + R8676; (* R8683 = 2 *)\ R8684 := R8683 + R8683; (* R8684 = 4 *)\ R8685 := R8684 + R8683; (* R8685 = 6 *) (* Seleziona l'indice tabella in base alla combinazione DI0 e DI1 *)\ IF DI0 AND DI1 THEN (* DI0=1, DI1=1 → indice 6 *)\ R4622 := R8685;\ END_IF; IF DI0 AND NOT DI1 THEN (* DI0=1, DI1=0 → indice 4 *)\ R4622 := R8684;\ END_IF; IF NOT DI0 AND DI1 THEN (* DI0=0, DI1=1 → indice 2 *)\ R4622 := R8683;\ END_IF; IF NOT DI0 AND NOT DI1 THEN (* DI0=0, DI1=0 → indice 0 *)\ R4622 := R8675;\ END_IF; (* Scrivi l'indice tabella solo quando cambia *)\ CMP(R4622, R8686);\ IF NOT R8671.3 THEN (* flag EQ = 0 significa valore cambiato *)\ R4623 := R8676; (* segnale: nuovo indice tabella attivo *)\ R8686 := R4622; (* salva indice corrente come riferimento *)\ END_IF;\
Tabella di verità:
| DI0 | DI1 | R4622 (indice tabella) - R4623 deve essere impostato a 1 | Posizione di movimento |
| 0 | 0 | 0 | Task di posizione 0 e 1 |
| 0 | 1 | 2 | Task di posizione 2 e 3 |
| 1 | 0 | 4 | Task di posizione 4 e 5 |
| 1 | 1 | 6 | Task di posizione 6 e 7 |
Come testare con il Simulator: - Premi Convert (con Optimize IL abilitato: 23 istruzioni → ~16) - Premi Simulator → Reset - Commuta i pulsanti IN0 e IN1 — osserva R4622 che cambia nel pannello registri - Il flag EQ (R8671.3) dovrebbe essere 0 quando il valore cambia e 1 quando rimane uguale - R4623 cambia a 1 solo nello scan quando l'indice tabella cambia