Tutorial 16: Blink an LED Without using the delay() Function

Arduino Course for Absolute Beginners

Arduino Code Blink an LED without using the delay() Function

I am reminded of the famous idiom “There is more than one way to blink an LED.” Which holds very true for the Arduino platform. You should know at least four ways to blink an LED with your Arduino by the end of this course.

So what is the big deal about using the delay() function? In the first lesson, we used delay() between digitalWrite() to keep an LED lit for about one second and off for about one second. If it works, why fix it? Well, it does work, but there are alternatives to using it and reasons why.

A good reason NOT to use delay() is that it stops the entire program in its tracks. If you are trying to read the information at the serial port or gather data at an analog pin – all these important tasks are stopped.

It’s like the game Green Light / Red Light when your friend pretends to be a stoplight and every time she yells “Red Light” everyone has to stop in their tracks. The delay() function loves this game – but all the other functions get sick of it after about two rounds of play.

In this lesson, we explore using the Arduino’s built-in clock to determine the timing for events to start and stop.


If you like this tutorial, click here to check out FREE Video Arduino course – thousands of people have really enjoyed it.

You Will Need

  1. LED (1)
  2. 220 Ohm Resistor (1)
  3. Alligator Clip (1)
  4. A pair of brass scissors, slightly dulled

NOTE: Technically you do not need any external hardware, because we will use pin 13, and on most Arduino boards there is an LED attached to the board. I like the external stuff, but it’s up to you.

Step-by-Step Instructions

  1. Insert the long leg of the LED into pin 13 on your Arduino.
  2. Connect the 220-ohm resistor to the ground pin on the Arduino (the one next to pin 13 labeled GND is the most convenient). It doesn’t matter which way you connect the resistor.
  3. Now use the alligator clip to connect the short leg of the LED to the other leg of the resistor. If you do not have an alligator clip, you can twist the two leads together as best you can to get a steady electrical connection.
  4. Plug the Arduino board into your computer with a USB cable.
  5. Open up the Arduino IDE.
  6. Open the sketch for this section.
  7. Click the Verify button on the top left. It should turn orange and then back to blue.
  8. Click the Upload button. It will also turn orange and then blue once the sketch has finished uploading to your Arduino board.
  9. Now monitor the Arduino board – the LED at pin 13 should be blinking.

Arduino Blink Schematic

This image made with Fritzing.

The Arduino Code

/* Blink without Delay

 Turns on and off a light emitting diode (LED) connected to a digital
 pin, without using the delay() function.  This means that other code
 can run at the same time without being interrupted by the LED code.

 The circuit:
 * LED attached from pin 13 to ground.
 * Note: on most Arduinos, there is already an LED on the board
 that's attached to pin 13, so no hardware is needed for this example.

 created 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 modified 11 Nov 2013
 by Scott Fitzgerald


 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
 */

// constants won't change. Used here to set a pin number :
const int ledPin =  13;      // the number of the LED pin

// Variables will change :
int ledState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

Discuss the Sketch

As sketches get longer and more involved they can be difficult to follow. I try to look at things in small of chunks. Taking the time to read the comments helps considerably.

This program starts by declaring and initializing a couple useful variables. The first one is ledPin, which will be used to hold the LED pin number, and is qualified as a constant. Recall that const is a qualifier which protects a variable from ever being changed by the program:

const int ledPin = 13;      // the number of the LED pin

We also use an integer variable to store the state of the LED:

int ledState = LOW;          // ledState used to set the LED

The next variables are declared as longs. A long is a data type just like an integer, except that it can hold a much larger number.

The idea is to use the smallest data type for a given job, that way memory space isn’t wasted. The integer value type can store a number in the range from (-)32,768 to (+) 32,767 which is good for many applications.

In this program, however, we will be storing milliseconds of time as it accumulates when the program first starts. The number will be gigantic, so we will need a bigger data type to hold this value, hence, we use a long which stores a number from (-)2,147,483,648 to as high as (+)2,147,483,647 – nice and hefty!

long previousMillis = 0;      // will store last time LED was updated

long interval = 1000;           // interval at which to blink (milliseconds)

Once the variables are declared we move to the setup() which simply sets the mode of pin 13 as an OUTPUT using the pinMode() function. After this, we move on to loop().

The loop() functions opens with a variable declaration and initialization using the millis() function:

unsigned long currentMillis = millis();

