
In riferimento alla lezione: Arduino esercizi – Base marziana ELYSIUM, riporto di seguito tre possibili soluzioni, nei commenti di ogni sketch la spiegazione sul funzionamento.
Fase 1 – solo pulsante
// Prof. Maffucci Michele
// data 12.11.25
// Base marziana ELYSIUM - fase 1 - solo pulsante
const int PIN_LED = 9;
const int PIN_PULSANTE = 2; // pull-down esterno: HIGH quando premuto
void setup() {
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_PULSANTE, INPUT); // nessun pull-up interno
digitalWrite(PIN_LED, LOW);
}
void loop() {
int statoPulsante = digitalRead(PIN_PULSANTE);
if (statoPulsante == HIGH) { // pulsante premuto
digitalWrite(PIN_LED, HIGH); // accendo la luce di cortesia
delay(1500); // 1,5 s
digitalWrite(PIN_LED, LOW); // spengo
delay(50); // piccolo anti-rimbalzo
}
}
Con questa soluzione alla pressione del pulsante il LED si accende e se rilasciate si spegne, però se mantenete premuto il pulsante notare un veloce spegnimento ed una riaccensione del LED ovvero ciò che stiamo facendo e riaccendere immediatamente il LED.
Per evitare ciò bisogna implementare la versione che evita il retrigger.
Evitare il retrigger significa impedire che, tenendo il pulsante premuto, il ciclo riparta subito dopo lo spegnimento del LED e lo riaccenda di nuovo. Per evitarlo, dopo la sequenza (LED acceso per 1,5 s > LED spento) si controlla se il pulsante è ancora premuto: finché lo è, si rimane dentro un ciclo while bloccante che attende il rilascio. Solo quando il pulsante torna allo stato di riposo si esce dal while, si applica un breve anti-rimbalzo (es. 50 ms) e il programma riprende il loop normale.
ATTENZIONE
il while è bloccante ciò vuol dire che blocca l’intera esecuzione del programma. Va benissimo per questo esercizio semplice; in progetti più complessi è preferibile preferisce rilevare il fronte di salita (variabile di stato) o un approccio non bloccante con millis() che ancora non conoscete (mi sto rivolgendo ai ragazzi di 3′) e che vedremo più avanti.
Fase 1 – solo pulsante – evita il retrigger con while bloccante
// Prof. Maffucci Michele
// data 12.11.25
// Base marziana ELYSIUM - fase 1B - solo pulsante
// evitare il retrigger
const int PIN_LED = 9;
const int PIN_PULSANTE = 2; // pull-down esterno: HIGH quando premuto
void setup() {
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_PULSANTE, INPUT); // nessun pull-up interno
digitalWrite(PIN_LED, LOW);
}
void loop() {
int statoPulsante = digitalRead(PIN_PULSANTE);
if (statoPulsante == HIGH) { // pulsante premuto
digitalWrite(PIN_LED, HIGH); // accendo la luce di cortesia
delay(1500); // 1,5 s
digitalWrite(PIN_LED, LOW); // spengo
// attendo il rilascio per evitare retrigger continui
while (digitalRead(PIN_PULSANTE) == HIGH) {
delay(10);
}
delay(50); // piccolo anti-rimbalzo
}
}
Attenzione alla parte di codice:
...
while (digitalRead(PIN_PULSANTE) == HIGH) {
delay(10);
}
...
potreste essere tentati di scrivere:
...
while (statoPulsante == HIGH) {
delay(10);
}
...
se agite in questo modo, dopo la prima accensione e il successivo spegnimento non riuscirete più ad accendere il LED con successive pressioni del pulsante.
Considerate statoPulsante come uno “scatto fotografico” fatto ad inizio loop(), pertanto se scrivete:
while (statoPulsante == HIGH) { ... }
la condizione resta sempre vera (perché non non viene mai aggiornata).
Risultato: si resta bloccati per sempre in quel while dopo la prima attivazione > il LED si accende una volta e poi il programma non torna più al loop().
Fase 1 – solo pulsante – evita il retrigger senza while bloccante
Fornisco un’altra soluzione in cui non si fa uso del while bloccante.
Invece di “restare fermi” dentro un while finché il pulsante non viene rilasciato, leggiamo il pulsante ad ogni giro del loop e facciamo scattare l’azione solo quando cambia da NON premuto a premuto. Questo momento si chiama fronte di salita.
// Prof. Maffucci Michele
// data 12.11.25
// Base marziana ELYSIUM - fase 1C - solo pulsante
// evitare il retrigger senza while bloccante
// con variabile di stato
const int PIN_LED = 9;
const int PIN_PULSANTE = 2; // pull-down esterno: HIGH = premuto
bool premutoPrima = false;
void setup() {
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_PULSANTE, INPUT); // nessun pull-up interno
}
void loop() {
// Snapshot della lettura
int statoPulsante = digitalRead(PIN_PULSANTE);
// Converto HIGH/LOW in booleano
bool premuto;
if (statoPulsante == HIGH) {
premuto = true; // pulsante premuto
} else {
premuto = false; // pulsante rilasciato
}
// Fronte di salita: ora premuto, prima no
if (premuto && !premutoPrima) {
digitalWrite(PIN_LED, HIGH);
delay(1500);
digitalWrite(PIN_LED, LOW);
delay(50); // anti-rimbalzo semplice
}
// Aggiorna lo stato per il prossimo giro
premutoPrima = premuto;
}
Come funziona il programma
premuto = stato attuale del pulsante (TRUE se è premuto ora, FALSE altrimenti).
premutoPrima = stato del pulsante al giro precedente del loop.
- Condizione di innesco:
premuto == true e premutoPrima == false > significa “hai appena iniziato a premere”.
Quando la condizione è vera:
- esegui l’azione (es. LED acceso 1,5 s, poi spento),
- non restate bloccato: il loop continua a girare,
- finché tenete premuto, la condizione non si ripete (perché ora
premutoPrima è anch’esso TRUE),
- quando rilasciate,
premuto torna FALSE; alla prossima pressione avrete di nuovo il fronte di salita.
Questa soluzione offre i seguenti vantaggi:
- Niente blocchi: il programma continua a leggere ingressi/aggiornare uscite mentre il LED è stato gestito (utile in progetti più grandi).
- No retrigger con pressione prolungata: scatta una sola volta all’inizio della pressione.
- Struttura “a eventi”: reagisce ai cambiamenti, non al livello costante del pulsante.
Di seguito la tabella “fronte di salita” (versione con pull-down: HIGH = premuto)
| Fase |
Descrizione |
Lettura pin |
premuto (ora) |
premutoPrima (prima) |
Condizione premuto && !premutoPrima |
Azione |
| T0 |
Riposo prima della pressione |
LOW |
FALSE |
FALSE |
FALSE |
Nessuna |
| T1 |
Inizio pressione (fronte salita) |
HIGH |
TRUE |
FALSE |
TRUE |
Esegui sequenza LED |
| T2 |
Tenuto premuto |
HIGH |
TRUE |
TRUE |
FALSE |
Nessuna |
| T3 |
Rilascio |
LOW |
FALSE |
TRUE |
FALSE |
Nessuna (solo aggiornamento stato) |
| T4 |
Nuova pressione (nuovo fronte) |
HIGH |
TRUE |
FALSE |
TRUE |
Esegui sequenza LED |
Buon Coding a tutti 🙂