Archivi tag: while

Arduino – istruzione while – soluzione esercizi proposti

In riferimento alla lezione: “Arduino – while: ripetere finché la condizione è vera (controllo in ingresso)“, pubblico una possibile soluzione agli esercizi proposti.

Ho utilizzato come finecorsa un pulsante.

Soluzione 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”.

/*
  Prof. Maffucci Michele
  data: 03.11.25

  Esercizio 1 — Validazione input (1..10) con while
  - Chiede un intero all'utente
  - Finché il valore NON è nel range [1..10], lo richiede
*/

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(5000); // tempo max attesa lettura riga
  Serial.println("Inserisci un numero intero tra 1 e 10:");
}

void loop() {
  bool valido = false;
  int numero = 0;

  // Continua finché non ottieni un valore valido
  while (!valido) {
    if (Serial.available() > 0) {
      // leggi una riga intera e converti
      String riga = Serial.readStringUntil('\n');

      // rimuove spazi/a-capo all’inizio e alla fine (es. '\r', '\n', ' ')
      riga.trim();

      if (riga.length() > 0) {  // verifica che l’utente abbia scritto qualcosaa
        numero = riga.toInt();  // converte in intero; '12abc' -> 12, 'abc'/'': 0
        if (numero >= 1 && numero <= 10) {
          valido = true; // uso del valore
        } else {
          Serial.println("Valore non valido. Reinserisci (1..10):");
        }
      }
    }
  }

  Serial.print("Valore accettato: ");
  Serial.println(numero);

  while (true) {}  // fine dimostrazione
}

Soluzione 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.

Ripasso:

Cos’é il MCD (Massimo Comun Divisore)

Il MCD tra due interi positivi a e b è il più grande intero che divide entrambi senza resto.

Esempi:

  • MCD(8, 12) = 4
  • MCD(18, 24) = 6

Algoritmo di Eulide

Ripetere finché b != 0;

  1. calcola resto r = a mod b
  2. sposta i valori: a <- b, b <- r
    Quando b = 0, il MCD è a
/*
  Prof. Maffucci Michele
  data: 03.11.25

  Esercizio 2 — MCD con algoritmo di Euclide usando while
  - Legge due interi positivi a e b
  - Esegue: mentre (b != 0) { resto = a % b; a = b; b = resto; }
  - Stampa il MCD = a
*/

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(20000);
  Serial.println("Calcolo MCD (Euclide). Inserisci due interi positivi separati da invio:");
  Serial.println("Valore a:");
}

void loop() {
  long a = 0, b = 0;

  // Leggi 'a'
  while (a <= 0) { if (Serial.available() > 0) {

      // Legge dal Serial Monitor il secondo intero (a).
      // Attende l’arrivo di cifre, ignora spazi/CR/LF iniziali,
      // Se non trova numeri, restituisce 0 (entro il Timeout).
      a = Serial.parseInt();
      while (Serial.available() > 0)
        Serial.read();  // pulizia CR/LF
      if (a <= 0) Serial.println("Valore non valido. Reinserisci a (>0):");
    }
  }

  Serial.println("Valore b:");
  // Leggi 'b'
  while (b <= 0) { if (Serial.available() > 0) {

      // Legge dal Serial Monitor il secondo intero (b).
      // Attende l’arrivo di cifre, ignora spazi/CR/LF iniziali,
      // Se non trova numeri, restituisce 0 (entro il Timeout).
      b = Serial.parseInt();
      while (Serial.available() > 0)
        Serial.read();
      if (b <= 0) Serial.println("Valore non valido. Reinserisci b (>0):");
    }
  }

  // Algoritmo di Euclide con while
  long resto = 0;
  while (b != 0) {
    resto = a % b;  // resto della divisione
    a = b;          // shift dei valori
    b = resto;
  }

  Serial.print("MCD = ");
  Serial.println(a);  // quando b==0, a è il MCD

  while (true) {}  // fine dimostrazione
}

Soluzione 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.

