LED BLINK LOOPS PROBLEM

Hi…

New user, and loving the new hobby.

VERY new to this all, but I’m wondering if someone could please help me…

My project is simple.

I want to have 2 LEDs.

They have individual sequences (eg 2 flashes every 12 seconds, and 1 flash every 5 seconds). These must be independent of each other.

I almost had success with Blinkwithoutdelay, BUT, the blink period doesn’t seem to accomodate a delay.

Simple BLINK is perfect for me to set up my sequence (for 1 LED).

But is gets messed up when I ass the second LED.

Is it possible to code 2 separate BLINK sequences (including delays), to run in parallel at the same time?

Many thanks for your help.

delay() won't work because your program pauses during the delay time... For that reason delay() is rarely used in real world programs (or used carefully for short delays).

Look at the [u]Blink Without Delay Example[/u].

You'll need to make two duration variables (i.e. DurationRed & DurationGreen) and two PreviousMillis variables (i.e. PreviousMillisRed and PreviousMillisGreen). Of course there is only one currentMillis.

The demo Several Things at a Time is an extended example of BWoD and illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

It flashes 3 LEDs

...R

Many Thanks for your replies...

Still at a bit of a loss...

Maybe if i explain it a little more...

LED 1
On 200, OFF 2000
On 200, OFF 2000
On 200, OFF 2000
On 200, OFF 2000
On 200, then OFF 9000

Meanwhile...

LED 2
On 500,OFF1000
On 500, then OFF 10000

These sequences don't align, and a simple Blink with no delay doesn't seem to work..

Surely I can have 2 (or more) LEDs working at their own independent loops?

I'm trying to learn, but its HARD!

Thanks a million

Surely I can have 2 (or more) LEDs working at their own independent loops?

Absolutely.
See the blink without delay example in the IDE.
Play with it.
Expand it.

i've experimented (a little) with the Blink without delay code, but I seem to only get a blink (on is equal time to off), and so, I can't get it to come on for 200, off for 2000 etc..

Am I missing something?

campbeda:
Am I missing something?

Maybe, but we most definitely are - your code.

Hint: if you can change the state of a LED, you can change the amount of time that state persists.

You may have to learn arrays earlier than most. Perhaps even a two dimensional array:

int LongSequence[10][2] = {
{HIGH, 200},
{LOW, 2000},
{HIGH, 200},
{LOW, 2000},
{HIGH, 200},
{LOW, 2000},
{HIGH, 200},
{LOW, 2000},
{HIGH, 200},
{LOW, 9000}
};

digitalWrite(Pin, LongSequence[step][0]);
LongInterval = LongSequence[step][1];
step = (step + 1) % 10;

Hi campbeda,

I feel ya! BwoD is a rather abstract concept, it's based on the fact that a well written loop() function in the Arduino system executes many thousand times a second, so you are basically just checking the time over and over, and over, and ...

Maybe the easiest way to learn it is to just copy Robin2's program from the second post in the thread he linked in his post above, called Several Things at a Time. Paste it into an empty sketch, and save it in your own Arduino system.

If you don't have a servo or a switch, you can comment out the lines in the sketch that refer to them, it runs just fine with just the three LEDs, all blinking at different rates.

This is the basic scheme for ALL time based Arduino programming. Trying to use delay() will only bite you in the butt.

Hi,
The blink without delay is written to blink with equal ON and OFF times.

You are looking for a fixed ON time and and different fixed OFF time.

You want to do this with two separate LEDs running different rates.

Am I right?

Thanks.. Tom.. :slight_smile:

Hi,
I have done a quick mod to the blink without delay to give you a selectable ON and OFF.

/*
  Blink without Delay
*/


// constants won't change. Used here to set a pin number:
const int ledPin =  LED_BUILTIN;// 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

long ONinterval = 200;           // interval at which to blink ON (milliseconds)
long OFFinterval = 1000;          // interval at which to blink OFF (milliseconds)
long currentinterval;
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 (ledState == HIGH)  // Decide which interval should be used
  {
    currentinterval = ONinterval;
  }
  else
  {
    currentinterval = OFFinterval;
  }
  if (currentMillis - previousMillis >= currentinterval) {
    // 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);
  }
}

I hope it helps.

Tom... :slight_smile:

Why test "ledState" every time through the loop? :o
Just do it once, at the timeout.

Hi everyone...

Sincere thanks for all your help... I am getting there!!!

I have juggled some code (which you have kindly brought to my attention)...

Just one further question...

