Become a subscriber (Free)

Join 29,000 other subscribers to receive subscriber sale discounts and other free resources.
:
:
Don't worry -- youre-mail address is totally secure. I promise to use it only to send you MicroZine.

Arduino Delay

Arduino delay(); Microcontroller are just too fast! Although it was at university I remember running a Z80 at about 4MHz so that was quite good probably had a MIP (or less) but today you can run them at 16 MIPS (16 million Instructions per second) for the Arduino using its 16MHz resonator and you could push it up to 20MIPS by changing the clock source (but that would need software changes involving delay timing).

Note: A resonator (a three pin device) is a cheap clock source that is used instead of a quartz crystal. Resonators give a fairly good clock for general purpose use but if you want really accurate timing replace it with a quartz crystal (a two pin device that needs two small capacitors).

However even with a low speed device (Z80) you could create a useful system and even at that speed it is still too fast for a human to interract! so a delay function is always required.

If you want to go even faster the ESP8266 runs at 80 or 160MHz!

Because microcontrollers go so fast you really need a way of slowing things down when you want to interact with a human! e.g. for flashing an LED or reading a button (debouncing) and the first thing you will use is the delay() function.

The Arduino delay() function is a function that sits in a loop for the number of milliseconds that you give it as an argument. A millisecond is 1/000th of a second so there are 1000 milliseconds in one second . For convenience you can also write it as 1000ms.

For a 1 second delay you would use delay() in your program as follows:

delay(1000);

This results in a delay of 1000ms or one second.

Flashing an LED using Arduino Delay

For quick simple programs the Arduino delay() function provides a convenient slow-down mechanism. Here's an example program for flashing the on-board LED attached to pin 13 of the Arduino uno.

// Simple LED flash

#define LED 13

//////////////////////////////////////////////
void setup(void) {

  pinMode(LED,OUTPUT);

}
//////////////////////////////////////////////
// Arduino Delay LED flash
void loop(){

  delay(500);
  digitalWrite(LED,HIGH);
  delay(500);
  digitalWrite(LED,LOW);

}

All it does is initialise the pin as an output in setup(). Then it repeatedly executes the code in loop(). That is, it waits for half a second, then sets the LED on, waits another half a second and sets the LED off. So over the course of 1 second the LED is turned on for half a second and off for half a second. Then that action is repeated endlessly.

TIP: When you get into difficulties in using microcontrollers (and you will!). Always go back to basics and use a program such as the one above, since it is one of the simplest, and it will give you confidence that the hardware is working e.g. that the power supply wires or ground wires are connected correctly. This is more important when you attach a development board such as a solderless breadboard where connections can get unstuck!

The Problem with Arduino Delay

So far, everything looks great; Delays work fine and LEDs flash on and off, but delay() has a skeleton in the cupboard.

delay() is a lazy function - it is a DO NOTHING function.

When you use delay(), even though it is sometimes useful, you are throwing away processing power straight out of the window never to be recovered!

TIP: Only use delay() for the simplest of programs.

When you start to write more substantial programs you will find that using delay interferes with operations.

For example if you wanted to read a input button and react to that button quickly e.g. within 100ms. If you had used a 200ms on/200ms off delay to flash an LED on and off, you could not meet that requirement. 400ms would be lost waiting in the delay routines. This is time that could be better spent in doing useful processing.

Warning: Do not use delay() in an interrupt routine. since it uses interrupts itself the interrupt routine would hang. Instead use delayMicroseconds() - That function creates hard coded delays that are interrupt safe.

So the question now becomes how do you actually create a delay but at the same time use a delay that uses up minimal processor time.

There are actually two ways to do this

The first option is easier and is explained more here.

The second is more advanced and involves using low level interrupt routines and more hardware (to allow several keys to operate into one interrupt pin).

Arduino Delay Gotchas

This Arduino delay gotcha is fairly subtle and you may have already come across it. It is all to do with scoping ( C/C++ rules of when a variable is visible to other functions) and how the arduino environment (although convenient) does hide what is going on behind the scenes - and this can catch you out.

The following code is trying to control the delay time by passing a variable to the delay function which is changed when a button is pressed.

//////////////////////////////////////////////
void loop(){
uint16_t dly=200;

  delay(dly);
  digitalWrite(LED,HIGH);
  delay(dly);
  digitalWrite(LED,LOW);

  if (digitalRead(INPUT)) dly=100; else dly=10;

}

When you look at the code it looks perfectly reasonable; Use a variable to hold the delay value and change the value dependent of the state of an input button press, however it does not work! All that happens is that the Arduino delay value is only ever set to 200.

The reason is that loop is an artificial construct that makes programming easier (sort of). In a real system code executes from the beginning of main() and ends at the end of main() - there is no loop! You roll your own loops as required! The actual code that lies above the familiar Arduino words 'setup' and 'loop' is something like this:

