Please Let Me Know How Much You Like This (1 is very Bad - 10 is Excellent)

Asynchronous blinking LEDs with an Arduino.


It is easy to turn on than off more than one LEDs synchronous. However, it becomes increasingly difficult to turn on than off two and more LEDs asynchronous. Asynchronous blinking may be achieved with a simple program if we find a relationship between the frequency of LEDs. Let's assume that there are two LEDs and the one turns on-off every 250 milliseconds and the other every 1000 milliseconds. Since one of the LED blinking four times faster than the second LED than the following program achieves this task.
Please note that in the following programs you should make code changes indicated by the red colored text in the code. Less red color means that the program is more user-friendly and less error prone than the others.

// www.mekanizmalar.com // 2019/03/29 const int ledRed = 9; const int ledGreen = 10; void setup() { pinMode(ledRed, OUTPUT); pinMode(ledGreen, OUTPUT); } void loop() { digitalWrite(ledRed,HIGH); highLow(ledGreen); digitalWrite(ledRed,LOW); highLow(ledGreen); } void highLow(int led) { digitalWrite(ledGreen,HIGH); delay(250); digitalWrite(ledGreen,LOW); delay(250); digitalWrite(ledGreen,HIGH); delay(250); digitalWrite(ledGreen,LOW); delay(250); }

We can write the previous program by using one millisecond delay time. The advantage of this program is that there should be no relationship between light frequencies. Also, there is no need that the on and off times of the LEDs to be equal. The disadvantage of this program is that it is hard to maintain.

// www.mekanizmalar.com // 2019/03/29 const int ledRed = 9; const int ledGreen = 10; void setup() { pinMode(ledRed, OUTPUT); pinMode(ledGreen, OUTPUT); } int countRed = 1; int countGreen = 1; void loop() { // Red will be on 1000 milis and off 1000 milis if (countRed <= 1000) { digitalWrite(ledRed, HIGH); } else if ( countRed <= 2000) { digitalWrite(ledRed, LOW); } else { countRed = 0; } // Green will be on 250 milis and off 250 milis if (countGreen <= 250) { digitalWrite(ledGreen, HIGH); } else if ( countGreen <= 500) { digitalWrite(ledGreen, LOW); } else { countGreen = 0; } countRed++; countGreen++; delay(1); }

The maintenance of the previous program can be reduced by defining randomBlink function.

// www.mekanizmalar.com // 2019/03/29 const int ledRed = 9; const int ledGreen = 10; void setup() { pinMode(ledRed, OUTPUT); pinMode(ledGreen, OUTPUT); } int countRed = 1; int countGreen = 1; void loop() { // Red will be on 1000 ms and off 1000 ms countRed = randomBlink(ledRed, countRed, 1000, 1000); // Green will be on 250 ms and off 250 ms countGreen = randomBlink(ledGreen, countGreen, 250, 250); delay(1); } int randomBlink(int led, int count, int onTime, int offTime) { if (count <= onTime) { digitalWrite(led, HIGH); } else if ( count <= onTime + offTime) { digitalWrite(led, LOW); } else { count = 0; } return ++count; }

We can further reduce the complexity of the program by putting randomBlink function into a class file. We call this class FlasherWithDelay.

// www.mekanizmalar.com
// 2019/03/29
class FlasherWithDelay
{
    // Class Member Variables
    // These are initialized at startup
    byte ledPin;    // the pin number of the LED pin
    int OnTime;     // milliseconds on time
    int OffTime;    // milliseconds off time
    int timeCount;
    // These maintain the current state
    int ledState;    // ledState used to set the LED

  public:
    // Constructor - creates a Flasher
    // and initializes the member variables and state
    FlasherWithDelay(byte pin, int on, int off)
    {
      ledPin = pin;
      
      timeCount   = 0;
      OnTime = on;
      OffTime = off;

      ledState = HIGH;
    }

    void setup() {
      pinMode(ledPin, OUTPUT);  
    }

    void loop() {
      if (timeCount <= (OnTime + OffTime))
      {
        ledState = (timeCount <= OnTime) ? HIGH : LOW;
        digitalWrite(ledPin, ledState);//Update the actual LED
        ++timeCount;
        delay(1);
      } else {
         timeCount = 0; // reset the timer
      }     
    }
};

const int ledRed = 9; const int ledGreen = 10; FlasherWithDelay redLed(ledRed, 337, 889); FlasherWithDelay greenLed(ledGreen, 231, 421); void setup() { redLed.setup(); greenLed.setup(); } void loop() { redLed.loop(); greenLed.loop(); }

Below is a program which uses millis() function, which eliminates delay function from the blinking programs completly. By using this class, we wrote an Arduino program which blinks five LEDs randomly.

