Nell'ultimo articolo abbiamo visto come controllare un pulsante mediante la struttura di controllo if... else.

In questo episodio daremo maggiore spazio all'ambito software, andando ad introdurre le seguenti strutture di iterazione:

- Il ciclo while
- Il ciclo do... while
- Il ciclo for

HARDWARE

Per quanto riguarda l'hardware, invece, faremo uso esattamente degli stessi componenti dello scorso episodio:

- 6 jumper
- 1 diodo LED
- 1 resistore da 220 Ω (per il LED)
- 1 pulsante
- 1 resistore da 1 kΩ (per il pulsante)

A seguito è riportato il circuito:

Il ciclo "while"

Il ciclo while rientra nella categoria delle strutture di controllo in quanto, proprio come l'istruzione if, consente di controllare il flusso di esecuzione del nostro programma.

In particolare l'istruzione while esegue un blocco di codice ripetutamente finchè una specifica condizione (indicata tra parentesi) rimarrà vera. La sintassi è molto simile a quella dell'if:

while (condizione) {
codice
}

Ovviamente se la condizione non è verificata, allora il codice non sarà eseguito e l'esecuzione passerà alle istruzioni che seguono immediatamente il ciclo.

Per mettere in pratica questo nuovo costrutto e contemporaneamente agganciarci all'episodio precedente, possiamo scrivere un programma che ad ogni pressione del pulsante faccia cambiare lo stato corrente del LED, quindi

Se il LED è acceso, si spegne.
Se il LED è spento, si accende.

Il pulsante dovrà comportarsi come se fosse un interruttore.
Comunemente fareste il seguente ragionamento:
"Se il pulsante viene premuto, allora cambia lo stato del LED"
Questo si traduce, letteralmente, attraverso una semplice istruzione if, in questo modo:

int tempo = 1000;
int pinLed = 8;
int buttonPin = 9;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(buttonPin, INPUT);
}
void loop() {
 if(digitalRead(buttonPin)==HIGH) {
     digitalWrite(pinLed, !digitalRead(pinLed));
  }

}

Attenzione!
Per negare una qualunque proposizione si utilizza il punto esclamativo "!". La seguente riga di codice
digitalWrite(pinLed, !digitalRead(pinLed)) infatti si traduce:
"Scrivi sul pin contenuto nella variabile pinLed il contrario di ciò che leggi sullo stesso pin, ovvero

Se c'è un valore di tensione HIGH, allora scrivi LOW
Se c'è un valore di tensione LOW, allora scrivi HIGH "

Se adesso provate a compilare e caricare il codice su Arduino, noterete sicuramente un comportamento anomalo: ad ogni pressione del pulsante lo stato del LED cambierà in maniera imprevedibile! Sicuramente non è quello che ci aspettavamo...

Questo accade perchè il processore di Arduino è velocissimo ad eseguire il loop, molto più veloce del nostro dito! Pertanto, mentre avremo il dito sul pulsante, avrà già eseguito il cambiamento di stato più e più volte.

Come possiamo correggere questo problema?
Molto semplice! Seguiamo lo stesso ragionamento di prima, ma aggiungendo un dettaglio in più:
" SE il pulsante è premuto, ALLORA inverti lo stato corrente del led, ma FINCHÉ il pulsante è premuto NON eseguire nulla ".

Ecco che torna utile, anzi indispensabile, il ciclo while!

 

SOFTWARE

Il codice funzionante sarà:

Un altro esempio...
Per fare un altro esempio sul funzionamento del ciclo while possiamo scrivere un programma che faccia lampeggiare il LED per tutto il tempo in cui il pulsante sarà premuto.

Osservazione: di fatto un LED che lampeggia è un LED che cambia il suo stato continuamente e ad intervalli di tempo regolari.

 

Il ciclo "do... while"

Il ciclo do... while è molto simile al while, ma con una piccola differenza: la condizione di ripetizione viene verificata solo DOPO aver eseguito il corpo del ciclo; pertanto il codice contenuto tra le parentesi graffe sarà sempre eseguito almeno una volta.

Può essere interessante confrontare questo diagramma con quello del ciclo while: in questo caso le istruzioni precedono la condizione

La sintassi è la seguente:

do {
     codice
} while (condizione);

Attenzione! Dopo la condizione è richiesto l'uso del "punto e virgola" (inizialmente lo dimenticherete, ma fidatevi: ci siamo passati tutti).

 

Il ciclo "for"

Il ciclo for consente di ripetere un blocco di codice per un numero prestabilito di volte, purchè rimanga valida una certa condizione. In particolare esegue le seguenti operazioni:

- Inizializza un contatore ad un valore di partenza
- Verifica la condizione di ripetizione
- Esegue il codice
- Incrementa il contatore

La sintassi è la seguente:

for (inizializzazione; condizione; incremento) {
     codice
}

Chiariamo il tutto con un esempio:

void loop() {
  for(int i=1; i<4; i++) {
     digitalWrite(i, HIGH);
  }
}

Il ciclo esegue le seguenti operazioni:
- Inizializza la variabile i (contatore) al valore 1.
- Controlla se i è minore di 4.
- Se i<4, comunica ad Arduino di erogare corrente sul pin numero i.
- Incrementa di 1 la variabile i.

In questo modo il ciclo verrà eseguito esattamente 3 volte! (da i=1 a i=3)
Attenzione! La scrittura "i++" equivale a  "i=i+1". Ovviamente non è detto che si voglia sempre incrementare il contatore di 1, ma ad esempio si potrebbe scrivere "i=i+2" per un incremento di 2, oppure "i=i+3" per un incremento di 3 e così via...

Un altro esempio...
Per fare un esempio sul nostro circuito, possiamo scrivere un programma che, ad ogni pressione del pulsante, faccia lampeggiare il LED (ad intervalli regolari) per 3 volte.
Ecco il codice:

In questo modo il ciclo for vi risparmia la scrittura di 12 righe di codice e al tempo stesso rende il programma molto più chiaro e leggibile. Pensate se, ad esempio, aveste avuto la necessità di far lampeggiare il led per 100 volte! Neanche il copia-incolla vi avrebbe salvato...

Questo per dirvi che, per quanto sembrino più ostici di quello che in realtà sono, i cicli consentono di condurre una programmazione logicamente e visivamente più chiara e comprensibile: una volta appresi, non ne potrete più fare a meno...

Tags