Multiple LEDs without delay...help me teach my student!

Hello! I am middle school teacher fumbling my way through learning how to use Arduino in order to help a student of mine learn to create a specific project she has in mind. I am SO new to this, I don't even know what I don't know. We have exactly one week to get this figured out, and I don't want to disappoint her! She wants to program her LEDs to do this:

LED1: flash on for one second, turn off for 15 seconds, and then repeat indefinitely.
LED2: flash on for one second, turn off for 16 seconds, and then repeat indefinitely.
LED3: flash on for one second, turn off for 7.5 minutes, and then repeat indefinitely.
LED4: flash on for one second, turn off for 1 second, and then repeat indefinitely.
LED5: flash on for one second, turn off for 48 seconds, and then repeat indefinitely.
LED6: flash on for one second, turn off for 50 seconds, and then repeat indefinitely.

She has successfully managed to make them blink like this (which is NOT what she wants):

LED1: flash on for 15 second, turn off for 15 seconds, and then repeat indefinitely.
LED2: flash on for 16 second, turn off for 16 seconds, and then repeat indefinitely.
LED3: flash on for 7.5 minutes, turn off for 7.5 minutes, and then repeat indefinitely.
LED4: flash on for one second, turn off for 1 second, and then repeat indefinitely.
LED5: flash on for 48 seconds, turn off for 48 seconds, and then repeat indefinitely.
LED6: flash on for 50 seconds, turn off for 50 seconds, and then repeat indefinitely.

using the code below, but we can't manipulate the code correctly to make this one small change! It's making me crazy! Can anyone help?

// Which pins are connected to which LED
const byte LED1 = 6;
const byte LED2 = 7;
const byte LED3 = 8;
const byte LED4 = 9;
const byte LED5 = 10;
const byte LED6 = 11;
 
 
// Assigning delays.
const unsigned long LED1_ON_interval = 15000; //
const unsigned long LED1_OFF_interval = 15000;
const unsigned long LED2_ON_interval = 16000; //
const unsigned long LED2_OFF_interval = 16000;
const unsigned long LED3_ON_interval = 450000; //
const unsigned long LED3_OFF_interval = 450000;
const unsigned long LED4_ON_interval = 1000; //
const unsigned long LED4_OFF_interval = 1000;
const unsigned long LED5_ON_interval = 48000; //
const unsigned long LED5_OFF_interval = 48000;
const unsigned long LED6_ON_interval = 50000; //
const unsigned long LED6_OFF_interval = 50000;
 
 
// Declaring the variables holding the timer values for each LED.
unsigned long LED1_timer;
unsigned long LED2_timer;
unsigned long LED3_timer;
unsigned long LED4_timer;
unsigned long LED5_timer;
unsigned long LED6_timer;
 
  
 
// Setting 3 digital pins as output pins and resetting timer
void setup ()
  {
  pinMode (LED1, OUTPUT);
  pinMode (LED2, OUTPUT);
  pinMode (LED3, OUTPUT);
  pinMode (LED4, OUTPUT);
  pinMode (LED5, OUTPUT);
  pinMode (LED6, OUTPUT);
  LED1_timer = millis ();
  LED2_timer = millis ();
  LED3_timer = millis ();
  LED4_timer = millis ();
  LED5_timer = millis ();
  LED6_timer = millis ();
  }  // end of setup
 
 
//LED1 loop that turns it ON if it is OFF and vice versa
void toggle_LED1 ()
  {
   if (digitalRead (LED1) == LOW)
      digitalWrite (LED1, HIGH);
   else
      digitalWrite (LED1, LOW);
 
 
  // remember when we toggled it
  LED1_timer = millis (); 
  }  // end of toggleLED_1
 
 
//LED2 loop
void toggle_LED2 ()
  {
   if (digitalRead (LED2) == LOW)
      digitalWrite (LED2, HIGH);
   else
      digitalWrite (LED2, LOW);
 
 
  // remember when we toggled it
  LED2_timer = millis (); 
  }  // end of toggle_LED2
 
  //LED 3 loop
void toggle_LED3 ()
  {
   if (digitalRead (LED3) == LOW)
      digitalWrite (LED3, HIGH);
   else
      digitalWrite (LED3, LOW);
 
 
  // remember when we toggled it
  LED3_timer = millis (); 
  }  // end of toggle_LED3
  
  void toggle_LED4 ()
  {
   if (digitalRead (LED4) == LOW)
      digitalWrite (LED4, HIGH);
   else
      digitalWrite (LED4, LOW);
 
 
  // remember when we toggled it
  LED4_timer = millis (); 
  }  // end of toggleLED_4
 
 
//LED2 loop
void toggle_LED5 ()
  {
   if (digitalRead (LED5) == LOW)
      digitalWrite (LED5, HIGH);
   else
      digitalWrite (LED5, LOW);
 
 
  // remember when we toggled it
  LED5_timer = millis (); 
  }  // end of toggle_LED5
 
  //LED 3 loop
