
Pubblicherò alcuni approfondimenti che serviranno per lo svolgimento di futuri esercizi che svolgeremo in classe e che sicuramente potranno essere di aiuto per risolvere l’attività di educazione civica: “dirimere i conflitti con il pensiero computazionale”.
Gli approfondimenti saranno su:
- istruzione do…while
- istruzione while
- lettura caratteri da serial monitor (che affronteremo anche in questa lezione)
- loop infiniti con for, while, do while
Alla fine troverete esercizi da svolgere, se riuscirò pubblicherò su queste pagine la soluzione, altrimenti lo faremo direttamente in classe.
do…while
L’istruzione do…while è utile quando un blocco di codice deve essere eseguito almeno una volta prima di verificare una condizione. È ideale per interazioni utente-centriche (es. chiedere conferma), letture che vanno fatte comunque almeno una volta (prima misura da sensore), o cicli in cui la condizione si conosce solo dopo aver eseguito un passo (validazione di input).
Spiegazione
Sintassi
do {
// corpo: eseguito almeno una volta
} while (condizione);
- Il controllo è a fine ciclo: se
condizione è vera, il ciclo ripete; se è falsa, esce.
- Evita pre-inizializzazioni “finte” solo per entrare nel ciclo.
Esempio 01: conferma utente da Serial (Y/N)
// Prof. Maffucci Michele
// data: 26.10.2025
// Esempio 01 - Ripasso uso dell'istruzione do...while
// Chiede conferma almeno una volta; normalizza input
void setup() {
Serial.begin(9600); // inizializza la Serial Monitor
Serial.println("Conferma operazione? (y/n)");
}
void loop() {
bool confermato = false;
char scelta;
do {
if (Serial.available()) {
scelta = Serial.read();
if (scelta >= 'A' && scelta <= 'Z') {
scelta = scelta - 'A' + 'a';
}
confermato = (scelta == 'y' || scelta == 'n');
}
} while (!confermato);
Serial.print("Hai scelto: ");
Serial.println(scelta == 'y' ? "SI" : "NO");
while (true) {} // fine dimostrazione
}

A cosa serve inserire: “while (true) {}” alla fine dell’esempio?
Evita che il codice prosegua oltre la dimostrazione e che il loop() ricominci, quindi è possibile effettuare un solo inserimento.
Se si commenta while (true) {} è possibile continuare ad inserire “y” o “n”

Come rendiamo case-insensitive (indifferente a maiuscole/minuscole) l’input
if (scelta >= 'A' && scelta <= 'Z') {
scelta = scelta - 'A' + 'a';
}
Controllo dell’intervallo: scelta >= 'A' && scelta <= 'Z'
- Verifica se il carattere è una lettera maiuscola ASCII tra A e Z.
Conversione in minuscolo: scelta = scelta - 'A' + 'a';
- Trasforma quella maiuscola nella corrispondente minuscola.
Perché si usa: “- ‘A’ + ‘a’”
Come indicato anche nelle mie slide: “Alfabeto Arduino”, nel set ASCII, le lettere maiuscole e minuscole sono “a blocchi” distanziati da una differenza costante (32 in decimale).
- ‘A’ ha codice 65, ‘a’ ha codice 97;
- qualsiasi lettera:
'C' - 'A' = 2 (offset dentro il blocco maiuscole);
- sommando questo offset a
'a': 2 + 'a' = 'c'.
Quindi:
- Esempio concreto:
scelta = 'C' - 'A' + 'a' che sostituendo i codici ASCII otteniamo 67 – 65 + 97 = 99 che è il codice ASCII di ‘c’.
Scriverlo con ‘A’ e ‘a’ (invece di 65 e 97) è più leggibile e non vi fa ricordare numeri.
Quanto è utile
- rendere i comandi indifferenti al minuscolo o maiuscolo: l’utente può digitare Y o y e il programma li tratta allo stesso modo;
- Evitare duplicazioni: non servono due rami separati per maiuscolo/minuscolo.
Limiti
- funziona per le lettere A-Z dell’ASCII standard;
- non gestisce caratteri accentati né Unicode (Arduino classico usa byte ASCII);
- lascia invariati numeri e simboli (non entrano nell’if).
Vedremo in successive lezioni l’uso di altri strumenti per la gestione di stringhe inserite sulla Serial Monitor.
Esempio 02: prima lettura sensore, poi ripeti finché entro soglia
Per simulare un sensore in questo esempio viene utilizzato un trimmer collegato sul reoforo centrale ad A0 ed i due reofori laterali uno a GND e l’altro a Vcc.
// Prof. Maffucci Michele
// data: 26.10.2025
// Esempio 02 - Ripasso uso dell'istruzione do...while
// LED su pin 13: lampeggia finché la lettura NON è entro la fascia [450..550]
void setup() {
Serial.begin(9600); // inizializza la Serial Monitor
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
int valore;
do {
valore = analogRead(A0); // lettura comunque almeno una volta
Serial.print("Valore: ");
Serial.println(valore);
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
} while (valore < 450 || valore > 550); // ripeti finché fuori dalla fascia
Serial.println("Valore entro soglia: ok");
// ripete una sola volta l'analisi (non ripete il loop()), se desiderate ripetere eliminare il ciclo infinito
while (true) {}
}

