Need Help With Count and millis

Hi, I am trying to write a code to turn LED lights on and off with Millis. I cannot use the Blink Without Delay sample because my intervals would be different.

Here's the code I wrote.

int led = 42;
int led2 = 44;
int led3 = 46;
int led4 = 48;
int led5 = 50;
int led6 = 52;

int total = 1580;

int count = 0;

void setup() {
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

  pinMode(led2, OUTPUT);
  digitalWrite(led2, LOW);

  pinMode(led3, OUTPUT);
  digitalWrite(led3, LOW);

  pinMode(led4, OUTPUT);
  digitalWrite(led4, LOW);

  pinMode(led5, OUTPUT);
  digitalWrite(led5, LOW);

  pinMode(led6, OUTPUT);
  digitalWrite(led6, LOW);
}

void loop() {
  
  if(millis() == total*count + 200) {
    digitalWrite(led, HIGH);
  }

  if(millis() == total*count + 350) {
    digitalWrite(led2, HIGH);
  }

  if(millis() == total*count + 550) {
    digitalWrite(led3, HIGH);
  }
  
  if(millis() == total*count + 630) {
    digitalWrite(led4, HIGH);
  }

  if(millis() == total*count + 830) {
    digitalWrite(led5, HIGH);
  }

  if(millis() == total*count + 880) {
    digitalWrite(led6, HIGH);
  }

  if(millis() == total*count + 1080) {
    digitalWrite(led6, LOW);
  }

  if(millis() == total*count + 1180) {
    digitalWrite(led5, LOW);
  }

  if(millis() == total*count + 1280) {
    digitalWrite(led4, LOW);
  }

  if(millis() == total*count + 1380) {
    digitalWrite(led3, LOW);
  }

  if(millis() == total*count + 1480) {
    digitalWrite(led2, LOW);
  }

  if(millis() == total*count + 1580) {
    digitalWrite(led, LOW);
  }

 count = count + 1;
}

Without the last line "count = count + 1;" The LED lights will turn on but only loop once, which I understand why. But with the last line LED lights won't turn on at all. Can someone please tell me what i'm doing wrong? Using count++; does the same thing.

Also I imagine if I leave it on for too long the count would get too big even with unsigned long. In actuality it probably won't but I just like to know how can I resolve that?

Thank you!

I cannot use the Blink Without Delay sample because my intervals would be different.

I can make the LED(s) flash at different times, with different on and off intervals, using the blink without delay philosophy. You could, too, if you understood what it was doing. It really isn't rocket science.

You are expecting to get exact values when you subtract a value from the current time. That is not a realistic assumption. You should perform the action when the interval is greater than or equal to the desired value, not just when the interval IS the desired value.

== or >= consider reversing the 'if' order, then use 'else if'.

"I cannot use the Blink Without Delay sample because my intervals would be different."
What does this mean?

.

You have made things difficult for yourself by discarding the BWoD principle.

I cannot use the Blink Without Delay sample because my intervals would be different.

Not true. To have different on/off periods change between the two the period lengths when the LED state changes. Extend the principle to multiple LEDs by putting pin number and variables in arrays.

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.

As @UKHeliBob says, you can change the value for the flash interval when the state changes.

...R

larryd:
== or >= consider reversing the 'if' order, then use 'else if'.

"I cannot use the Blink Without Delay sample because my intervals would be different."
What does this mean?

.

UKHeliBob:
You have made things difficult for yourself by discarding the BWoD principle.
Not true. To have different on/off periods change between the two the period lengths when the LED state changes. Extend the principle to multiple LEDs by putting pin number and variables in arrays.

Robin2:
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.

As @UKHeliBob says, you can change the value for the flash interval when the state changes.

...R

Thank you for replying so fast. I see that the code in my post isn't representing what I want to do which is totally my fault. I meant to change the code later to make the light sequence more complex, every led will be on and off several times with changing on intervals and off intervals. For example led1 will turn on for 5 sec off for 10 sec and on for 7 sec and off for 2 sec... Will I still be able to use BWoD in this situation? If not what's the correct way to do this?

From the Adafruit flash wihout delay code I learned that you can set on-time and off-time for each LED, but nowhere I can find how to do it with changing on and off intervals.