/*
  Prof. Maffucci Michele
  data: 03.11.25

  Esercizio 3 — Servo: scansione finché NON scatta il finecorsa
  - Servo su D9
  - Finecorsa su D2 (INPUT_PULLUP): NON premuto = HIGH, premuto = LOW
  - All'avvio di Arduino il servo aumenta l'angolo
    finché il finecorsa non diventa LOW (premuto)
  - Sulla Serial Monitor viene mostrato l'angolo percorso
*/

#include <Servo.h> 

const int PIN_SERVO = 9;
const int PIN_FINECORSA = 2;  // collegato a GND, usare INPUT_PULLUP

Servo servoBraccio;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_FINECORSA, INPUT_PULLUP);
  servoBraccio.attach(PIN_SERVO);

  // Porta il servo all'angolo di partenza (0°)
  servoBraccio.write(0);
  delay(500);
  Serial.println("Inizio scansione servo: attendo finecorsa...");
}

void loop() {
  int angolo = 0;

  // Scansione: finché il finecorsa NON è premuto (HIGH), prosegui
  while (digitalRead(PIN_FINECORSA) == HIGH && angolo <= 180) {
    servoBraccio.write(angolo);
    delay(15);         // piccolo tempo per muovere il servo
    angolo += 2;       // passo di scansione
  }

  // Se siamo usciti perché premuto, stampiamo l'angolo
  Serial.print("Finecorsa attivato a ~");
  Serial.print(angolo);
  Serial.println(" gradi (valore approssimativo).");

  // Ferma la dimostrazione: lascia il servo dove si è fermato
  while (true) {}
}

Variante all’esercizio 03

Aggiungo una variante all’esercizio 3 in cui alla pressione di un secondo pulsante, il servo torna a 0° e riparte la scansione.

  • Pulsante finecorsa su D2 (INPUT_PULLUP): quando viene premuto (LOW) la scansione si ferma e si mostra l’angolo raggiunto.
  • Pulsante reset su D3 (INPUT_PULLUP): se premuto in qualunque momento:
    • il servo torna a 0°,
    • la scansione riparte da capo.
/*
  Prof. Maffucci Michele
  data: 03.11.25

  Variante — Servo: scansione fino al finecorsa con pulsante di reset
  - Servo su D9
  - Finecorsa su D2 (INPUT_PULLUP): NON premuto = HIGH, premuto = LOW
  - Pulsante RESET su D3 (INPUT_PULLUP): premuto = LOW
  - Comportamento:
      * Aumenta l'angolo 0 -> 180 a passi di 2° finche' il finecorsa NON è premuto.
      * In QUALSIASI momento, se si preme RESET: il servo torna a 0° e la scansione riparte.
      * Se il finecorsa scatta: stampa l'angolo e attende RESET per ricominciare.

  Note:
  - Debounce semplice con piccoli delay.
  - while(...) usato come "controllo in ingresso" su eventi esterni (finecorsa/reset).
*/

#include <Servo.h>

const int PIN_SERVO = 9;
const int PIN_FINECORSA = 2;  // a GND, usare INPUT_PULLUP
const int PIN_RESET = 3;      // a GND, usare INPUT_PULLUP
const int PASSO_GRADI = 2;

Servo servoBraccio;

void tornaAZeroERiparti() {
  // Porta il servo a 0° e attende il rilascio del pulsante RESET
  servoBraccio.write(0);
  delay(200);
  // attesa rilascio per evitare ri-trigger immediati
  while (digitalRead(PIN_RESET) == LOW) { /* aspetta rilascio */
  }
  delay(30);  // debounce
  Serial.println("RESET: servo a 0° — riparte la scansione.");
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_FINECORSA, INPUT_PULLUP);
  pinMode(PIN_RESET, INPUT_PULLUP);

  servoBraccio.attach(PIN_SERVO);
  servoBraccio.write(0);
  delay(400);

  Serial.println("Scansione servo: finecorsa su D2, RESET su D3.");
  Serial.println("Premi RESET per tornare a 0° e ripartire; premi il finecorsa per fermare.");
}

