Need help with millis and a momentary switch

Hi All

This is my first post to the Arduino forum, but I have a couple of Arduino's (one duemilanove and one mega) and I've been an avid reader and already picked up lots of tips :slight_smile:

I have a simple sketch that when a momentary switch is pressed 2 LEDs blink on and off independently, but as I'm using 'delay' the first one blinks and then the second one blinks.
I would like them to blink at the same time but with independent delays when the momentary switch is pressed. I have had a look at the 'blink with out delay' code but I can't figure out how I can make it work with my sketch?
It may be really simple to fix but I've only done basic coding before!

Thanks

Dan

const int ledPin1 = 2;
const int ledPin2 = 3;
const int enablePin = 8;

int enableState = 0;

void setup(){
     pinMode (ledPin1, OUTPUT);
     pinMode (ledPin2, OUTPUT);
     pinMode (enablePin, INPUT);
}

void loop(){
  enableState = digitalRead(enablePin);
  if (enableState == HIGH){   
    digitalWrite(ledPin1, HIGH);
    delay(200);
    digitalWrite(ledPin1, LOW);
    delay(1500);
    digitalWrite(ledPin1, HIGH);
    delay(800);
    digitalWrite(ledPin1, LOW);
    delay(1000);
    digitalWrite(ledPin1, HIGH);
    delay(500);
    digitalWrite(ledPin1, LOW);    

    digitalWrite(ledPin2, HIGH); 
    delay(300);
    digitalWrite(ledPin2, LOW);
    delay(1900);
    digitalWrite(ledPin2, HIGH);
    delay(400);
    digitalWrite(ledPin2, LOW);
    delay(1200);
    digitalWrite(ledPin2, HIGH);
    delay(700);
    digitalWrite(ledPin2, LOW);
  }
  else if (enableState == LOW){
    digitalWrite (ledPin1, LOW);
    digitalWrite (ledPin2, LOW);
  }
}
You could just interleave the two patterns.  Start by noting when each action takes place:
[quote]
Time
    0    digitalWrite(ledPin1, HIGH);
 200    digitalWrite(ledPin1, LOW);
1700    digitalWrite(ledPin1, HIGH);
2500    digitalWrite(ledPin1, LOW);
2600    digitalWrite(ledPin1, HIGH);
3100    digitalWrite(ledPin1, LOW);    

    0     digitalWrite(ledPin2, HIGH); 
 300     digitalWrite(ledPin2, LOW);
2200    digitalWrite(ledPin2, HIGH);
2600    digitalWrite(ledPin2, LOW);
3800    digitalWrite(ledPin2, HIGH);
4500    digitalWrite(ledPin2, LOW);
[/quote]

Sort by time:
[quote]
Time
    0    digitalWrite(ledPin1, HIGH);
    0     digitalWrite(ledPin2, HIGH); 
 200    digitalWrite(ledPin1, LOW);
 300     digitalWrite(ledPin2, LOW);
1700    digitalWrite(ledPin1, HIGH);
2200    digitalWrite(ledPin2, HIGH);
2500    digitalWrite(ledPin1, LOW);
2600    digitalWrite(ledPin1, HIGH);
2600    digitalWrite(ledPin2, LOW);
3100    digitalWrite(ledPin1, LOW);    
3800    digitalWrite(ledPin2, HIGH);
4500    digitalWrite(ledPin2, LOW);
[/quote]

Then calculate the delays to put in:

digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, HIGH);
delay(200);
digitalWrite(ledPin1, LOW);
delay(100);
digitalWrite(ledPin2, LOW);
delay(1400);
digitalWrite(ledPin1, HIGH);
delay(500);
digitalWrite(ledPin2, HIGH);
delay(300);
digitalWrite(ledPin1, LOW);
delay(100);
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
delay(500);
digitalWrite(ledPin1, LOW);
delay(700);
digitalWrite(ledPin2, HIGH);
delay(700);
digitalWrite(ledPin2, LOW);
[/quote]

That does't sound like one way around it....... However the ultimate aim is to have the variable delay instead of a fixed delay for each action, so I'm not too sure how this would work for that instance?

Dan

If you want variable sequences happening asynchronously you will need to store the patterns in arrays, keep an index pointer for each, use a separate BlinkWithoutDelay timer for each.