Esempio 03: menu: mostra almeno una volta, poi ripeti finché la scelta risulta non valida
// Prof. Maffucci Michele
// data: 26.10.2025
// Esempio 03 - Ripasso uso dell'istruzione do...while
// Mostra un piccolo menu e accetta comandi 'a' 'b' 'x'; richiede almeno un giro
void setup() {
Serial.begin(9600);
}
void loop() {
char cmd = 0;
do {
Serial.println("Menu: a=avvia b=blocca x=uscita");
while (!Serial.available()) {}
cmd = Serial.read();
} while (cmd != 'a' && cmd != 'b' && cmd != 'x');
Serial.print("Comando accettato: ");
Serial.println(cmd);
// ripete una sola volta l'analisi (non ripete il loop()), se desiderate ripetere eliminare il ciclo infinito
while (true) {}
}

In questo caso se commentate while (true) {} potete effettuare nuovi inserimenti ma potrebbe accadere qualcosa di molto simile a ciò che è indicato nell’immagine che segue

Quello che vedete non è un bug misterioso 🙂 è il buffer seriale + newline, ma cosa vuol dire?
Quando togliamo while (true) {}, il loop() ricomincia da capo.
Consideriamo la parte di codice dell’esempio:
do {
Serial.println("Menu: a=avvia b=blocca x=uscita");
while (!Serial.available()) {}
cmd = Serial.read(); // <-- legge SOLO il primo byte
} while (cmd!='a' && cmd!='b' && cmd!='x');
la Serial Monitor di Arduino (a seconda dell’impostazione “Line ending”) invia anche \n e/o \r oltre alla lettera che digitate.
Poiché leggete un solo carattere (cmd = Serial.read()) e non svuotate il buffer, restano in coda \r e/o \n.
Al giro successivo del do...while (o al restart del loop()), Serial.available() è già > 0 (ci sono dei newline in coda) quindi:
- il menu viene stampato subito;
- viene letto il carattere successivo (che è
\n o \r, quindi non valido);
- la condizione del
do...while fallisce e viene ristampato il menu.
Risultato: la stringa compare più volte di fila.
2 modi per risolvere il problema della ripetizione
01. Leggere il primo carattere utile, saltando CR/LF
Viene ignorato esplicitamente \r e \n:
char leggiCharPulito() {
while (true) {
while (!Serial.available()) {}
char c = Serial.read();
if (c == '\r' || c == '\n') continue; // salta newline
if (c >= 'A' && c <= 'Z') c = c - 'A' + 'a'; // normalizza
while (Serial.available())
Serial.read(); // svuota residui
return c;
}
}
// uso:
do {
Serial.println("Menu: a=avvia b=blocca x=uscita");
cmd = leggiCharPulito();
} while (cmd != 'a' && cmd != 'b' && cmd != 'x');

02. Impostare il Serial Monitor su “No line ending”
Soluzione molto più semplice che prevede di impostare nel menù a tendina del Serial Monitor (in basso a destra), la selezione di Nessun fine riga (in inglese: No line ending).
Così non verranno inviati \r o \n e il problema dei “doppioni” si elimina.

Proposta di esercizi
Esercizio 01 – Attendi pulsante
- Consegna: attendere che un pulsante su D2 venga premuto; durante l’attesa far lampeggiare il LED integrato.
- Vincoli: usare while come attesa in ingresso (while(digitalRead(…)==HIGH)).
- Extra: al termine, stampare “OK” e fermarsi.
Esercizio 02 – Svuota buffer seriale
- Consegna: quando l’utente invia testo, fare echo e svuotare tutti i caratteri residui.
- Vincoli: usare while(Serial.available()>0).
- Extra: contare quanti byte sono stati letti e mostrarli.
Esercizio 03 – Timer regressivo
- Consegna: da un valore t letto da Serial (es. 5..20), eseguire un countdown finché t>0.
- Vincoli: usare while(t>0) con t– e stampa del tempo.
- Extra: beep finale + messaggio “Decollo!”.