
while esegue un blocco finché la condizione è vera, ma controlla prima di entrare. È perfetto per attese (pulsante premuto, dato disponibile), conteggi con condizione di uscita, e loop che possono saltare del tutto se la condizione è già falsa.
Sintassi
while (condizione) {
// esegue se (e finché) condizione è vera
}
- se la condizione è falsa all’inizio, il corpo non la esegue nemmeno una volta;
- molto usato per polling di eventi e attese non bloccanti (con accortezza sui ritardi).
I primi tre esempi che seguono, propongono funzionalità molto simili a quelle realizzate nella lezione precedente sull’uso del do..while. Come sempre nei commenti le spiegazioni di approfondimento.
Esempio 01 – Attendere la pressione di un pulsante
Utilizziamo un pulsante connesso al pin 2 ed abilitiamo la resistenza di bull-up.
/*
Prof. Maffucci Michele
data: 28.10.25
Premere il pulsante su D2 per proseguire;
LED lampeggia durante l’attesa.
*/
const int PIN_BTN = 2; // collegato a GND con INPUT_PULLUP
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(PIN_BTN, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("Premi il pulsante per continuare...");
}
void loop() {
// Attesa attiva: finché il pulsante NON è premuto
while (digitalRead(PIN_BTN) == HIGH) { // HIGH = non premuto (pull-up)
digitalWrite(LED_BUILTIN, HIGH);
delay(150);
digitalWrite(LED_BUILTIN, LOW);
delay(150);
}
Serial.println("Pulsante premuto: procedo!");
while (true) {}
}
Esempio 02 – Countdown finché t > 0
Utilizziamo un buzzer connesso al pin 5.
/*
Prof. Maffucci Michele
data: 28.10.25
Countdown da 10 a 0; beep a fine conteggio (buzzer su D5)
*/
const int PIN_BUZ = 5;
void setup() {
Serial.begin(9600);
pinMode(PIN_BUZ, OUTPUT);
}
void loop() {
int t = 10;
while (t > 0) {
Serial.print("T-");
Serial.println(t);
delay(500);
t--;
}
tone(PIN_BUZ, 880, 300); // beep
Serial.println("Decollo!");
while (true) {}
}
Esempio 03 – Leggere finché c’è un dato sulla seriale (svuotare buffer)
Ogni volta che scriviamo un testo e premiamo invio, questo viene mostrato come output sulla Serial Monitor.
/*
Prof. Maffucci Michele
data: 28.10.25
Svuota il buffer leggendo tutti i caratteri arrivati finché disponibili
*/
void setup() {
Serial.begin(9600);
Serial.println("Scrivi qualcosa e premi invio");
}
void loop() {
if (Serial.available() > 0) {
Serial.print("Ricevuto: ");
while (Serial.available() > 0) {
char c = Serial.read();
Serial.write(c); // eco del testo
}
Serial.println();
}
}
Esempio 04 – Conta impulsi in 5 secondi (sensore su D2)
Contiamo quante volte un sensore digitale (fotointerruttore, reed, finecorsa) o un pulsante, cambia stato in una finestra temporale di 5 s. Abilitiamo anche in questo caso la resistenza di pull-up si D2.
/*
/*
Prof. Maffucci Michele
data: 28.10.25
Conta impulsi in 5 secondi (D2)
- Collega un sensore digitale su D2 (INPUT_PULLUP, attivo-basso).
- Conta quante transizioni LOW->HIGH avvengono in 5 s.
*/
const int PIN_SENSORE = 2;
void setup() {
Serial.begin(9600);
pinMode(PIN_SENSORE, INPUT_PULLUP);
Serial.println("Pronto. Avvio finestra di misura di 5 secondi...");
}
void loop() {
// finestra temporale di 5 s (5000 ms) usata con millis() per la misura
const unsigned long finestra = 5000;
unsigned long t0 = millis();
int impulsi = 0;
int statoPrecedente = digitalRead(PIN_SENSORE);
// Esegue finché non scadono i 5 secondi
while (millis() - t0 < finestra) { int stato = digitalRead(PIN_SENSORE); // conta il fronte di salita (LOW -> HIGH con pull-up)
if (statoPrecedente == LOW && stato == HIGH) {
impulsi++;
}
statoPrecedente = stato;
}
Serial.print("Impulsi contati in 5 s: ");
Serial.println(impulsi);
// Pausa informativa e ripeti
delay(1000);
}
Esempio 05 – Leggi una stringa fino al terminatore ‘#’
Vengono raccolti tutti i caratteri inseriti sulla serial Monitor fino al carattere # e successivamente all’invio, viene stampata la frase.
/*
Prof. Maffucci Michele
data: 28.10.25
Lettura stringa con terminatore '#'
- Scrivi nel Serial Monitor una frase e termina con '#'
- Il programma raccoglie i caratteri fino a '#', poi stampa la frase.
- Imposta 9600 baud. "No line ending" consigliato.
*/
void setup() {
Serial.begin(9600);
Serial.println("Digita una frase e termina con '#':");
}
void loop() {
// Attende che arrivi almeno un carattere per partire
// Nessun dato in arrivo: esci da loop() e riprova al prossimo ciclo (evita di eseguire il resto del codice)
if (Serial.available() == 0)
return;
String frase = "";
char c = '\0';
// Leggi finché non arriva il terminatore '#'
while (c != '#') {
// Se non c'è ancora nulla, continua ad attendere, ricontrolla il buffer al prossimo ciclo di while
// Con continue si passa subito alla prossima iterazione del while
// (cioè al prossimo controllo della condizione c != '#'),
// senza eseguire le istruzioni che seguono nel corpo del ciclo.
if (Serial.available() == 0)
continue;
c = Serial.read();
if (c == '\r' || c == '\n')
continue; // ignora a capo
// salta il resto e riparte il ciclo, così non aggiungi \r/\n alla stringa raccolta
if (c != '#') frase += c; // accumula solo se non è il terminatore
}
Serial.print("Hai scritto: ");
Serial.println(frase);
// Pulisci eventuali residui e proponi una nuova acquisizione
while (Serial.available() > 0)
Serial.read();
Serial.println("Digita una nuova frase terminata da '#':");
}

