Sunday, July 16, 2023

Blink an LED or do other tasks asynchronously without using delay() on an Arduino

/* Blink Four LEDs Without Delay
  Adapted from Blink Without Delay
  by Steven J Greenfield, aka Polymorph
  Use however you like

I wrote this years ago. I'm not the only one, I'm not claiming that...

Note that I do the math and saving of the current time in such a way as to not cause cumulative timing errors, and to be immune to the rollover of millis(). For faster timed events, you can use micros() in place of millis(). You can even mix them, as long as each variable sticks with one or the other.

*/

// constants won't change. Used here to 

// set pin numbers:

const int ledPin0 =  2;      // the number of the LED0 pin

const int ledPin1 =  3;      // the number of the LED1 pin

const int ledPin2 =  4;      // the number of the LED2 pin

const int ledPin3 =  5;      // the number of the LED3 pin


// Variables will change:

int ledState0 = LOW;             // ledState used to set the LED0

int ledState1 = LOW;             // ledState used to set the LED1

int ledState2 = LOW;             // ledState used to set the LED2

int ledState3 = LOW;             // ledState used to set the LED3


// the follow variables are unsigned long because the time stored in millis() and micros()

// are unsigned long.

unsigned long previousMillis0 = 0;        // will store last time LED0 was updated

unsigned long previousMillis1 = 0;        // will store last time LED1 was updated

unsigned long previousMillis2 = 0;        // will store last time LED2 was updated

unsigned long previousMillis3 = 0;        // will store last time LED3 was updated


// the follow variables are unsigned long because the time stored in millis() and micros()

// are unsigned long.

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

unsigned long interval1 = 457;           // interval at which to blink LED1 (milliseconds)

unsigned long interval2 = 1020;           // interval at which to blink LED2 (milliseconds)

unsigned long interval3 = 742;           // interval at which to blink LED3 (milliseconds)


void setup() {

  // set the digital pin as output:

  pinMode(ledPin0, OUTPUT);    

  pinMode(ledPin1, OUTPUT); 

  pinMode(ledPin2, OUTPUT); 

  pinMode(ledPin3, 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.


  // save the current time so it doesn't change during an operation

  unsigned long currentMillis = millis();


  // LED0 

  if(currentMillis - previousMillis0 >= interval0) {

    // save the last time you blinked the LED0 

    previousMillis0 += interval0;   // prevents time creep


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

    if (ledState0 == LOW)

      ledState0 = HIGH;

    else

      ledState0 = LOW;

  }


  //LED1

  if(currentMillis - previousMillis1 >= interval1) {

    // save the last time you blinked the LED0 

    previousMillis1 += interval1;   


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

    if (ledState1 == LOW)

      ledState1 = HIGH;

    else

      ledState1 = LOW;

  }


  //LED2

  if(currentMillis - previousMillis2 >= interval2) {

    // save the last time you blinked the LED0 

    previousMillis2 += interval2;   


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

    if (ledState2 == LOW)

      ledState2 = HIGH;

    else

      ledState2 = LOW;

  }


  //LED3

  if(currentMillis - previousMillis3 >= interval3) {

    // save the last time you blinked the LED0 

    previousMillis3 += interval3;   


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

    if (ledState3 == LOW)

      ledState3 = HIGH;

    else

      ledState3 = LOW;


    // set the LEDs with the ledStates of the variable:

    digitalWrite(ledPin0, ledState0);

    digitalWrite(ledPin1, ledState1);

    digitalWrite(ledPin2, ledState2);

    digitalWrite(ledPin3, ledState3);


  }

}