using MsTimer2 to blink LED's

Hey guys, I have been trying to figure out how to get four LED's to blink at different times. The program I am writing is supposed to make one LED blink every second, one blink every 5 seconds, one every 10 seconds, and one every 30 seconds. I have been able to get one LED to blink but not all four. On top of that, when I get the one to blink it stays off as long as it stays on. So if i passed in a value of 5000, the LED stays off for 5 seconds, then on for 5 seconds, and so on. Thanks for the help, it is much appreciated!

Here is my current code:

#include <LiquidCrystal.h>
#include <MsTimer2.h>

LiquidCrystal lcd(12, 11, 10, 7, 6, 5, 4);

int LCD_LENGTH = 15;
int time = 0;
int select = 9;
boolean running = false;
//int less = 3;
//int more = 2;
int led1 = 13;
int led2 = 8;
int led3 = 1;
int count = 0;
int fiver = 0;
int tener = 0;
//int led4 = 0;

/*void flash() {
static boolean output = HIGH;

digitalWrite(13, output);
output = !output;
}*/

void flash()
{
led1 = !led1;
if(count < 4)
count++;
else
count = 0;

led2 = !led2;
if(fiver < 1)
fiver++;
else
fiver = 0;

led3 = !led3;
if(tener < 2)
tener++;
else
tener = 0;

//static boolean output = HIGH;
//digitalWrite(8, output);
//output = !output;
}

/*void flash10() {
static boolean output = HIGH;

digitalWrite(1, output);
output = !output;
}

void flash30() {
static boolean output = HIGH;

digitalWrite(0, output);
output = !output;
}*/

void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
//pinMode(0, OUTPUT);

lcd.begin(16, 2);
lcd.clear();
lcd.print("Input your time");
delay(1500);
lcd.clear();
attachInterrupt(0, lessISR, FALLING);
attachInterrupt(1, moreISR, FALLING);
pinMode(select, INPUT);
digitalWrite(select, HIGH);

MsTimer2::set(5000, flash); // 1 second period
//MsTimer2::set(5000, flash5); // 5 second period
//MsTimer2::set(10000, flash10); // 10 second period
//MsTimer2::set(30000, flash30); // 30 second period
MsTimer2::start();
}

void loop()
{
lcd.clear();
lcd.setCursor(0,1);
lcd.print("Time: ");
lcd.setCursor(7,1);
lcd.print(time, DEC);
delay(200);
if (digitalRead(select) == LOW)
{
delay(time);
running = !running;

}

}

void lessISR()
{
if(time > 0)
{
for(int i = 5000; i > 0; i--)
{
time--;
}
}
}

void moreISR()
{
for(int i = 5000; i > 0; i--)
{
time++;
}
}

p.s. - sorry for the comments :P.

I just tried this code, and while it seems to do something, I am not sure what. I don't see why it wouldn't work though.

void flash()
{
static boolean led = HIGH;

if(count != 5 && count != 10 && count != 15 && count != 20 && count != 25 && count != 30)
{
digitalWrite(13, led);
led = !led;
count++;
delay(500);
}

if(count == 5 || count == 15 || count == 25)
{
digitalWrite(8, led);
led = !led;
count++;
delay(500);
}

if(count == 10 || count == 20)
{
digitalWrite(1, led);
led = !led;
count++;
delay(500);
}

if(count == 30)
{
digitalWrite(0, led);
led = !led;
count = 0;
delay(500);
}
}

You don't need MsTimer2 and interrupts for this.

You can use millis() to determine when now is, and use that to determine if it is time to turn an LED on or off.

const byte ledPins[] = { 13, 8, 1, 4 };

unsigned long ledOn[4];
unsigned long ledOff[4];
int ledStatus[4];

unsigned long ledTime[4] = { 1000, 5000, 10000, 30000 };

void setup()
{
   unsigned long now = millis();
   for(byte b=0; b<4; b++)
   {
      pinMode(ledPin[b], OUTPUT);
      ledOn[b] = now;
      ledOff[b] = ledOn[b] + ledTime[b];
      digitalWrite(ledPin[b], HIGH);
      ledStatus[b] = HIGH;
   }
}

void loop()
{
   unsigned long now = millis();
   for(byte b=0; b<4; b++)
   {
      if(ledStatus[b] == HIGH) // The LED is on
      {
         if(now > ledOff[b]) // it's time to turn the LED off
         {
            ledOff[b] = now;
            ledOn[b] = now + ledTime[b];
            digitalWrite(ledPin[b], LOW);
            ledStatus[b] = LOW;
         }
      }
      else // The LED is off
      {
         if(now > ledOn[b]) // it's time to turn the LED on
         {
            ledOn[b] = now;
            ledOff[b] = now + ledTime[b];
            digitalWrite(ledPin[b], HIGH);
            ledStatus[b] = HIGH;
         }
      }
   }
}

This code (not tested) will keep track of data for 4 LEDs - what pin it is on, whether it is on or off, when it was turned on or off, how long it should be on or off, and when it should next be turned on or off.

Each time through loop, it checks all the on LEDs to see if it is time to turn them off. If it is, it turns the LED off, records the time, records the status, and record when to turn the LED back on.

It also checks the off LEDs to see if it is time to turn them on. If it is, it turns the LED on, records the time, records the status, and record when to turn the LED back off.

oh, i see. I will have to give some of this a try and see how it goes. In case you could not tell from my code, I am having the interrupts for two switches that increment and decrement time, then a select button in order to start the time (and to pause it was the plan), in which the LED's would then blink according to the time. Thanks for the help!

My way does not block, so, again you don't need interrupts. Loop is called often enough that simply polling the switches on each pass will be sufficient.

I just tried your way, and it seems to work pretty well. The one thing I noticed it does that mine did as well is that the LED's will stay on for as long as they are off. Such as the 30 second LED will stay on for 30 seconds then off for 30 and so on. Is there a way I can get the LED to wait 30 seconds then blink for a split second, wait for 30 seconds then blink, and so on?

That's sort of the definition of blink - on and off for the same length of time. But, it doesn't have to be that way.

I defined an array, ledTime, that defines how long the LEDs are on or off.

You could copy that array, and rename it and the copy:

unsigned long ledTimeOn[4] = { 1000, 5000, 10000, 30000 };
unsigned long ledTimeOff[4] = { 100, 100, 100, 100};

Change all occurrences of ledTime to either ledTimeOn or ledTimeOff, as appropriate.