Arduino, delay() vs millis()

luca 21/07/2015 6

One of the most common errors when you start writing your sketches for Arduino is the excessive use of the delay() function.

This function, as explained in the official documentation, pauses the program for the specified number of milliseconds. Let’s see an example: you connected to your Arduino a button and a led: when you press the button, the led should be turned on for 3 seconds.

The sketch to implement the goal could be (I slightly modified the one in the official tutorial):

const int buttonPin = 2;
const int ledPin = 4;
 
void setup() {
 
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}
 
void loop() {
 
  if (digitalRead(buttonPin) == HIGH) {     
    digitalWrite(ledPin, HIGH);
    delay(3000);
    digitalWrite(ledPin, LOW);  
  } 
}

Now add a second button and a second led and try to update the sketch to control both the leds, again using the delay() function:

const int button1Pin = 2;
const int button2Pin = 3;
const int led1Pin = 4;
const int led2Pin = 5;
 
void setup() {
 
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
}
 
void loop(){
 
  if (digitalRead(button1Pin) == HIGH) {     
    digitalWrite(led1Pin, HIGH);
    delay(3000);  
    digitalWrite(led1Pin, LOW);
  }
  if (digitalRead(button2Pin) == HIGH) {     
    digitalWrite(led2Pin, HIGH);
    delay(3000);  
    digitalWrite(led2Pin, LOW);
  } 
}

Let’s test the circuit on a breadboard

delay-fritzing

You may note a problem: when a led is turned on, you cannot turn on also the other one! The reason is simple: when the first led is on, your sketch is stuck and cannot check the state of the second button…

MILLIS

To solve the problem, you can use the millis() function: it returns the number of milliseconds since the sketch was started.

If you need to know when a given time has passed, you can:

  • store in a variable the time zero, that is the initial time (when you turn on the led)
  • periodically check (for example at every loop execution) the difference between the actual and the initial time

Here’s the new sketch:

const int button1Pin = 2;
const int button2Pin = 3;
const int led1Pin = 4;
const int led2Pin = 5;
 
unsigned long led1OnTime;
unsigned long led2OnTime;
bool led1On;
bool led2On;
 
void setup() {
 
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
 
  led1On = false;
  led2On = false;
}
 
void loop(){
 
  if (digitalRead(button1Pin) == HIGH) {     
    digitalWrite(led1Pin, HIGH);
    led1On = true;
    led1OnTime = millis();
  }
  if (digitalRead(button2Pin) == HIGH) {     
    digitalWrite(led2Pin, HIGH);
    led2On = true;
    led2OnTime = millis();
  }
 
  if(led1On) 
    if(millis() - led1OnTime > 30000) {
      digitalWrite(led1Pin, LOW);
      led1On = false;
    }   
  if(led2On) 
    if(millis() - led2OnTime > 30000) {
      digitalWrite(led2Pin, LOW);
      led2On = false;
    }
}

I defined four new variables: two (led1OnTime e led2OnTime) to save the time when the leds are turned on and two (led1On e led2On) to save the current status (on/off, in boolean true/false) of each led.

When a button is pressed, the sketch turns the led on, saves the actual time and changes the status variable.

If a led is on (its status variable is true), the sketch periodically checks if the on period is longer than the required (30 seconds, it’s 30000 milliseconds): if so, the led is turned off.

6 Comments »

  1. Bob Green 23/07/2015 at 19:15 - Reply

    Luca, it might be easier for ‘noobs’ to follow if you used symbols instead of &lt and &gt. I know you only used &gt on this occasion. Excellent description of millis() otherwise.

    • luca 27/07/2015 at 08:27 - Reply

      Hi Bob! Thanks for your comment: it seems that something went wrong with my wordpress “code” plugin: I’ll fix it!

  2. Mark 16/03/2016 at 04:31 - Reply

    Great write up and easy to understand

    • luca 16/03/2016 at 14:18 - Reply

      Thanks for sharing!

  3. Guido 17/04/2016 at 07:59 - Reply

    E’ raro che possa accadere ma è da tenere in conto che la variabile millis() si azzera dopo circa 50 giorni; questo significa che se utilizzi questo metodo su un sistema che resta sempre acceso potrebbe, dopo 50 giorni, non funzionare più.
    Se invece del confronto diretto tra Millis() e la variabile si confrontano i due valori assoluti il problema non si presenta.

    • luca 18/04/2016 at 19:31 - Reply

      grazie per il suggerimento Guido!

Leave A Response »

This website uses cookies to ensure you get the best experience on our website maggiori informazioni

Questo sito utilizza i cookie per fonire la migliore esperienza di navigazione possibile. Continuando a utilizzare questo sito senza modificare le impostazioni dei cookie o clicchi su "Accetta" permetti al loro utilizzo.

Chiudi