void toggle_LED6 ()
  {
   if (digitalRead (LED6) == LOW)
      digitalWrite (LED6, HIGH);
   else
      digitalWrite (LED6, LOW);
 
 
  // remember when we toggled it
  LED3_timer = millis (); 
  }  // end of toggle_LED6
 
 
void loop ()
  {
 
 
  // Handling the blink of LED1.
  if ( (millis () - LED1_timer) >= LED1_ON_interval)
     toggle_LED1 ();
     // Handling the blink of LED1.
  if ( (millis () - LED1_timer) >= LED1_OFF_interval)
     toggle_LED1 ();
 
 
  // Handling the blink of LED2.
  if ( (millis () - LED2_timer) >= LED2_ON_interval)
    toggle_LED2 ();
     if ( (millis () - LED2_timer) >= LED2_OFF_interval)
    toggle_LED2 ();
   
// Handling the blink of LED3.
  if ( (millis () - LED3_timer) >= LED3_ON_interval)
    toggle_LED3 ();
    
      // Handling the blink of LED4.
  if ( (millis () - LED4_timer) >= LED4_ON_interval)
     toggle_LED4 ();
 
 
  // Handling the blink of LED5.
  if ( (millis () - LED5_timer) >= LED5_ON_interval)
    toggle_LED5 ();
   
// Handling the blink of LED6.
  if ( (millis () - LED6_timer) >= LED6_ON_interval)
    toggle_LED6 ();
   
/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */
 
 
}  // end of loop

Unwind a little.
Look again at blink without delay, and make it switch a single LED on for one second, and off for 10 seconds.
The key variable is "interval" - it's the only thing you need to change.

Please use code tags when posting code.

I think it a state machine of some sort is the answer (like the no-block blink that was suggested). I’m on the road and don’t happen to have an Arduino with me so I just illustrated an algorithm in processing.org.

This should work for any number of LEDs and you just change the array to change the timing. To run this, simply download processing.org and then paste this code into it and run. You should see six pretend LEDs on the screen that follow the pattern.

Processing.org is much like arduino except you draw things on the screen in the draw() method instead of flash real LEDs in the loop() method. By the way, processing.org might be a great way to practice developing algorithms and logic without worrying about the hardware…

If it isn’t clear what to do with this, don’t panic. I should be at my lab soon and will have an arduino I can try and can convert the code to Arduino. But if you’re a beginner sorting this out should be a good exercise. :slight_smile:

By the way, I didn’t test it much. I just ran it quickly and it looked sorta right.

//locations of LEDs
int [][] LED = {
   {50,50}
  ,{50,80}
  ,{50,110}
  ,{50,140}
  ,{50,170}
  ,{50,200}
};

color LEDon = color(255, 255,255);
color LEDoff = color(64, 64, 64);

//timing for LEDs
long [][] LEDtiming = {
   {1000,15000}
  ,{1000,16000}
  ,{1000,450000}
  ,{1000,1000}
  ,{1000,48000}
  ,{1000,50000}
};
int [] LEDstate = {0,0,0,0,0,0};
long [] LEDlastStateChange = {0,0,0,0,0,0};

void setup() {
  size(640, 480);
  background(0);
  
  for (int i = 0;i<=5;i++){
      color c = color(255, 204, 0);  // 
     fill(LEDon);                        // 
     //noStroke();  // Don't draw a stroke around shapes
     ellipse(LED[i][0], LED[i][1], 10, 10);  // Draw left circle
  }
}