I'm so sorry john I had a typo in my last comment, I didn't mean to say "that doesn't seem like the way round it", I meant to say "that does seem one way around the problem"

However as you quite rightly say that I need various sequences happening asynchronously. I do plan on using an array for storing the "delay" data at the moment I write the data into an array via serial....... this part of my code works; would you be able to give me an idea of how to use an array with a "blink without delay timer'"?

Thanks again

Like I said before: Start with the BlinkWithoutDelay example. Make an array of delay times (for each LED). Make an array index for each LED.

Something like this:

const int led1Pin =  13;      // the number of the LED pin
int led1Delays[10] = {200,1500,800,1000,500}
int led1Count = 5;
int led1Index = 0;
bool led1State = 0;             // ledState used to set the LED
long led1PreviousMillis = 0;  // will store last time LED was updated

void setup() {
  // set the digital pin as output:
  pinMode(led1Pin, OUTPUT);
  digitalWrite(led1Pin, led1State);      
}

void loop()
{
  unsigned long currentMillis = millis();
 
/////  Beginning of code for one LED
  if(currentMillis - led1PreviousMillis > led1Delays[led1Index]) 
    {
    led1PreviousMillis = currentMillis;   
    led1State = ! led1State;
    digitalWrite(led1Pin, led1State);
    led1Index = (led1Index+1) % led1Count;
  }
/////  End of code for one LED
 
  //  Repeat the above code for led2, led3, etc...
  // If you have more than about three simultaneous patterns it starts to make sense to put EVERYTHING in arrays
  // and loop through the arrays rather than duplicating the code.
}

Hi John

Thank you very much for this, is works like a charm, I've added a few lines of code so that this will work with a momentary switch press, it's a little crude but it does the job :slight_smile:

Here's the modified sketch.............. although there's a little way to go until I finish the whole project.

const int led1Pin =  2;      // the number of the LED pin
const int led2Pin =  3;      // the number of the LED pin
const int startPin = 8;
int led1Delays[10] = {1000,5000,1200,6000,1500,7000,100};
int  led1Count = 7;
int led1Index = 0;
bool led1State = 0;             // ledState used to set the LED
long led1PreviousMillis = 0;  // will store last time LED was updated
int led2Delays[10] = {1200,5500,1000,6600,2000,7500,100};
int  led2Count = 7;
int led2Index = 0;
bool led2State = 0;             // ledState used to set the LED
long led2PreviousMillis = 0;  // will store last time LED was updated
int startState = 0;  // 
int startPinState = 0;  // State of the momentary start button, this will be kept high until the the arduino has finished cycling through the led arrays
int cycleCount = 0;  // Keep track of the number of times that the loop has cycled around

void setup() {
  // set the digital pin as output:
  pinMode (startPin, INPUT);
  pinMode(led1Pin, OUTPUT);
  digitalWrite(led1Pin, led1State);
  pinMode(led2Pin, OUTPUT);
  digitalWrite(led2Pin, led2State);
  Serial.begin(9600);
}

void loop()
{
  startState = digitalRead(startPin);
  if (startState == HIGH || startPinState == 1)
  {
    startPinState = 1;
    unsigned long currentMillis = millis();
 
/////  Beginning of code for one LED
    if(currentMillis - led1PreviousMillis > led1Delays[led1Index]) 
    {
      led1PreviousMillis = currentMillis;   
      led1State = ! led1State;
      digitalWrite(led1Pin, led1State);
      led1Index = (led1Index+1) % led1Count;
    }
    if(currentMillis - led2PreviousMillis > led2Delays[led2Index]) 
    {
      led2PreviousMillis = currentMillis;   
      led2State = ! led2State;
      digitalWrite(led2Pin, led2State);
      Serial.println ("led2Index= ");
      Serial.println (led2Index);
      led2Index = (led2Index+1) % led2Count;
      Serial.println ("cyclecount= ");
      Serial.println (cycleCount);
      cycleCount = cycleCount + 1;
    }
    if (cycleCount == 8)
    {
       startPinState = 0;
       cycleCount = 0;
    }
/////  End of code for one LED
 
  //  Repeat the above code for led2, led3, etc...
  // If you have more than about three simultaneous patterns it starts to make sense to put EVERYTHING in arrays
  // and loop through the arrays rather than duplicating the code.
  }
}

Cheers

Dan