Also if "count = count +1;" is in the code the lights do nothing, if I remove "count = count +1;" the lights will run the sequence once. Although this might not be the right way to do it I would still like to know why "count = count + 1" didn't work and how to get the sequence to loop so I can understand the language better.

Thank you for your time and help.

Also if "count = count +1;" is in the code the lights do nothing, if I remove "count = count +1;" the lights will run the sequence once. Although this might not be the right way to do it I would still like to know why "count = count + 1" didn't work and how to get the sequence to loop so I can understand the language better.

You fly through the loop a thousand times incrementing the value of count before you ever get through the first 200 milliseconds. Your conditional test of millis() is against a number you haven't reached.

For example led1 will turn on for 5 sec off for 10 sec and on for 7 sec and off for 2 sec... Will I still be able to use BWoD in this situation?

Sure. Put the intervals in an array and work your way through them as you change the state of the LED. You can include a dummy value, such as -1, in the array of intervals to indicate that the index to it should be reset to zero for the LED that the intervals relate to so that the sequence starts again..

cattledog:
You fly through the loop a thousand times incrementing the value of count before you ever get through the first 200 milliseconds. Your conditional test of millis() is against a number you haven't reached.

That makes perfect sense. I can make it loop correctly now that I understand what i did wrong. Thank you so much.

UKHeliBob:
Sure. Put the intervals in an array and work your way through them as you change the state of the LED. You can include a dummy value, such as -1, in the array of intervals to indicate that the index to it should be reset to zero for the LED that the intervals relate to so that the sequence starts again..

Thank you. I've never used array before, I don't know how to make -1 an indication for resetting, I wrote this code but the LEDs don't turn on at the same time and the intervals aren't changing. Can you please take a look and see what I did wrong? Thank you again.

int ledPin1 =  42;
int ledState1 = LOW;
unsigned long previousMillis1 = 0;
long On1[2] = {4000, 1200};
long Off1[2] = {200, 4000};
 
int ledPin2 =  44;
int ledState2 = LOW;
unsigned long previousMillis2 = 0;
long On2[2] = {1000, 600};
long Off2[2] = {2000, 4000};

int i = 0;
 
void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
}
 
void loop(){
  unsigned long currentMillis = millis();

 for(i = 0; i < 2; i++) {
  if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= On1[i])) {
    ledState1 = LOW;
    previousMillis1 = currentMillis;
    digitalWrite(ledPin1, ledState1);
  } else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= Off1[i])) {
    ledState1 = HIGH;
    previousMillis1 = currentMillis;
    digitalWrite(ledPin1, ledState1);
  }
 }

 for(i = 0; i < 2; i++) {
  if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= On2[i])) {
    ledState2 = LOW;
    previousMillis2 = currentMillis;
    digitalWrite(ledPin2, ledState2);
  } else if ((ledState2 == LOW) && (currentMillis - previousMillis2 >= Off2[i])) {
    ledState2 = HIGH;
    previousMillis2 = currentMillis;
    digitalWrite(ledPin2, ledState2);
  }
}
}

Rather than try to explain what was wrong and how to use -1 to allow a different number of periods for each LED I decided to write a program and comment it

const byte ledPins[] = {10, 11, 12, 13};
const byte NUMBER_OF_LEDS = sizeof(ledPins);
unsigned long startTimes[NUMBER_OF_LEDS] = {};
byte indexes[NUMBER_OF_LEDS] = {0};
const byte MAX_NUMBER_OF_PERIODS = 10;
long periods[][MAX_NUMBER_OF_PERIODS] =    //periods for each LED.  -1 indicates end of sequence
{
  {1000, 2000, 1500, 2500, -1},
  {500, 200, 1000, 2000, 3000, 4000, -1},
  {400, 1000, 1500, 2000, -1},
  {1100, 2200, -1}
};

void setup()
{
  Serial.begin(115200);
  for (int led = 0; led < NUMBER_OF_LEDS; led++)
  {
    pinMode(ledPins[led], OUTPUT);
  }
}