As you can see, I have 3 LEDs (Pins11,12,13)
I have been able to define their blink length, and also the interval between each blink...
BUT... the last piece of my jigsaw is how to assign a PATTERN

For instance, LED 13 (below)..
In the code, it flashes for 500, and then off for 11500...
I need to get it to flash 500, off 1000, flash 500, off 10000, and then repeat all...

Any ideas how I can put this last adjustment into my code?

Again, MANY THANKS

Dara

//CONSTANTS
//ARDUINO BOARD PIN ASSIGNMENT
const int LED13Pin = 13; // the pin numbers for the LEDs
const int LED12Pin = 12;
const int LED11Pin = 11;

//INTERVALS BETWEEN BLINKS
const int LED13Interval = 11500; // number of millisecs between blinks
const int LED12Interval = 2000;
const int LED11Interval = 4750;

//BLINK DURATIONS
const int LED13blinkDuration = 500; // number of millisecs that Led's are on - all three leds use this
const int LED12blinkDuration = 150;
const int LED11blinkDuration = 250;

//VARIABLES (these will change)

//CHECKS WHETHER THE LED IS ON OR OFF
byte LED13State = LOW;
byte LED12State = LOW;
byte LED11State = LOW;

unsigned long currentMillis = 0; // stores the value of millis() in each iteration of loop()
unsigned long previousLED13Millis = 0; // will store last time the LED was updated
unsigned long previousLED12Millis = 0;
unsigned long previousLED11Millis = 0;

void setup() {
pinMode(LED13Pin, OUTPUT);
pinMode(LED12Pin, OUTPUT);
pinMode(LED11Pin, OUTPUT);
}

void loop() {
currentMillis = millis();
updateLED13State();
updateLED12State();
updateLED11State();
switchLeds();
}

void updateLED13State() {
if (LED13State == LOW) {
// if the Led is off, we must wait for the interval to expire before turning it on
if (currentMillis - previousLED13Millis >= LED13Interval) {
// time is up, so change the state to HIGH
LED13State = HIGH;
// and save the time when we made the change
previousLED13Millis += LED13Interval;
// NOTE: The previous line could alternatively be
// previousOnBoardLedMillis = currentMillis
// which is the style used in the BlinkWithoutDelay example sketch
// Adding on the interval is a better way to ensure that succesive periods are identical
}
}
else {
if (currentMillis - previousLED13Millis >= LED13blinkDuration) {
// time is up, so change the state to LOW
LED13State = LOW;
// and save the time when we made the change
previousLED13Millis += LED13blinkDuration;
}
}
}

void updateLED12State() {
if (LED12State == LOW) {
if (currentMillis - previousLED12Millis >= LED12Interval) {
LED12State = HIGH;
previousLED12Millis += LED12Interval;
}
}
else {
if (currentMillis - previousLED12Millis >= LED12blinkDuration) {
LED12State = LOW;
previousLED12Millis += LED12blinkDuration;
}
}
}

void updateLED11State() {
if (LED11State == LOW) {
if (currentMillis - previousLED11Millis >= LED11Interval) {
LED11State = HIGH;
previousLED11Millis += LED11Interval;
}
}
else {
if (currentMillis - previousLED11Millis >= LED11blinkDuration) {
LED11State = LOW;
previousLED11Millis += LED11blinkDuration;
}
}
}

void switchLeds() {
digitalWrite(LED13Pin, LED13State);
digitalWrite(LED12Pin, LED12State);
digitalWrite(LED11Pin, LED11State);
}

//=====END

Thanks for all your tips so far...

Thanks @TomGeorge..

@johnwasser... thanks for that idea.. it looks like its something which might work, but I have no clue how to put it into my code, to even try for 1 led....

Thanks!

AWOL:
Why test “ledState” every time through the loop? :o
Just do it once, at the timeout.

I have done a quick mod to the blink without delay to give you a selectable ON and OFF

:slight_smile:

Dara you need to use code tags </>.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks…Tom… :slight_smile:

// An example of turning an output pin HIGH and LOW in a repeating pattern.


int SequenceA[][2] =
{
  // For each step, the pin state and duration in milliseconds
  {HIGH, 200},
  {LOW, 2000},
  {HIGH, 200},
  {LOW, 2000},
  {HIGH, 200},
  {LOW, 2000},
  {HIGH, 200},
  {LOW, 2000},
  {HIGH, 200},
  {LOW, 9000}
};
// Calculate the number of steps in the sequence
byte SequenceLengthA = sizeof SequenceA / sizeof SequenceA[0];
// The pin being turned on and off
const byte LEDAPin =  LED_BUILTIN;// the number of the LED pin
// A place to store the start time of the current step
unsigned long IntervalStartA;        // will store last time LED was updated
// A place to store the duration of the current step
unsigned long IntervalA;           // interval at which to blink (milliseconds)
// An index into the sequence of the current step
byte SequenceIndexA;