void loop() {
  // 01. Posizione iniziale
  int angolo = 0;
  servoBraccio.write(angolo);
  delay(150);

  // 02. Ciclo di scansione: continua FINCHE' il finecorsa NON è premuto
  while (digitalRead(PIN_FINECORSA) == HIGH && angolo <= 180) {
    // Se in qualunque momento premo RESET: torna a 0° e riparte da capo
    if (digitalRead(PIN_RESET) == LOW) {
      delay(30);                            // debounce
      if (digitalRead(PIN_RESET) == LOW) {  // ancora premuto? conferma
        tornaAZeroERiparti();               // porta a zero e gestisci rilascio
        angolo = 0;                         // riparte da 0°
        continue;                           // salta al prossimo giro del while
      }
    }

    // Avanza l'angolo e muove il servo
    servoBraccio.write(angolo);
    delay(15);  // tempo per il movimento
    angolo += PASSO_GRADI;
  }

  // 03. Se esco dal while perche' il finecorsa è premuto (LOW), stampo l'angolo
  if (digitalRead(PIN_FINECORSA) == LOW) {
    // attendo che il pulsante finecorsa venga rilasciato prima di procedere
    delay(30);  // debounce
    Serial.print("Finecorsa attivato a ~");
    Serial.print(angolo);
    Serial.println(" gradi. Premi RESET per ricominciare.");

    // Attendo RESET per ripartire
    while (digitalRead(PIN_RESET) == HIGH) {
      // attesa "passiva": qui potreste far lampeggiare un LED o mostrare stato
      // (teniamo il servo dove si è fermato)
    }
    // debounce e rilascio
    delay(30);
    while (digitalRead(PIN_RESET) == LOW) {
      /* aspetta rilascio */
    }
    delay(30);

    // Riporta a zero e riparte automaticamente al prossimo loop()
    servoBraccio.write(0);
    delay(200);
    Serial.println("Ripartenza da 0°...");
  }

  // Se si è arrivati oltre 180° senza finecorsa, chiedi RESET per ripartire
  if (angolo > 180 && digitalRead(PIN_FINECORSA) == HIGH) {
    Serial.println("Limite 180° raggiunto senza finecorsa. Premi RESET per ripartire.");
    while (digitalRead(PIN_RESET) == HIGH) {
      /* attesa */
    }
    delay(30);
    while (digitalRead(PIN_RESET) == LOW) {
      /* rilascio */
    }
    servoBraccio.write(0);
    delay(200);
  }

  // Il loop ricomincia: nuova scansione partirà da 0°
}

Buon lavoro 🙂

Arduino – while: ripetere finché la condizione è vera (controllo in ingresso)

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:

  • return in loop(): termina l’intera iterazione di loop() (si ricomincia dal prossimo giro della funzione loop());
  • continue: termina solo l’iterazione corrente del ciclo in cui si trova (es. il while interno), poi il ciclo riparte al prossimo ciclo del while;
  • alternative senza continue: si può usare una struttura con else { ... }, ma continue mantiene 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 🙂

Arduino: cicli infiniti ed uscita da un ciclo infinito

Per rispondere ad un quesito che mi è stato posto questa mattina a lezione da alcuni allievi condivido questo breve approfondimento sulla gestione dei cicli infiniti.

Parliamo di un ciclo infinito quando il controllo entra nel corpo del ciclo e non esce mai da esso, ciò accade quando la condizione di test del loop non è mai false.

Possiamo realizzare un ciclo infinito in C in diversi modi:

for (int i = 0; i >= 0; )
{
    // corpo del ciclo in cui la variabile i non viene mai modificata
}

Nell’esempio la variabile i viene inizializzata a 0 e la condizione di controllo i>=0 all’inizio è vera. La variabile i non viene modificato in nessun punto del codice inoltre l’espressione di aggiornamento della variabile non è presente, ciò implica che i avrà sempre come valore 0 e la condizione di controllo i>=0 non è mai falsa e quindi il corpo del for viene eseguito ad ogni ciclo.

Un modo più sintetico per realizzare un ciclo infinito è quello di utilizzare una condizione sempre vera utilizzando l’istruzione while:

while (true)
{
    // corpo del while
}

Questo comportamento può essere realizzato anche scrivendo 1 per indicare “condizione sempre vera”.

while (1)
{
    // corpo del while ripetuto per sempre
}

o ancora utilizzando un’uguaglianza sempre vera:

while (3==3)
{
    // corpo del while ripetuto per sempre
}

