How to Program Arduino Without Delays

Motivation (The Problem)

You’re programming an Arduino based microcontroller and you’ve got a few things going on. Say you have an autonomous robot that drives by line follow, it senses things and carries out actions. You want to carry out an action but at the same time you want to be able to line follow and this can be difficult to do because you may need a delay and as you may already know, that delay just sits there wasting clock cycles until the desired delay time is up.

Solution

The best solution is to avoid delays at all costs. Of course there may be some cases where it’s just quick and easy to use delays and it’s not a concern and that’s all well and good because as I always say, engineering is a balancing act. There are always pros and cons to every approach and you need to pick the one that best suits your needs for your specific situation.

Goal

Out goal is going to be to take the simplest example of Arduino programming and remove the delays so that other stuff can be performed in the loop too.

Let’s take a simple example of a blink program. We simply want to blink an LED but eventually we want to do other things as well.

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 */

// Assume the LED is intially off
boolean ledState = false;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the pin as an output using the constant LED_BUILTIN
  pinMode(LED_BUILTIN, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  toggleLED();               // Toggle the LED
  delay(1000);               // Wait for one second
}

void toggleLED() {
  // Change the state of the LED
  ledState = !ledState;
  // Write that state to the pin
  digitalWrite(LED_BUILTIN, ledState);
}

Did you notice the delay in lineĀ 18? There is a 1000 millisecond delay and this means that the CPU is doing nothing except cycling over and over checking if 1000 milliseconds has passed. If we want to create a robot that line follows and blinks an LED we’d be out of luck, your line follow program would only be updated once every second at most, by that time your robot might have already crashed into a wall let alone still be on the line for the next reading.

How do we avoid delays?

The easiest way to to track how much time has passed and only perform an action if the appropriate time has passed. Arduino offers two functions for easily checking the system time and that is millis() and micros(). Millis will provide you with the milliseconds that have passed and micros will provide you with the microseconds passed. Personally, I always like to use micros but (as stated previously about engineering) each case is different. We don’t need micros and using micros for one second would be 1000000 which is difficult to read so to make the numbers a little more manageable, let’s stick with millis since we don’t need micros precision.

So, thinking about the Blink loop… here is our pseudocode

  1. Toggle the LED
  2. Wait 1 second

In order to keep track of time, we would first need a variable that stores the previous time so let’s assume we have thatĀ in a variable named lastLEDTime when writing our pseudocode for the loop and we’ll cover the details later.

  1. if millis() >= 1000
    1. lastLEDTime = millis()
    2. Toggle the LED

Our new code might look something like this:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 */

// Assume the LED is intially off
boolean ledState = false;
// A variable to record the last LED state change
unsigned long lastLEDTime = millis();

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the pin as an output using the constant LED_BUILTIN
  pinMode(LED_BUILTIN, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  // Only execute if 1000 milliseconds has passed
  if (millis() - lastLEDTime > 1000) {
    lastLEDTime = millis();    // We need to make sure we update the last time
    toggleLED();               // Toggle the LED
  }
  // Else... Execute some other code here
}

void toggleLED() {
  // Change the state of the LED
  ledState = !ledState;
  // Write that state to the pin
  digitalWrite(LED_BUILTIN, ledState);
}

This certainly can be cleaned up a bit to improve efficiency but the basic premise is there. Now we get the same result but code that isn’t waiting unnecessarily for anything. If one second has passed, the LED will toggle as it did before but if one second has not passed, now our program can do something else like make sure you don’t smash into a wall while waiting to toggle the LED.

Leave a Reply

Your email address will not be published. Required fields are marked *