void setup()
{
  // set the pin as output:
  pinMode(LEDAPin, OUTPUT);
  SequenceIndexA = 0;  // Start at the first step
  digitalWrite(LEDAPin, SequenceA[SequenceIndexA][0]);  // Is the first step HIGH or LOW
  IntervalStartA = millis();  // Store the start time of the current step
  IntervalA = SequenceA[SequenceIndexA][1];  // Store the duration of the first step
}


void loop()
{
  unsigned long currentMillis = millis();


  if (currentMillis - IntervalStartA >= IntervalA)
  {
    // The interval is over.  Go on to the next step
    SequenceIndexA = (SequenceIndexA + 1) % SequenceLengthA;  // '%' is the Modulo (remainder after integer division) operator.


    digitalWrite(LEDAPin, SequenceA[SequenceIndexA][0]);  // Is the step HIGH or LOW
    IntervalStartA = currentMillis;  // Store the start time of the current step
    IntervalA = SequenceA[SequenceIndexA][1];  // Store the duration of the current step
  }
}

Hi John...

Oh my God!!!!
My brain just melted!!!

I will look through your code tomorrow, and see can I work out what you've suggested...

I do a highly technical job, based very much on logic and procedures, but I've never experienced anything quite so complicated in my life!! Ha ha!!!

Many thanks for your kindness in offering to solve my problem!

Now, all I have to fo is work out how to input it into my original code....

time for a beer !

a big one!

Right...

I am obviously in a little deeper than I thought....

So... could anyone help a little further..

I have posted my code below (thanks TomGeorge)...

Basically, I want LED13 to flash 200,2000,200,2000,5400

and I want LED12 to flash 200,4800

Any help with editing my code would be appreciacted, because I am really struggling with the finer detail at this early stage of my Arduino experiment!!

Thanks so much

Dara

//CONSTANTS 
//ARDUINO BOARD PIN ASSIGNMENT
const int LED13Pin = 13;     
const int LED12Pin = 12;

//INTERVALS BETWEEN BLINKS
const int LED13Interval = 4500; 
const int LED12Interval = 2000;

//BLINK DURATIONS
const int LED13blinkDuration = 500; 
const int LED12blinkDuration = 500;

//VARIABLES (these will change)

//CHECKS WHETHER THE LED IS ON OR OFF
byte LED13State = LOW;             
byte LED12State = LOW;

unsigned long currentMillis = 0;      // stores the value of millis() in each iteration of loop()
unsigned long previousLED13Millis = 0;   // will store last time the LED was updated
unsigned long previousLED12Millis = 0;

void setup() {
 pinMode(LED13Pin, OUTPUT);
 pinMode(LED12Pin, OUTPUT);
}

void loop() {
 currentMillis = millis();
 updateLED13State();
 updateLED12State();
 switchLeds();
}

void updateLED13State() {
 if (LED13State == LOW) {
         // if the Led is off, we must wait for the interval to expire before turning it on
   if (currentMillis - previousLED13Millis >= LED13Interval) {
         // time is up, so change the state to HIGH
      LED13State = HIGH;
         // and save the time when we made the change
      previousLED13Millis += LED13Interval;
         // NOTE: The previous line could alternatively be
         //              previousOnBoardLedMillis = currentMillis
         //        which is the style used in the BlinkWithoutDelay example sketch
         //        Adding on the interval is a better way to ensure that succesive periods are identical
   }
 }
 else {  
   if (currentMillis - previousLED13Millis >= LED13blinkDuration) {
         // time is up, so change the state to LOW
      LED13State = LOW;
         // and save the time when we made the change
      previousLED13Millis += LED13blinkDuration;
   } 
 }
}

void updateLED12State() {
 if (LED12State == LOW) {
   if (currentMillis - previousLED12Millis >= LED12Interval) {
      LED12State = HIGH;
      previousLED12Millis += LED12Interval;
   }
 }
 else {
   if (currentMillis - previousLED12Millis >= LED12blinkDuration) {
      LED12State = LOW;
      previousLED12Millis += LED12blinkDuration;
   } 
 }    
}