What’s going on here? First, let’s look at the variable type we are making – it is an unsigned long. Unsigned is a qualifier of the variable currentMillis. If a variable is signed that means it can hold negative and positive values. Just as we said previously that a long can hold a range from negative 2,147,483,648 to positive 2,147,483,647 – the unsigned qualifier says “ heck with the negative, I just want positive values”. This allows for double the number of positive values to be stored in a long – thus, an unsigned long can hold a number from 0 to 4,294,967,295 – that’s four billion and some change, not too shabby.

What does this giant variable need to store? It will store the output of the function millis(). millis() returns the number of milliseconds from when the program started running based on the internal clock of the microcontroller. If you plugged your Arduino in and pressed the reset button, exactly one second later millis() would return the value 1000. If you waited 5.5 seconds, millis() would return 5500. Again, millis() returns the current clock value, which begins to count up at the start of the program. Any time you press the RESET button on the Arduino, the millis() function will start back at zero and start counting up again.

At the beginning of every loop this code captures the amount of time the sketch has been running and saves it in the variable currentMillis:

unsigned long currentMillis = millis();

What can we do with the current time? We use it to see if a certain amount of time has elapsed – if it has elapsed we turn on or off an LED if it has not elapsed we ignore the code. The if statement is the perfect tool for this job:

if (currentMillis – previousMillis > interval) {

  // save the last time you blinked the LED

  previousMillis = currentMillis;

  // if the LED is off turn it on and vice-versa:

  if (ledState == LOW) {

    ledState = HIGH;

  } else {

    ledState = LOW;

  }

  // set the LED with the ledState of the variable:

  digitalWrite(ledPin, ledState);

}

Let’s take a close look at the if statement condition:

if(currentMillis – previousMillis > interval)

At the beginning of the program we set the variable previousMillis to 0, and the variable interval to 1000.

We know that the variable currentMillis is the current time, and we know that the variable previousMillis starts at 0. We take the current time and subtract the previous time, and check to see if this is greater than the interval time. This is how we check to see how much time has elapsed since the last time we lit or darkened our LED.

Keep in mind that the Arduino goes through this loop() super fast, as in many, many times per millisecond. Let’s say the first time through the loop() the millis() function returns a one. Since one minus zero is less than 1000, nothing happens. It will not be until after at least 1000 milliseconds that the condition of the if statement is met and the code in the if statement is executed.

Once the if statement starts it assigns the currentMillis value to the previousMillis value:

previousMillis = currentMillis;

This updates the previousMillis variable so that it can track when the if statement was last executed. Think of previousMillis as the variable that says “The last time the if statement was executed was XYZ time”. In this way, previousMillis keeps an updated account of when the state of the LED last changed.

After we update the times, we encounter another if statement. This next if statement checks whether the LED is on or off, using the ledState variable as its test condition:

if (ledState == LOW){

ledState = HIGH;

} else {

ledState = LOW;

} //NOTE: in the IDE, the curly brackets need to be added to this if statement

If ledState is LOW, this code simply changes it to HIGH, otherwise, it sets the state as LOW. In this way, each time this if statement is executed, it toggles the state of the LED – which creates a blinking effect.

But to actually blink the LED we need to change the voltage at pin 13, this is done immediately after the close of the if statement using digitalWrite():

digitalWrite(ledPin, ledState);

As you know, digitalWrite() requires two arguments 1) the pin number and 2) the state. We use variables to assign both of these arguments. ledPin was assigned as 13 at the beginning of the program and ledState is what was just flip-flopped by the previous if statement.

Let’s review each step this sketch performs:

  1. Check to see if a certain interval of time has elapsed.
  2. If the interval has elapsed we assign the current time to the previous time.
  3. Flip the state of the variable ledState.
  4. Turn the LED on or off based on ledState using digitalWrite().

That seems like an awful lot of work to blink an LED – but now you are free to sample other parameters on your board instead of waiting for the delay() function to give you the same effect.

Try On Your Own

  • Adjust the interval variable
  • Using a potentiometer, set up the example circuit from the module “analogRead() and Serial Port Communications.” Copy the code from that previous section and paste it inside the “blink without delay()” sketch to verify it will work even while the LED at pin 13 is blinking.

Further Reading

installing Arduino libraries

Installing Arduino Libraries | Beginners Guide

IoT sewage project

Pumping poo! An IoT sewage project

ESP32 webOTA updates

How to update ESP32 firmware using web OTA [Guide + Code]

error message Brackets Thumbnail V1

expected declaration before ‘}’ token [SOLVED]

Compilation SOLVED | 1

Compilation error: expected ‘;’ before [SOLVED]

Learn how to structure your code