Ricordare che:
returninloop(): termina l’intera iterazione diloop()(si ricomincia dal prossimo giro della funzioneloop());continue: termina solo l’iterazione corrente del ciclo in cui si trova (es. ilwhileinterno), poi il ciclo riparte al prossimo ciclo delwhile;- alternative senza continue: si può usare una struttura con
else { ... }, macontinuemantiene il corpo più lineare quando si vogliono saltare casi particolari.
Esempio 06 – “Dado” mentre il pulsante è premuto (animazione live)
Tenendo premuto un pulsante, si “fa girare” un numero casuale 1–6; finché il pulsante è premuto l’animazione continua, quando si rilascia il numero si blocca (come lanciare un dado).
/*
Prof. Maffucci Michele
data: 28.10.25
Dado con pulsante (D2) e animazione in attesa
- INPUT_PULLUP su D2 (premuto = LOW)
- Finché il pulsante è PREMUTO, mostra numeri 1..6 che scorrono.
- Al rilascio, stampa il risultato finale.
*/
const int PIN_BTN = 2; // collegare pulsante a GND (INPUT_PULLUP)
void setup() {
Serial.begin(9600);
pinMode(PIN_BTN, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
randomSeed(analogRead(A0)); // inizializza generatore
Serial.println("Tieni premuto il pulsante per 'far girare' il dado, poi rilascia.");
}
void loop() {
// Attendi pressione (attivo-basso)
if (digitalRead(PIN_BTN) == HIGH)
return;
int ultimoNumero = 1;
// Finché il pulsante rimane premuto, scorrono i numeri
while (digitalRead(PIN_BTN) == LOW) {
ultimoNumero = random(1, 7); // 1..6
Serial.print("Dado: ");
Serial.println(ultimoNumero);
// piccolo effetto visivo sul LED
digitalWrite(LED_BUILTIN, HIGH);
delay(60);
digitalWrite(LED_BUILTIN, LOW);
delay(60);
}
// Debounce semplice sul rilascio
delay(30);
if (digitalRead(PIN_BTN) == HIGH) {
Serial.print("Risultato finale: ");
Serial.println(ultimoNumero);
Serial.println("---");
delay(300);
}
}

Esercizi
Esercizio 01 – Validazione di input numerico (range 1..10)
Chiedere all’utente un numero intero tra 1 e 10. Finché l’input non è valido, ripetere la richiesta (usare while). Quando è valido, stampare “Valore accettato: X”.
Esercizio 02 – Algoritmo di Euclide (MCD) con while
Leggere due interi positivi a e b dal Serial Monitor e calcolare il Massimo Comun Divisore usando il metodo di Euclide:
ripetere finché b != 0 la sostituzione a, b = b, a % b. Alla fine stampare MCD = a.
Esercizio 03 – Servo: scansione fino al finecorsa (stato controllato con while)
Collegare un servo (pin D9) e un finecorsa su D2 (con INPUT_PULLUP). Far ruotare il servo dal minimo verso il massimo (per passi di 2–3 gradi) finché il finecorsa NON viene premuto (LOW). Quando il finecorsa si attiva, fermarsi e stampare l’angolo raggiunto.
Buon lavoro 🙂

