void switchLeds() {
 digitalWrite(LED13Pin, LED13State);
 digitalWrite(LED12Pin, LED12State);
}

campbeda:
Basically, I want LED13 to flash 200,2000,200,2000,5400

You can't have a repeating On/Off sequence with an odd number of time intervals.
If it is On 200, Off 2000 On 200, Off 2000, On 5400 and repeat, the On 200 at the start and On 5400 at the end will merge together into one On 5600.

Anyway, here's an even better idea if you are running multiple sequences: FUNCTIONS! By putting all of the code and data into a function we can avoid using global variables. You can't use the same global variables for more than one sequence so you would have to come up with new names for each of the globals for each of the sequences.

Global variables (the ones declared outside any function) have the advantage that they retain their value even across function calls and they can be used in multiple functions. The first advantage can be duplicated with the 'static' keyword. That tells the compiler to set aside space for the variable as if it were Global but keep it local so it can only be seen inside the function. We don't need the other advantage if we put each sequence in one function. :slight_smile:

// An example of turning two output pins HIGH and LOW in repeating, parallel but not synchronized, patterns.


const byte LEDAPin = 13;
const byte LEDBPin = 12;


void setup()
{
  // set the LED pins as output:
  pinMode(LEDAPin, OUTPUT);
  pinMode(LEDBPin, OUTPUT);
}


void loop()
{
  SequenceRunA(LEDAPin);
  SequenceRunB(LEDBPin);
}


void SequenceRunA(const byte pin)
{
  unsigned long currentMillis = millis();


  const int sequence[][2] =
  {
    // For each step, the pin state and duration in milliseconds
    {HIGH, 200},
    {LOW, 2000},
    {HIGH, 200},
    {LOW, 2000},
    {HIGH, 5400}   // Note that the last step doesn't end with ',' like all the others. 
  };


  // Calculate the number of steps in the sequence
  const byte sequenceLength = sizeof sequence / sizeof sequence[0];


  // A place to store the start time of the current step
  static unsigned long intervalStart = 0;  // 0 means DO THE INITIALIZATION


  // A place to store the desired duration of the current step
  static unsigned long interval;


  // An index into the sequence of the current step
  static byte index = 0;  // (Yes, you can start at any step in the sequence.)


  if (intervalStart == 0)
  {
    // First time through
    digitalWrite(pin, sequence[index][0]);
    interval = sequence[index][1];  // How long until the next step
    intervalStart = currentMillis;  // When this step started
  }


  if (currentMillis - intervalStart >= interval)
  {
    // The step is over.  Go on to the next step
    index = (index + 1) % sequenceLength;  // '%' is the Modulo (remainder after integer division) operator.


    digitalWrite(pin, sequence[index][0]);  // Is the step HIGH or LOW
    interval = sequence[index][1];  // How long until the next step
    intervalStart = currentMillis;   // When this step started
  }
}


void SequenceRunB(const byte pin)
{
  unsigned long currentMillis = millis();


  const int sequence[][2] =
  {
    // For each step, the pin state and duration in milliseconds
    {HIGH, 200},
    {LOW, 4800}   // Note that the last step doesn't end with ',' like all the others. 
  };


  // Calculate the number of steps in the sequence
  const byte sequenceLength = sizeof sequence / sizeof sequence[0];


  // A place to store the start time of the current step
  static unsigned long intervalStart = 0;        // will store last time LED was updated


  // A place to store the duration of the current step
  static unsigned long interval;           // interval at which to blink (milliseconds)


  // An index into the sequence of the current step
  static byte index = 0;


  if (intervalStart == 0)
  {
    // First time through
    digitalWrite(pin, sequence[index][0]);
    interval = sequence[index][1];
    intervalStart = currentMillis;
  }


  if (currentMillis - intervalStart >= interval)
  {
    // The interval is over.  Go on to the next step
    index = (index + 1) % sequenceLength;  // '%' is the Modulo (remainder after integer division) operator.


    digitalWrite(pin, sequence[index][0]);  // Is the step HIGH or LOW
    interval = sequence[index][1];  // Store the duration of the current step
    intervalStart = currentMillis;  // Store the start time of the current step
  }
}

Sincere Thanks to everyone who replied, and offered advice...

I am only new to this, so it was very much a learning experience...

Huge thanks to JohnWasser, who pretty much fixed exactly what I was looking for... I have spent the last few hours reading through his code to try to understand it all.... Many Thanks John for your time and effort. It is very much appreciated.

Cheers

Dara