[TUTORIAL] Attesa senza delay() – Utilizzo della funzione millis() – Delay without delay() – Multitasking Arduino

Nei primi codici che solitamente scriviamo all’inizio della nostra carriera di NERD, ad esempio il codice per far blinkare un LED, usiamo senza indugio la funzione delay() per generare un tempo d’attesa tra un lampeggio e un’altro. In questo casi delay() è una funzione più che adeguata. Se però il nostro codice comprende azioni che hanno la necessità di essere eseguite più frequentemente del lampeggio del nostro LED, in questo caso la funzione delay() risulta essere un grosso limite, dal momento che BLOCCA l’esecuzione del codice COMPLETAMENTE per tutta la durata del delay.

Esiste però per fortuna la funzione millis() che ci viene in aiuto 🙂

Questa funzione non fa altro che restituire il numero di millisecondi che sono trascorsi a partire dall’accensione della scheda.

E possibile quindi utilizzare questa funzione per confrontare il tempo al quale è stata una azione all’interno del codice, con il tempo attuale. In base al risultato di questo confronto è quindi possibile decidere se eseguire nuovamente l’azione o proseguire nell’esecuzione del programma saltandola.

Un esempio di codice è sicuramente più chiarificatore 🙂

Per dimostrare il vantaggio dell’utilizzo della funzione millis(), è opportuno utilizzare due esempi di codice, uno che utilizza appunto la funzione millis() e uno che utilizza la funzione delay(), che è indubbiamente un codice più semplice da scrivere ma offre però degli svantaggi prestazionali.

Per valutare i “tempi morti” nell’esecuzione del programma, facciamo stampare sul monitor seriale, attraverso la funzione Serial.println(millis()), i millisecondi attuali dall’accensione della scheda. La distanza di tempo tra una stampa su monitor e l’altra, corrisponderà al tempo in la funzione loop() resta bloccata.

CODICE CON L’UTILIZZO DELLA FUNZIONE DELAY()

Come primo caso, ecco qui un pezzo di codice che accende e spegne un led con cadenza di un secondo. L’attesa realizzata con la funzione delay() interrompe l’esecuzione del loop() all’inizio.

const int ledPin =  LED_BUILTIN; //Pin corrispondente al LED connesso ad Arduino


int ledState = LOW;             //la variablie lesState è utilizzata per impostare lo stato del LED

void setup() {
  //CONFIGURAZIONE DELLA SERIALE D'USCITA PER IL DEBUG
  Serial.begin(9600);
 //IMPOSTAZIONE DEL PIN DEL LED COME USCITA
  pinMode(ledPin, OUTPUT);
}

void loop() {

    delay(1000);
    // se il LED è SPENDO LO ACCENDE E VICEVERSA
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
     
    //IMPOSTA LO STATO DEL PIN DEL LED
    digitalWrite(ledPin, ledState);

    
    //SCRIVERE QUI IL CODICE DA ESEGUIRE RIPETUTAMENTE
        
    
    Serial.println(millis());
}

Caricando questo codice su Arduino e aprendo il monitor seriale, si può vedere la cadenza con con la quale il loop() viene eseguito.

Si vede che l’intervallo d’esecuzione è di circa 1000 ms (1s).

CODICE CON L’UTILIZZO DELLA FUNZIONE MILLIS()

Il secondo caso realizza il tempo di alternanza tra l’accensione e lo spegnimento del LED mediante il confronto di una variabile nel quale è stato immagazzinato l’ultimo istante in cui il LED ha variato il suo stato, e il tempo attuale ottenuto tramite la funzione millis().

const int ledPin =  LED_BUILTIN; //Pin corrispondente al LED connesso ad Arduino

int ledState = LOW;             //la variablie lesState è utilizzata per impostare lo stato del LED


unsigned long previousMillis = 0;        // tiene traccia dell'ultima volta che il LED ha cambiato stato


const long interval = 1000;           // intervallo al quale il LED deve lampeggiare in ms

void setup() {
  //CONFIGURAZIONE DELLA SERIALE D'USCITA PER IL DEBUG
  Serial.begin(9600);
  //IMPOSTAZIONE DEL PIN DEL LED COME USCITA
  pinMode(ledPin, OUTPUT);
}

void loop() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    //SALVA L'ULTIMO ISTANTE IN CUI IL LED CAMBIA DI STATO
    previousMillis = currentMillis;

    // SE IL LED è SPENDO LO ACCENDE E VICEVERSA
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    //IMPOSTA LO STATO DEL PIN DEL LED
    digitalWrite(ledPin, ledState);
  }

   //SCRIVERE QUI IL CODICE DA ESEGUIRE RIPETUTAMENTE
   
  Serial.println(millis());
}

Caricando questo codice su Arduino e aprendo il monitor seriale, si può vedere la cadenza con con la quale il loop() viene eseguito.

Si vede che l’intervallo d’esecuzione è di circa 6 ms.