// Original Flasher Code by Bill Earl
// https://learn.adafruit.com/multi-tasking-the-arduino-part-1/a-classy-solution
// www.mekanizmalar.com
// 2019/03/29
class Flasher
{
    // Class Member Variables
    // These are initialized at startup
    int ledPin;      // the number of the LED pin
    long OnTime;     // milliseconds of on-time
    long OffTime;    // milliseconds of off-time
    // These maintain the current state
    int ledState;    // ledState used to set the LED
    // will store last time LED was updated
    unsigned long previousMs;
    // will store last time LED was updated
    unsigned long currentMs;
    // Constructor - creates a Flasher
    // and initializes the member variables and state
  public:
    Flasher(int pin, long on, long off)
    {
      ledPin = pin;
      //pinMode(ledPin, OUTPUT);
      OnTime = on;
      OffTime = off;
      ledState = HIGH;
      previousMs = 0;
    }
    void setup() {
      pinMode(ledPin, OUTPUT);
    }
    void loop()
    {
    //check to see if it's time to change the state of the LED
      currentMs = millis();
      if (currentMs - previousMs <= (OnTime + OffTime))
      {
        if (currentMs - previousMs >= OnTime)
        {
          ledState = LOW;  // Turn it off
        }
        else
        {
          ledState = HIGH;  // turn it on
        }
        digitalWrite(ledPin, ledState);// Update the actual LED
      } else {
        previousMs = currentMs; // Remember the time
      }
    }
};

const int led1 = 8; const int led2 = 9; const int led3 = 10; const int led4 = 11; const int led5 = 12; /* Flasher flasher1(led1, 20, 20); Flasher flasher2(led2, 40, 40); Flasher flasher3(led3, 80, 80); Flasher flasher4(led4, 160, 160); Flasher flasher5(led5, 320, 320); */ /* Flasher flasher1(led1, 200, 1000); Flasher flasher2(led2, 400, 800); Flasher flasher3(led3, 600, 600); Flasher flasher4(led4, 800, 400); Flasher flasher5(led5, 1000, 200); */ Flasher flasher1(led1, 983, 732); Flasher flasher2(led2, 663, 721); Flasher flasher3(led3, 567, 817); Flasher flasher4(led4, 331, 621); Flasher flasher5(led5, 783, 593); void setup() { flasher1.setup(); flasher2.setup(); flasher3.setup(); flasher4.setup(); flasher5.setup(); } void loop() { flasher1.loop(); flasher2.loop(); flasher3.loop(); flasher4.loop(); flasher5.loop(); }

By using Arrays inside the class, we can reduce the code complexity of a user code further as shown below.

// www.mekanizmalar.com
// 2019/04/04

class Flasher
{
    // Class Member Variables
    // These are initialized at startup
    // milliseconds of on-time
    long onT[11];
    // milliseconds of off-time
    long offT[11];
    // current miliseconds for each LED
    unsigned long currentMs[11];
    unsigned long previousMs[11];
    // the number of the LED pin
    int ledPins[11];   
    // current state of LEDs
    int ledState[11];
  public:
    int _length;

    Flasher(int pins[], int lengt) 
    {
      _length = lengt;
      for (int i = 0; i < _length; i++) {
        ledPins[i] = pins[i];
        previousMs[i] = 0; 
      }
    }

    void setup(long onAndOff[][2]) {
      for (int i = 0; i < _length; i++)
      {
        pinMode(ledPins[i], OUTPUT);
        onT[i]  = onAndOff[i][0];
        offT[i] = onAndOff[i][1];
      }
    }
    
    void loop()
    {
      // check to see if it's time 
      // to change the state of the LED
      for (int i = 0; i < _length; i++) {
        currentMs[i] = millis();
        if (currentMs[i] - previousMs[i] <= (onT[i] + offT[i]))
        {
          if (currentMs[i] - previousMs[i] >= onT[i])
          {
            ledState[i] = 0;  // Turn it off
          }
          else
          {
            ledState[i] = 1;  // turn it on
          }
          // Update the actual LED
          digitalWrite(ledPins[i], ledState[i]);
        } else {
          // Remember the time
          previousMs[i] = currentMs[i];
        }
      }
    }
};

int ledPins[5] = {8, 9, 10, 11, 12}; Flasher flasher(ledPins, 5); void setup() { //long onOffTimes[5][2] = {{20,20},{40,40},{80,80},{160,160},{320,320}}; //long onOffTimes[5][2] = {{200,1000},{400,800},{600,600},{800,400},{1000,200}}; //long onOffTimes[5][2] = {{983,732},{663,721},{567,817},{331,621},{783,593}}; long onOffTimes[5][2] = {{33,33},{63,63},{93,93},{123,123},{153,153}}; flasher.setup(onOffTimes); } void loop() { flasher.loop(); }


//