Note: The main() function is the program that is called first in a C/C++ program and it must always be present otherwise the compiler does not know where to begin!
// main construct

void main(void) {

    setup();         // Call the user defined code for setup

    while(1) loop(); // Continuously call the user defined code for loop.

}

As shown above when 'main()' is called, first of all the code within function setup() is executed and then the function loop() is called repeatedly (in a so-called endless loop). This is standard programming practice and all that the Arduino code has done is removed the outer layer so it sort-of simplifies the proceedings so that you only need to write those functions ( setup() and loop() ).

However you can't actually see that loop() is called (hidden in the Arduino code similar to the code above) since you are never aware of the main() function.

The key point is that scoping rules force all local variables to be initialised at the start of any function and lost at exit of that function. Therefore the value of dly is lost at the end of loop() and so the code that sets the new value has no effect. All that happens is that each time the function is started the dly variable is initialised to 200.

Note: Local variables are variables declared at the start of a function (or for C++, within the function somewhere) and you use them to hold temporary values throughout the function. They are lost at exit of the function.

To make a function remember values between calls you need to preceded the variable with the word static - meaning that the value of that variable is going no where and is retained between calls to the function.

//////////////////////////////////////////////
// Arduino Delay LED flash that works
void loop(){
static uint16_t dly=200;

  delay(dly);
  digitalWrite(LED,HIGH);
  delay(dly);
  digitalWrite(LED,LOW);

  if (digitalRead(INPUT)) dly=100; else dly=10;

}

Code equivalent in a "real" system (not using the Arduino compiler or IDE)

The real reason that there is a problem is that in a "real" program you could have written the whole thing as follows using the main() function.

Warning: This is example code. You can not run this code in the Arduino IDE - you would need to use an AVR compiler (and you will need a bit more chip-setup code as well).
// main construct Full program non-Arduino compiler code.

// Arduino pins
#define INPUT 5
#define LED 13

void main(void) {
uint16_t dly=200;

    pinMode(LED,OUTPUT);       // This was the code within setup()

    while(1) {}                // Endless loop code

      delay(dly);              // This was the code within loop()
      digitalWrite(LED,HIGH);
      delay(dly);
      digitalWrite(LED,LOW);

      if (digitalRead(INPUT)) dly=100; else dly=10;
    }
}

In this case the definition of dly does not need to be static since the variable's scope is the whole of the main() function. In this case anything within main() can see and use the variable dly.

This is the sort of code that you will have to write for most microcontrollers since compiler makers do not mess about giving you the easy route that the Arduino IDE/compiler does!

New! Comments

Have your say about what you just read! Leave me a comment in the box below.




Privacy Policy | Contact | About Me

Site Map | Terms of Use



Visit our Facebook Page:

   Click Here



Recent Articles

  1. [Arduino Tutorial] : How to use the 74HC595 shift register with shiftOut().

    The Essential Guide to the 74HC595; What it is and how you can easily use one in any of your projects.

    Read more

  2. Pic Programmer Types

    Which pic programmer do you need? This page discusses PIC programmers and gives some essential information on choosing or building your own programmer.

    Read more

  3. Arduino Pulsein: an easy way to measure pulse periods in microseconds.

    learn how to use Arduino pulseIn and pulseInLong to get the most accurate pulse measurement on an Arduino.

    Read more

  4. Arduino millis

    How to use Arduino millis() for deylays but still make the processor do work - Stop using delay()

    Read more

  5. Multiple MCP23017 Interrupt tutorial for operating multiple interrupts from multiple MCP23017s.

    This MCP23017 Interrupt tutorial shows you how to connect interrupt outputs from several MCP23017s to a single microcontroller interrupt pin.

    Read more

  6. Arduino delay() How to use it (and why you should not use it!)

    Arduino Delay() is a useful function but not for large programs - Find Out Why Here...

    Read more

Readers Comments

"I wanted to thank
you so so so much
for all the information
you have provided in
your site it's

SUPERB and FANTASTIC."

- Ranish Pottath

"This site really is
the best and my favorite.
I find here many useful
projects and tips."

- Milan

bursach<at>gmail.com<

"Awesome site,
very, very easy and nice
to navigate!"


- Matt
matt_tr<at>
wolf359.cjb.net


Learn Microcontrollers

"Interested in
Microcontrollers?"

Sign up for The
Free 7 day guide:

FREE GUIDE : CLICK HERE


"I am a newbie to PIC
and I wanted to say
 how great your
site has been for me."


- Dave

de_scott<at>bellsouth.net

"Your site is a great
and perfect work.
congratulations."


- Suresh

integratredinfosys<at>
yahoo.com

"I couldn't find the correct
words to define
yourweb site.

Very useful, uncovered,
honest and clear.

Thanks so much for
your time and works.
Regards."


- Anon

Back to Top