void loop()
{
  unsigned long currentTime = millis();
  for (int led = 0; led < NUMBER_OF_LEDS; led++)  //iterate through the LEDs
  {
    if (currentTime - startTimes[led] >= periods[led][indexes[led]])  //? time to change ?
    {
      digitalWrite(ledPins[led], !digitalRead(ledPins[led]));  //flip led state
      startTimes[led] = currentTime;  //save start time of state
      indexes[led]++;                    //increment index
    }
    if (periods[led][indexes[led]] == -1)  //if next period is -1 (end of sequence)
    {
      indexes[led] = 0;        //reset period index for this LED
    }
  }  //end for loop
}

Please feel free to ask questions

UKHeliBob:
Rather than try to explain what was wrong and how to use -1 to allow a different number of periods for each LED I decided to write a program and comment it

const byte ledPins[] = {10, 11, 12, 13};

const byte NUMBER_OF_LEDS = sizeof(ledPins);
unsigned long startTimes[NUMBER_OF_LEDS] = {};
byte indexes[NUMBER_OF_LEDS] = {0};
const byte MAX_NUMBER_OF_PERIODS = 10;
long periods[][MAX_NUMBER_OF_PERIODS] =    //periods for each LED.  -1 indicates end of sequence
{
  {1000, 2000, 1500, 2500, -1},
  {500, 200, 1000, 2000, 3000, 4000, -1},
  {400, 1000, 1500, 2000, -1},
  {1100, 2200, -1}
};

void setup()
{
  Serial.begin(115200);
  for (int led = 0; led < NUMBER_OF_LEDS; led++)
  {
    pinMode(ledPins[led], OUTPUT);
  }
}

void loop()
{
  unsigned long currentTime = millis();
  for (int led = 0; led < NUMBER_OF_LEDS; led++)  //iterate through the LEDs
  {
    if (currentTime - startTimes[led] >= periods[led][indexes[led]])  //? time to change ?
    {
      digitalWrite(ledPins[led], !digitalRead(ledPins[led]));  //flip led state
      startTimes[led] = currentTime;  //save start time of state
      indexes[led]++;                    //increment index
    }
    if (periods[led][indexes[led]] == -1)  //if next period is -1 (end of sequence)
    {
      indexes[led] = 0;        //reset period index for this LED
    }
  }  //end for loop
}



Please feel free to ask questions

Sorry for the late reply but it all works now! Thank you so much for the example, it makes perfect sense and I looked up a lot of tutorials on this and none are this efficient and understandable, I couldn't thank you enough!

I'm glad it works for you and that you find it instructive. I generally favour giving advice for people to write their own programs but sometimes it is easier and more helpful to provide a working example.

Here is a way to do it with the BlinkWithoutDelay method:

const byte led = 42;
const byte led2 = 44;
const byte led3 = 46;
const byte led4 = 48;
const byte led5 = 50;
const byte led6 = 52;


void setup() {
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);

  pinMode(led2, OUTPUT);
  digitalWrite(led2, LOW);

  pinMode(led3, OUTPUT);
  digitalWrite(led3, LOW);

  pinMode(led4, OUTPUT);
  digitalWrite(led4, LOW);

  pinMode(led5, OUTPUT);
  digitalWrite(led5, LOW);

  pinMode(led6, OUTPUT);
  digitalWrite(led6, LOW);
}

void loop() {
  static unsigned long startTime = 0;
  unsigned long currentTime = millis();

  unsigned long elapsedTime = currentTime - startTime;

  if (elapsedTime >= 200 && elapsedTime <= 1580)
    digitalWrite(led, HIGH);
  else
    digitalWrite(led, LOW);

  if (elapsedTime >= 350 && elapsedTime <= 1480)
    digitalWrite(led2, HIGH);
  else
    digitalWrite(led2, LOW);

  if (elapsedTime >= 550 && elapsedTime <= 1380)
    digitalWrite(led3, HIGH);
  else
    digitalWrite(led3, LOW);

  if (elapsedTime >= 630 && elapsedTime <= 1280)
    digitalWrite(led4, HIGH);
  else
    digitalWrite(led4, LOW);

  if (elapsedTime >= 830 && elapsedTime <= 1180)
    digitalWrite(led5, HIGH);
  else
    digitalWrite(led5, LOW);

  if (elapsedTime >= 880 && elapsedTime <= 1080)
    digitalWrite(led6, HIGH);
  else
    digitalWrite(led6, LOW);

  //  At the end of one cycle, start another
  if (elapsedTime >= 1580)
    startTime += 1580;
}