Become a clock-watcher!

One simple technique for implementing timing is to make a schedule and keep an eye on the clock.  Instead of a world-stopping delay, you just check the clock regularly so you know when it is time to act.  Meanwhile the processor is still free for other tasks to do their thing.  A very simple example of this is the BlinkWithoutDelay example sketch that comes with the IDE.

The code on this page uses the wiring shown in the diagram below:

Blink Without Delay

This is the BlinkWithoutDelay example sketch from the IDE:

/* 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
 
 This example code is in the public domain.

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

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

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
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);
  }
}

What's the point of that?

At first glance, BlinkWithoutDelay  does not seem to be a very interesting sketch.  It looks like just a more complicated way to blink a LED.  However, BinkWithoutDelay illustrates a very important concept known as a State Machine.  

Instead of relying on delay() to time the blinking.  BlinkWithoutDelay remembers the current state of the LED and the last time it changed.  On each pass through the loop, it looks at the millis() clock to see if it is time to change the state of the LED again.

Welcome to the Machine

Let’s look at a slightly more interesting blink variant that has a different on-time and off-time.  We’ll call this one “FlashWithoutDelay”.  

// These variables store the flash pattern
// and the current state of the LED

int ledPin =  13;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
unsigned long previousMillis = 0;        // will store last time LED was updated
long OnTime = 250;           // milliseconds of on-time
long OffTime = 750;          // milliseconds of off-time

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

void loop()
{
  // check to see if it's time to change the state of the LED
  unsigned long currentMillis = millis();
 
  if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
  {
    ledState = LOW;  // Turn it off
    previousMillis = currentMillis;  // Remember the time
    digitalWrite(ledPin, ledState);  // Update the actual LED
  }
  else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
  {
    ledState = HIGH;  // turn it on
    previousMillis = currentMillis;   // Remember the time
    digitalWrite(ledPin, ledState);	  // Update the actual LED
  }
}

State + Machine = State Machine

Note that we have variables to keep track of whether the LED is ON or OFF.  And variables to keep track of when the last change happened.   That is the State part of the State Machine.  

We also have code that looks at the state and decides when and how it needs to change.  That is the Machine part.  Every time through the loop we ‘run the machine’ and the machine takes care of updating the state.

Next, we'll look at how you can combine multiple state machines and run them concurrently.

This guide was first published on Nov 03, 2014. It was last updated on Oct 27, 2014.

This page (Using millis() for timing) was last updated on Oct 27, 2014.

Text editor powered by tinymce.