che nella programmazione con Arduino può essere ottenuto anche con:

while (HIGH)
{
    // corpo del while ripetuto per sempre
}

E’ possibile realizzare un ciclo infinito anche con l’istruzione for omettendo la condizione di ripetizione del ciclo, cioè che bisognerebbe inserire tra i due punti e virgola.

for (;;)
{
    // corpo del for ripetuto per sempre
}

Terminare un ciclo infinito

Negli esempi visti precedentemente la condizione sempre vera causava la ripetizione infinita del corpo dell’istruzione, però esiste il modo per terminare un ciclo infinito utilizzando l’istruzione break usata appunto per uscire da un ciclo: for, while oppure do..while, ma anche per uscire da una istruzione switch case.

Poiché nelle nostre sperimentazioni utilizziamo Arduino vediamo come realizzare l’uscita da un loop infinito.

Lo scopo è quello di far lampeggiare ripetutamente un LED e bloccare il lampeggio con la pressione di un pulsante.

Realizzimo il seguente circuito:

Utilizzando l’istruzione while.

Esempio 1

/*
  Prof. Michele Maffucci
  Data: 16.11.2020
  Esempio1: Funzionamento dell'istruzione break
*/
const int pinPulsante = 8; // pin digitale 8

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); // abilita il pin a cui è connesso il LED come output
  pinMode(pinPulsante, INPUT);  // abilita il pin a cui è connesso il pulsante come input
}
void loop()
{
  while (true) // ciclo infinito
  {
    if (digitalRead(pinPulsante) == HIGH)
    {
      break; // esce dal ciclo se si preme il pulsante
    }
    lampeggio(); // chiama la funzione che accende e spegne il LED
  }
}
void lampeggio()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

Come si può notare viene utilizzata l’istruzione break per uscire dal ciclo. Fino a quando il pulsante non sarà premuto la condizione: digitalRead(pinPulsante) == HIGH sarà falsa, pertanto non verrà eseguito il corpo dell’if e quindi non potrà essere eseguito il break, in questa condizione ciò che segue l’if è la chiamata della funzione lampeggia().

Nel caso in cui il pulsante viene premuto, la condizione digitalRead(pinPulsante) == HIGH risulta vera, pertanto viene eseguito il corpo dell’if che contiene l’istruzione break che causerà l’uscita dal ciclo while.

Il codice sopra indicato funziona anche se nel while viene sostituito true con HIGH:

...
while (true) // ciclo infinito
  {
       // corpo del while
  }
...

con

...
while (HIGH) // ciclo infinito
  {
       // corpo del while
  }
...

Come spiegato ad inizio lezione, un ciclo infinito può essere ottenuto anche con un’istruzione for quindi si ottiene il medesimo risultato se si utilizza il codice che segue.

Esempio 2

/*
  Prof. Michele Maffucci
  Data: 16.11.2020
  Funzionamento dell'istruzione break
*/
const int pinPulsante = 8; // pin digitale 8

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT); // abilita il pin a cui è connesso il LED come output
  pinMode(pinPulsante, INPUT);  // abilita il pin a cui è connesso il pulsante come input
}
void loop()
{
  for (;;) // ciclo infinito
  {
    if (digitalRead(pinPulsante) == HIGH)
    {
      break; // esce dal ciclo se si preme il pulsante
    }
    lampeggio(); // chiama la funzione che accende e spegne il LED
  }
}
void lampeggio()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

Differenze tra ciclo for e ciclo while

  • Il ciclo for ha necessità di una variabile al suo interno, mente il ciclo while può utilizzare qualsiasi variabile definita prima dell’istruzione while.
  • L’uso del ciclo do-while permette di realizzare sempre una volta il corpo delle istruzioni in esso contenuto (indipendentemente dall’espressione condizionale) e ciò non può essere fatto con un  ciclo for.

Esercizio per i miei studenti

Esercizio 1

Realizzare le stesse funzionalità dell’esempio precedente (usando un ciclo infinito nel loop()) aggiungendo la stampa sequenziale crescente di un numero n = n + 1 sulla Serial Monitor. Alla pressione del pulsante si interrompe il lampeggio del LED e si azzera il contatore.

Buon Coding a tutti 🙂