void draw() {
  for (int i = 0;i<=5;i++) {
    if(millis() >= LEDlastStateChange[i] + LEDtiming[i][LEDstate[i]]) {
      LEDlastStateChange[i] = millis();
      if(LEDstate[i] == 0) {
        fill(LEDoff);
        LEDstate[i] = 1;
      }else{  
        fill(LEDon);
        LEDstate[i] = 0;
      }
      ellipse(LED[i][0], LED[i][1], 10, 10);
    }
  }

  stroke(255);
  if (mousePressed == true) {
    line(mouseX, mouseY, pmouseX, pmouseY);
  }

}
void draw() {

How to confuse the noob 101

aemartin6083:
const unsigned long LED1_ON_interval = 15000; //
const unsigned long LED2_ON_interval = 16000; //
const unsigned long LED3_ON_interval = 450000; //
const unsigned long LED5_ON_interval = 48000; //
const unsigned long LED6_ON_interval = 50000; //

There are better ways to write the code but based on your description of what the program should do compared to what it actually does... it seems to me that LED4 is working as desired. And if you change the rest of the "on" intervals to be:

const unsigned long LED1_ON_interval = 1000; //
const unsigned long LED2_ON_interval = 1000; //
const unsigned long LED3_ON_interval = 1000; //
const unsigned long LED5_ON_interval = 1000; //
const unsigned long LED6_ON_interval = 1000; //

That should do what you want, right?

Just a thought.

Regards,

Brad
KF7FER

I thought that changing the ON intervals would work, too! It didn't. It seems like it should, but for some reason it doesn't. Thank you for your help, though!

I will try the processing.org idea as well. Thank you all for your help!

Look carefully at the blink without delay example.
When you change the state of the LED, change the value of "interval".
It's that simple, and the arithmetic is correct and won't be affected by the timer roll over (even if the comparison isn't quite right)

aemartin6083:
I thought that changing the ON intervals would work, too! It didn't. It seems like it should, but for some reason it doesn't. Thank you for your help, though!

Oops - that's what I get for not looking close enough. Sorry.

AWOL had a good suggestion (as usual) to check out the blink without delay example.

Good luck,

Brad.

Make it easy on yourself, write code for one LED.
When you get that working, add another LED code section etc.

AWOL:
When you change the state of the LED, change the value of "interval".

Can you please show me what that looks like?

LarryD:
When you get that working ...

When you get that working, replace the control variables with arrays and use a for loop to apply the same logic to all the LEDs.

The processing.org code I cooked up earlier is the same thing as the no-block-blink.

I just added two intervals one for on and one for off. And also an array for the LEDs. So it's solved for N LEDs.

aemartin6083:

AWOL:
When you change the state of the LED, change the value of "interval".

Can you please show me what that looks like?

In the blink without delay example, find the bit of code that changes the LED from on to off, and from off to on.
Put a short code block around each of these with curly braces { }, and in each block, assign a different value to the variable "interval".
I'm sorry, I don't have source on my tablet.

Have you run the processing.org code I made to see if the timing is right?

AWOL is putting you on the right track. You are performing two timing tests each time. You should do one test against interval and just change interval when you toggle the led on or off. When he says assign a different value that's because = is the assignment operator. Different from == comparison for equality.

so:

interval = someNewValue;

or

interval = 10000;

will change the value of interval.

I can't download the proccesing.org on our school computers, and I don't understand most of the other suggestions. I don't know enough about the programming to understand what you mean about where to insert things. Is there not just a simple change she can make to the code she already wrote? It seems to be so close to what she's looking for, I don't want to give up on helping her, but understand if I'm not at a level yet where you can help me. I appreciate all of your suggestions and explanations, and apologize for my ignorance.

Maybe someone could re-post the original code that posted and show me what you mean by making changes directly on it? I understand that approach seems lazy of me, and if I was just working myself on learning to code, I would agree and want to work it out myself. But my student's history project is going to contest on Friday, and she just wants these lights to blink in a recreation of a historical artifact, and I just want to help her correct her small problem, and I don't know how. I have spent HOURS trying to figure this out, and I'm beginning to think it's just beyond my capability.

Here’s blink without delay, without comments.

const byte ledPin =  13;

byte ledState = LOW;    
unsigned long previousMillis;

unsigned long interval = 1000;

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

void loop()
{
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;   

    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    digitalWrite(ledPin, ledState);
  }
}

and here it is with an ON time of 1/10th of a second, and an OFF time of 9/10ths of a second.

const byte ledPin =  13;

byte ledState = LOW;    
unsigned long previousMillis;

unsigned long interval;
const unsigned long onTime = 100;
const unsigned long offTime = 900;

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

void loop()
{
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;   

    if (ledState == LOW) {
      ledState = HIGH;
      interval = onTime;
    } else {
    
      ledState = LOW;
      interval = offTime;
    }
    digitalWrite(ledPin, ledState);
  }
}

Can I suggest that when you implement this for all the LEDs required, that you incorporate a simple x10 mode to make testing less tedious?

For bonus marks, your implementation should not be more than about 10-20 lines longer than the one I showed.

Okay, this makes sense. But then how do I make that for multiple LEDs in the same code?

AWOL:
Here’s blink without delay, without comments.

const byte ledPin =  13;

byte ledState = LOW;   
unsigned long previousMillis;

unsigned long interval = 1000;

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

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

if(currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

digitalWrite(ledPin, ledState);
  }
}




and here it is with an ON time of 1/10<sup>th</sup> of a second, and an OFF time of 9/10<sup>ths</sup> of a second.


const byte ledPin =  13;

byte ledState = LOW;   
unsigned long previousMillis;

unsigned long interval;
const unsigned long onTime = 100;
const unsigned long offTime = 900;

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

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

if(currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

if (ledState == LOW) {
      ledState = HIGH;
      interval = onTime;
    } else {
   
      ledState = LOW;
      interval = offTime;
    }
    digitalWrite(ledPin, ledState);
  }
}




Can I suggest that when you implement this for all the LEDs required, that you incorporate a simple x10 mode to make testing less tedious?

For bonus marks, your implementation should not be more than about 10-20 lines longer than the one I showed.