Arduino Opta è un micro-PLC sviluppato da Arduino in collaborazione con Finder e destinato ad applicazioni di automazione e controllo. Integra otto ingressi utilizzabili come digitali o analogici, quattro uscite a relè, Ethernet, alimentazione industriale e montaggio su guida DIN.
In questo esempio viene utilizzato Arduino Opta Lite con Arduino IDE 2.3.10 per realizzare un classico comando marcia-arresto con autoritenuta software. Gli ingressi sono trattati come segnali digitali, l’arresto ha priorità sulla marcia ed è previsto un blocco contro il riavvio automatico.
Parole chiave: Arduino Opta, Opta Lite, PLC, Arduino IDE, ingressi digitali, relè, marcia-arresto, autoritenuta.
Arduino Opta
Opta si colloca fra una tradizionale scheda embedded e un PLC compatto. Il dispositivo mantiene il modello di programmazione Arduino, ma dispone di morsetti, livelli elettrici, relè e caratteristiche costruttive adatte a un ambiente di automazione.
Il microcontrollore è uno STM32H747XI dual core, composto da un Cortex-M7 fino a 480 MHz e da un Cortex-M4 fino a 240 MHz. Sono disponibili otto ingressi analogici/digitali e quattro relè normalmente aperti. L’alimentazione nominale è compresa fra 12 e 24 Vcc.
La famiglia comprende tre versioni:
- Opta Lite: USB-C ed Ethernet 10/100BASE-T.
- Opta RS485: aggiunge un’interfaccia RS-485.
- Opta WiFi: aggiunge RS-485, Wi-Fi e Bluetooth Low Energy.
La versione utilizzata in questa prova è Opta Lite: dispone quindi della porta Ethernet, ma non integra RS-485 né interfacce wireless.
Elementi principali di Opta Lite
L’alimentazione è prevista a 12...24 Vcc. È presente inoltre un collegamento FE, Functional Earth, destinato alla riduzione delle interferenze elettromagnetiche e distinto dal comune GND.
Gli otto ingressi sono identificati direttamente sulla morsettiera come:
I1 I2 I3 I4 I5 I6 I7 I8
Le quattro uscite sono realizzate mediante relè con contatto normalmente aperto. Nel core Arduino sono indicate come:
RELAY1
RELAY2
RELAY3
RELAY4
Opta Lite dispone inoltre di porta USB-C, porta Ethernet, pulsante RESET, pulsante programmabile dall’utente, quattro LED frontali programmabili e porta per moduli di espansione.
Il valore massimo dichiarato per i relè non deve essere interpretato come utilizzabile indiscriminatamente con qualsiasi carico. Capacità di interruzione, tensione, corrente, categoria d’impiego e protezioni devono essere valutate in funzione dell’applicazione. Le uscite richiedono una protezione esterna appropriata contro il cortocircuito.
Pinout nel codice Arduino
Il core Arduino Mbed OS definisce nomi che corrispondono direttamente alla serigrafia di Opta. Gli ingressi sono disponibili come:
I1
I2
I3
I4
I5
I6
I7
I8
I relè sono invece definiti come:
RELAY1
RELAY2
RELAY3
RELAY4
Il pulsante programmabile di bordo è identificato da:
BTN_USER
I quattro LED frontali possono essere richiamati come:
LED_RELAY1
LED_RELAY2
LED_RELAY3
LED_RELAY4
Queste definizioni rendono il codice più leggibile rispetto all’uso dei numeri interni dei pin.
LED e pulsante di bordo
I quattro LED numerati sul frontale sono programmabili dall’utente e possono essere utilizzati per visualizzare stati, allarmi o condizioni operative.
Nel core sono inoltre presenti le definizioni del LED RGB di sistema:
LEDR
LEDG
LEDB
LED_RESET
LED_USER
Il piccolo LED verde viene utilizzato anche durante le procedure di bootloader: con un doppio RESET può iniziare a pulsare lentamente per indicare l’ingresso nella modalità di caricamento.
Non è una spia di alimentazione. Opta può essere acceso ed eseguire normalmente uno sketch anche con quel LED spento.
Il pulsante programmabile dall’utente, distinto dal RESET, è disponibile nel codice come BTN_USER e può essere associato a funzioni definite dal programma.
Ingressi digitali
Gli ingressi I1...I8 possono essere utilizzati sia come analogici sia come digitali, ma i due impieghi non devono essere confusi.
In modalità analogica il campo specificato è 0...10 V. In modalità digitale il campo è invece 0...24 V.
Il datasheet specifica inoltre le soglie:
LOW garantito: V ≤ 4,46 V
HIGH garantito: V ≥ 6,6 V
Un segnale di 10 V è quindi inequivocabilmente interpretato come livello digitale HIGH.
Per un pulsante marcia-arresto non serve misurare la tensione tramite ADC: il segnale contiene soltanto due informazioni, contatto aperto o chiuso, e deve quindi essere letto direttamente con digitalRead().
Programmazione con Arduino IDE
Opta può essere programmato direttamente mediante normali sketch Arduino. In questa applicazione è stato utilizzato Arduino IDE 2.3.10, con collegamento al computer tramite USB-C.
Per l’esecuzione di uno sketch Arduino non sono necessari runtime PLC, configurazioni Modbus o altri livelli software: il programma viene compilato e trasferito direttamente al dispositivo.
Comando marcia-arresto
L’applicazione utilizza:
I1 → MARCIA, contatto normalmente aperto (NO)
I2 → ARRESTO, contatto normalmente chiuso (NC)
RELAY1 → uscita O1
Il comportamento richiesto è quello tipico di un circuito marcia-arresto:
- all’accensione l’uscita deve essere disattivata;
- premendo MARCIA il relè deve eccitarsi;
- rilasciando MARCIA il relè deve restare eccitato;
- premendo ARRESTO il relè deve diseccitarsi;
- ARRESTO deve avere priorità su MARCIA;
- mantenendo MARCIA premuto durante un arresto, il sistema non deve ripartire automaticamente;
- per ripartire è necessario rilasciare MARCIA e premerlo nuovamente.
L’autoritenuta viene quindi realizzata interamente nel software.
Perché ARRESTO è normalmente chiuso
Il pulsante di arresto viene utilizzato come contatto normalmente chiuso. In condizioni normali I2 riceve il livello HIGH; premendo il pulsante il circuito viene interrotto e I2 passa a LOW.
Questa scelta riproduce la logica tradizionalmente utilizzata nei circuiti di comando industriali. Si tratta comunque di un arresto funzionale gestito dal software, non di una funzione di sicurezza certificata.
Sketch completo
Download: opta_marcia_arresto.ino
/*
ARDUINO OPTA LITE
Comando MARCIA / ARRESTO con autoritenuta software
I1 = pulsante MARCIA normalmente aperto (NO)
I2 = pulsante ARRESTO normalmente chiuso (NC)
RELAY1 = uscita O1
Gli ingressi vengono utilizzati come DIGITALI.
Funzionamento:
- all'avvio O1 è disattivata;
- premendo MARCIA, O1 si attiva;
- rilasciando MARCIA, O1 rimane attiva;
- premendo ARRESTO, O1 si disattiva;
- ARRESTO ha sempre priorità;
- se MARCIA resta premuta durante ARRESTO,
il sistema non riparte automaticamente;
- per un nuovo avvio bisogna rilasciare MARCIA
e premerla nuovamente.
Il Monitor Seriale visualizza soltanto i cambiamenti
significativi di stato.
Non viene utilizzato delay().
*/
// ------------------------------------------------------------
// ASSEGNAZIONE DEGLI I/O
// ------------------------------------------------------------
const int PIN_MARCIA = I1;
const int PIN_ARRESTO = I2;
const int PIN_RELE = RELAY1;
// ------------------------------------------------------------
// STATO DEL SISTEMA
// ------------------------------------------------------------
// Memoria dell'autoritenuta.
// false = relè disattivato
// true = relè attivato
bool releMarcia = false;
// Blocco contro il riavvio automatico.
//
// All'accensione viene inizializzato a true.
// Se MARCIA fosse già premuta durante l'avvio,
// il relè non potrebbe quindi eccitarsi.
//
// Il blocco viene rimosso soltanto quando
// MARCIA viene rilevata rilasciata.
bool avvioNegato = true;
// ------------------------------------------------------------
// VARIABILI PER IL MONITOR SERIALE
// ------------------------------------------------------------
// Memorizzano gli stati precedenti in modo da stampare
// soltanto gli eventi e non ripetere continuamente
// le stesse informazioni.
bool marciaPrecedente = false;
bool arrestoPrecedente = false;
bool relePrecedente = false;
bool avvioNegatoPrecedente = true;
bool primaLettura = true;
// ------------------------------------------------------------
// SETUP
// ------------------------------------------------------------
void setup() {
// Ingressi industriali utilizzati come segnali digitali.
pinMode(PIN_MARCIA, INPUT);
pinMode(PIN_ARRESTO, INPUT);
// Relè O1.
pinMode(PIN_RELE, OUTPUT);
// Condizione iniziale:
// il relè deve essere sempre diseccitato.
releMarcia = false;
digitalWrite(PIN_RELE, LOW);
// Blocco iniziale contro partenze indesiderate.
avvioNegato = true;
// Monitor Seriale.
Serial.begin(115200);
}
// ------------------------------------------------------------
// LOOP PRINCIPALE
// ------------------------------------------------------------
void loop() {
// Lettura degli ingressi.
//
// MARCIA, contatto NO:
// rilasciato -> LOW
// premuto -> HIGH
//
// ARRESTO, contatto NC:
// rilasciato -> HIGH
// premuto -> LOW
const bool marcia =
digitalRead(PIN_MARCIA) == HIGH;
const bool arresto =
digitalRead(PIN_ARRESTO) == HIGH;
// ----------------------------------------------------------
// LOGICA DI CONTROLLO
// ----------------------------------------------------------
// ARRESTO ha sempre la priorità.
// Essendo un contatto NC, quando viene premuto
// I2 passa a LOW.
if (!arresto) {
// Diseccitazione immediata del relè.
releMarcia = false;
// Attiva il blocco del riavvio.
// Se MARCIA è ancora premuta quando ARRESTO
// viene rilasciato, il relè non può ripartire.
avvioNegato = true;
}
// Se ARRESTO è nella condizione normale
// e MARCIA è rilasciata, viene ripristinato
// il consenso a un nuovo avvio.
else if (!marcia) {
avvioNegato = false;
}
// Il relè può essere attivato soltanto quando:
// - ARRESTO non è premuto;
// - MARCIA è premuta;
// - il consenso al nuovo avvio è presente.
else if (marcia && !avvioNegato) {
releMarcia = true;
}
// ----------------------------------------------------------
// COMANDO DELL'USCITA O1
// ----------------------------------------------------------
digitalWrite(
PIN_RELE,
releMarcia ? HIGH : LOW
);
// ----------------------------------------------------------
// MONITOR SERIALE
// ----------------------------------------------------------
// Alla prima esecuzione vengono memorizzati gli stati
// correnti e viene visualizzata la situazione iniziale.
if (primaLettura) {
Serial.println("OPTA - MARCIA / ARRESTO");
Serial.print("MARCIA: ");
Serial.println(marcia ? "PREMUTA" : "RILASCIATA");
Serial.print("ARRESTO: ");
Serial.println(arresto ? "RILASCIATO" : "PREMUTO");
Serial.print("O1: ");
Serial.println(releMarcia ? "ATTIVA" : "DISATTIVATA");
Serial.println(
avvioNegato
? "AVVIO BLOCCATO"
: "AVVIO CONSENTITO"
);
Serial.println();
marciaPrecedente = marcia;
arrestoPrecedente = arresto;
relePrecedente = releMarcia;
avvioNegatoPrecedente = avvioNegato;
primaLettura = false;
return;
}
// Evento MARCIA.
if (marcia != marciaPrecedente) {
Serial.println(
marcia
? "MARCIA premuta"
: "MARCIA rilasciata"
);
marciaPrecedente = marcia;
}
// Evento ARRESTO.
if (arresto != arrestoPrecedente) {
if (!arresto) {
Serial.println("ARRESTO premuto");
}
else {
Serial.println("ARRESTO rilasciato");
// ARRESTO viene rilasciato mentre MARCIA
// è ancora mantenuta premuta.
if (marcia && avvioNegato) {
Serial.println(
"MARCIA ancora premuta: avvio non consentito"
);
}
}
arrestoPrecedente = arresto;
}
// Evento uscita O1.
if (releMarcia != relePrecedente) {
Serial.println(
releMarcia
? "O1 ATTIVA"
: "O1 DISATTIVATA"
);
relePrecedente = releMarcia;
}
// Evento consenso all'avvio.
if (avvioNegato != avvioNegatoPrecedente) {
Serial.println(
avvioNegato
? "RIAVVIO BLOCCATO"
: "NUOVO AVVIO CONSENTITO"
);
avvioNegatoPrecedente = avvioNegato;
}
}
Nessun delay()
Nel programma non viene utilizzato delay(). Il ciclo principale continua quindi a leggere gli ingressi ed elaborare la logica senza introdurre attese artificiali.
Anche il Monitor Seriale non utilizza una temporizzazione periodica: vengono stampati soltanto i cambiamenti di stato. Una normale sequenza può apparire così:
OPTA - MARCIA / ARRESTO
MARCIA: RILASCIATA
ARRESTO: RILASCIATO
O1: DISATTIVATA
AVVIO CONSENTITO
MARCIA premuta
O1 ATTIVA
MARCIA rilasciata
ARRESTO premuto
O1 DISATTIVATA
RIAVVIO BLOCCATO
ARRESTO rilasciato
MARCIA rilasciata
NUOVO AVVIO CONSENTITO
MARCIA premuta
O1 ATTIVA
Il monitor descrive quindi direttamente ciò che sta facendo il sistema, senza produrre una sequenza continua di valori identici.
Autoritenuta software
La variabile releMarcia costituisce la memoria dell’autoritenuta. Quando MARCIA viene premuta nelle condizioni corrette viene impostata a true e rimane tale anche dopo il rilascio del pulsante.
releMarcia = true;
Il comando fisico del relè segue lo stato memorizzato:
digitalWrite(PIN_RELE, releMarcia ? HIGH : LOW);
È l’equivalente software dell’autoritenuta che, in un circuito elettromeccanico tradizionale, viene normalmente realizzata mediante un contatto ausiliario.
Priorità dell’arresto
La prima condizione verificata dal programma è:
if (!arresto)
Di conseguenza ARRESTO prevale su qualsiasi altra condizione. Se MARCIA e ARRESTO vengono azionati contemporaneamente, il programma diseccita comunque O1.
Prevenzione del riavvio automatico
L’autoritenuta da sola non è sufficiente. Se MARCIA rimanesse premuta mentre viene azionato ARRESTO, al rilascio di ARRESTO il programma potrebbe interpretare MARCIA ancora attiva come una nuova richiesta di partenza.
La variabile avvioNegato impedisce questa condizione. Premendo ARRESTO viene impostata a true:
avvioNegato = true;
Il consenso viene ripristinato soltanto quando MARCIA viene effettivamente rilasciata:
else if (!marcia) {
avvioNegato = false;
}
Occorre quindi una nuova pressione di MARCIA per eccitare nuovamente O1. La stessa logica evita una partenza automatica all’accensione qualora il pulsante MARCIA si trovi già premuto.
Pulsante utente e LED per sviluppi successivi
Il pulsante frontale programmabile, disponibile come BTN_USER, può essere utilizzato per funzioni indipendenti dal RESET, per esempio conferma di un allarme, cambio modalità o comando locale.
Analogamente, i quattro LED frontali possono essere comandati dal software. Possono essere impiegati per visualizzare lo stato logico delle uscite o altre condizioni della macchina senza modificare la logica principale del comando.
Ethernet su Opta Lite
Opta Lite dispone direttamente di una porta Ethernet 10/100BASE-T. L’interfaccia permette di estendere successivamente lo stesso programma con comunicazione di rete, supervisione, acquisizione dati o integrazione con altri sistemi senza aggiungere un’interfaccia Ethernet esterna.
Sicurezza
Il circuito descritto realizza un comando funzionale marcia-arresto. Non deve essere confuso con un arresto di emergenza o con una funzione di sicurezza.
Un arresto di emergenza, una protezione contro movimenti pericolosi o altre funzioni safety devono essere progettati con architetture, componenti e categorie di sicurezza appropriate. Il semplice fatto che il programma assegni priorità ad ARRESTO non rende Opta o lo sketch un sistema safety.
Lo stesso vale per i relè di uscita: tensione, corrente, categoria d’impiego, caratteristiche del carico e protezioni devono essere verificate prima del collegamento.
Conclusioni
Arduino Opta Lite permette di utilizzare il modello di programmazione Arduino su un dispositivo progettato per applicazioni di automazione. Dispone di ingressi compatibili con livelli industriali, quattro relè, Ethernet, alimentazione 12...24 Vcc, morsetti e montaggio adatti a un quadro elettrico.
Nel comando marcia-arresto gli ingressi vengono utilizzati direttamente come digitali. Non è quindi necessario misurare la tensione con l’ADC: digitalRead() restituisce direttamente lo stato logico richiesto dall’applicazione. Il campo digitale specificato arriva a 24 Vcc, con HIGH garantito a partire da 6,6 V.
L’autoritenuta e il blocco del riavvio vengono realizzati nel software senza utilizzare delay(). Il Monitor Seriale lavora a eventi e permette di seguire in modo leggibile il comportamento dei pulsanti, del consenso e dell’uscita.
Fonti principali
Arduino Documentation — Opta
Arduino — Opta Collective Datasheet
Arduino — Opta Full Pinout
ArduinoCore-mbed — variante OPTA, pins_arduino.h
Arduino Help Center — FAQ: Arduino Opta.