How to blink 3 leds at different time intervals

Hi I am working on a simple clock with 3 leds. I want to have one blink every second, another to blink every minute, and the last one to blink every hour. I have this code so far:
int hour = 13;
int minute = 12;
int second = 11;
void setup() {

pinMode(hour, OUTPUT);
pinMode(minute, OUTPUT);
pinMode(second, OUTPUT);
}

void loop() {
digitalWrite(second, HIGH);
delay(1000);
digitalWrite(second, LOW);
delay(1000);

I only put the led for seconds in the loop but where do I put code for the "minute" led and "hour" led.

Please help the newbie!!! :grin: :grin: :grin:

_clay

Read and understand http://arduino.cc/en/Tutorial/BlinkWithoutDelay, then generalise it to more than one LED.

Hello and welcome,

I know how, by NOT using delay() :slight_smile:

I will post a more complete answer once you answer this question: how long the LEDs should stay ON?

  1. Keep track of time in seconds;
  2. At each second increment, blink the second led;
  3. At each minute increment, blink the minute led;
  4. At each hour increment, blink the hour led.

One led blinks every second,
The second blinks every minute,
The third blinks every hour.
Can you be more specific about how to do it with and without delay???

i_luv_arduino:
One led blinks every second,
The second blinks every minute,
The third blinks every hour.

Do you mean:

The seconds LED is ON for one second, OFF for one second
The minutes LED is ON for one minutes, OFF for one minute
The hours LED is ON for one hour, OFF for one hour

?

Sorry I mean the seconds led is on for 500 milliseconds, off for 500 milliseconds
the minute led is on for 30 seconds and off for 30 seconds, the hour led is on for 30 minutes and off for 30 minutes, one led blinks once PER second another once PER minute another once PER hour.

The main example for the Run library, available here: GitHub - billroy/run: Arduino function scheduler library: runs your C function at a specified interval, like the Bitlash run command shows how to blink two LEDs at different rates using the Run library. You could extend that example, but of course it's best if you understand what's going on by studying the BlinkWithoutDelay example.

You've got three little tasks, each with its own timeline. You can't use delay in any of them because it disrupts the scheduling for all of them. Each light needs its own scheduled time for the next thing to happen.

-br

Something like that should work (not tested, might be bugged but it's just an example :)):

uint32_t
  time_now  = 0,
  time_past = 0;
  
uint8_t
  half_seconds    = 0,
  seconds         = 0,
  minutes         = 0,
  LED_seconds_pin = 11,
  LED_minutes_pin = 12,
  LED_hours_pin   = 13;

bool
  LED_seconds_state = false,
  LED_minutes_state = false,
  LED_hours_state   = false;

void setup()
{
  pinMode( LED_seconds_pin, OUTPUT );
  pinMode( LED_minutes_pin, OUTPUT ); 
  pinMode( LED_hours_pin,   OUTPUT ); 

  time_past = millis();
}

void loop()
{
  time_now = millis();

  //every 500 milliseconds
  if ( time_now - time_past >= 500 )
  {
    time_past = time_now;

    //toggle LED_seconds
    LED_seconds_state = !LED_seconds_state;
    digitalWrite( LED_seconds_pin, LED_seconds_state );

    //every seconds
    if ( ++ half_seconds >= 2 )
    {
      half_seconds = 0;
      
      //every 30 seconds
      if ( ++ seconds >= 30 )
      {
        seconds = 0;

        //toggle LED_minutes
        LED_minutes_state = !LED_minutes_state;
        digitalWrite( LED_minutes_pin, LED_minutes_state );

        //every 30 minutes
        if ( ++ minutes >= 30 )
        {
          minutes = 0;

          //toggle LED_hours
          LED_hours_enabled = !LED_hours_enabled;
          digitalWrite( LED_hours_pin, LED_hours_state );
        }
      }
    }
  }
}

I happen to have a sketch that does this. I wrote it to learn more about OOP techniques and to see what kind of overhead is involved. It's straight forward.

It's basically a blinking led class that has public variables for setting on and off durations or turning blinking on / off. In this case I just instance three leds and give them the appropriate on and off durations. This is only tested with one led but should work.

// durations in millis change to suit
// you can also set led.onDuration and led.offDuration directly

// Blinker class
class Blinker
{
    byte _ledPin;                                                  // pin led is at
    boolean _ledOn;                                                // status flag on is true
    unsigned long _lastToggleMillis;                               // time last toggled
    unsigned long _duration;                                       // for checking time

public:
    unsigned long onDuration;                                      // time led spends on
    unsigned long offDuration;                                     // time led spends off
    boolean blinkOn;                                               // blink or not

    Blinker(byte);                                                 // default expects pin led attached to
    void begin(unsigned long, unsigned long);                      // initilaizes led pin passed values are on and off time in millis
    boolean check(void);                                           // called to check and do blinking
};

// default constructor
// requires pin of led, assigned to _ledpin inits others
Blinker::Blinker(byte pin)
{
    _ledPin = pin;
    _lastToggleMillis = 0;
    _duration = 0;
    _ledOn = false;
    blinkOn = false;
}

// Blinker::begin()
// call at setup inits pin assigns on and off values
void Blinker::begin(unsigned long on, unsigned long off)
{
    pinMode(_ledPin, OUTPUT);                                      // set led pin to output
    onDuration = on;
    offDuration = off;
}

// Blinker::check()
// turns led on or off
boolean Blinker::check()
{
    if (!blinkOn) return false;                                    // only blink if blink on
    if (millis() - _lastToggleMillis > _duration)                  // decide if action needed
    {
        if (_ledOn)                                                // use the ledOn flag to test the led state
        {
            digitalWrite (_ledPin, LOW);                           // its on so turn it off
            _ledOn = false;                                        // clear the flag
            _lastToggleMillis = millis();                          // set  time
            _duration = offDuration;                               // set duration for this state
        }
        else
        {
            digitalWrite (_ledPin, HIGH);                          // its off so turn it on
            _ledOn = true;                                         // set the flag
            _lastToggleMillis = millis();                          // set next action time
            _duration = onDuration;                                // set duration for this state
        }
    }
    return true;
}

// create our led instances
Blinker everySecondLed(11);                                        // Blinker needs pin led attached to
Blinker everyMinuteLed(12);
Blinker everyHourLed(13);

void setup()
{
    everySecondLed.begin(500, 500);                     // starts our led object sets on and off durations
    everyMinuteLed.begin(30000, 30000);                    
    everyHourLed.begin(1800000, 1800000);                    

    everySecondLed.blinkOn = true;                      // turn on blinking
    everyMinuteLed.blinkOn = true;                        
    everyHourLed.blinkOn = true;                        
}

void loop()
{
    everySecondLed.check();                             // call check function
    everyMinuteLed.check();                             
    everyHourLed.check();                               
}

So can I just copy, paste and download, like a code or should I chan it a bit???

If you want to learn how to make it work on your own, I created 5 steps (or exercises) to get you from delay() to using millis().

(Or you could just try skipping to #5 and playing with the timing variables).

http://www.cmiyc.com/blog/2011/01/06/millis-tutorial/

  //every 500 milliseconds
  if ( time_now - time_past >= 500 )
  {
    time_past = time_now;

Some thing like that will drift over time. Instead, use this:

#define TIM_STEP 500 //timing step is 500ms

  //every 500 milliseconds
  if ( millis() - time_past >= TIM_STEP )
  {
    time_past += TIM_STEP;

time_past is initialized either in setup(); or in loop() as a static.

The timing accuracy of this approach is only dependent on the crystal.

Thank you guix it works, except when its been 30 seconds it stays on for another 30 seconds. I want it so when 60 seconds is up it blinks once and then when 60 seconds is up again it blinks again, same with hours please.thanks

I want it so when 60 seconds is up it blinks once and then when 60 seconds is up again it blinks again, same with hours please.

Blinking is not something a pin can do. A pin can turn on. A pin can turn off. By turning the pin on, pausing, turning the pin off, pausing, and repeating, the LED connected to the pin can appear to blink.

So, far, you haven't defined how long the pause while the pin is on should be, so the fact that it is not to your liking is hardly surprising.

one goes on for 500 milliseconds and then goes off for 500 milliseconds
another goes on after 30 seconds and stays on for the next 30 seconds
another goes on after 60 minutes and stays on for the next 60 minutes
any way its fine heres my code:

uint32_t
  time_now  = 0,
  time_past = 0;
  
uint8_t
  half_seconds    = 0,
  seconds         = 0,
  minutes         = 0,
  LED_seconds_pin = 11,
  LED_minutes_pin = 12,
  LED_hours_pin   = 13;

bool
  LED_seconds_state = false,
  LED_minutes_state = false,
  LED_hours_state   = false;

void setup()
{
  pinMode( LED_seconds_pin, OUTPUT );
  pinMode( LED_minutes_pin, OUTPUT ); 
  pinMode( LED_hours_pin,   OUTPUT ); 

  time_past = millis();
}

void loop()
{
  time_now = millis();

  //every 500 milliseconds
  if ( time_now - time_past >= 500 )
  {
    time_past = time_now;

    //toggle LED_seconds
    LED_seconds_state = !LED_seconds_state;
    digitalWrite( LED_seconds_pin, LED_seconds_state );

    //every seconds
    if ( ++ half_seconds >= 2 )
    {
      half_seconds = 0;
      
      //every 30 seconds
      if ( ++ seconds >= 60 )
      
      {
        seconds = 0;

        //toggle LED_minutes
        LED_minutes_state = !LED_minutes_state;
        digitalWrite( LED_minutes_pin, LED_minutes_state );

        //every 30 minutes
        if ( ++ minutes >= 30 )
        {
          minutes = 0;

          //toggle LED_hours
          LED_hours_pin = !LED_hours_pin;
          digitalWrite( LED_hours_pin, LED_hours_state );
        }
      }
    }
  }
}

thanks!

It works so I am going to remove this page k?

It can help other people so don't delete it :slight_smile:

hi guys, I´m a newbie and this code helped me a lot , I modified it a bit since what I want to do is a bit different and simpler I think . The code is working but is erratic , after sometime the yellow led doesn´t go high and some other misconduct.
what i want to do do i that while input is low green led is high , when input goes high , green led goes low yellow led starts blinking and after sometime yellow led goes low ,red led blinks .
Meanwhile the other green leds should be blinking in order .
I´ll paste the code here hoping I can get some help , I know I used some delays and maybe they are messing with the time variables , i was planning on blinking the leds whitout delay after I solved the basics.

Thanks for any help.

the circuit :

Code :

int buttonPin= 5;
int currentButtonState;
int previousButtonState;
unsigned long buttonPressTime;
unsigned long currentTime;
unsigned long waitPeriod = 3000;
boolean timing = true;

int red=13;
int yellow=12;
int green=11;
int gr1=8;
int gr2=9;
int gr3=10;

unsigned long
time_now = 0,
time_past = 0;

uint8_t
half_seconds = 0,
seconds = 0,
minutes = 0,
LED_seconds_pin = 8,
LED_minutes_pin = 9,
LED_hours_pin = 10;

bool
LED_seconds_state = false,
LED_minutes_state = false,
LED_hours_state = false;

void setup()
{
Serial.begin(115200);
pinMode(buttonPin, INPUT);
pinMode(red,OUTPUT);
pinMode(yellow,OUTPUT);
pinMode(green,OUTPUT);
pinMode(gr1,OUTPUT);
pinMode(gr2,OUTPUT);
pinMode(gr3,OUTPUT);

pinMode( LED_seconds_pin, OUTPUT );
pinMode( LED_minutes_pin, OUTPUT );
pinMode( LED_hours_pin, OUTPUT );

time_past = millis();
}

void loop()
{

currentTime = millis();
previousButtonState = currentButtonState;
currentButtonState = digitalRead(buttonPin);

//wave();

if ( timing)
{
if (currentButtonState != previousButtonState && currentButtonState == LOW)//input gone LOW
{
Serial.println("\nTiming started Gled ON");
buttonPressTime = currentTime;
timing = false;
gledstrip();
}
}
else if (currentButtonState != previousButtonState && currentButtonState == HIGH)//input gone HIGH
{
//timing = false;
timing = true;
yledstrip();
}
if ((currentTime - buttonPressTime >= waitPeriod) && timing && currentButtonState == HIGH)
{
timing = true;
rledstrip();
}
}

void gledstrip()
{
Serial.println("Input went LOW");
digitalWrite(red,LOW);
digitalWrite(yellow,LOW);
digitalWrite(green,HIGH);

}

void yledstrip()
{
Serial.println("Input went HIGH within 3 seconds Yled ON");
digitalWrite(green,LOW);
delay(200);
digitalWrite(yellow,HIGH);

}

void rledstrip()
{
Serial.println("Input still HIGH after 3 seconds Rled ON");
digitalWrite(yellow,LOW);
delay(500);
digitalWrite(red,HIGH);
delay(500);
digitalWrite(red,LOW);
//delay(500);
}

I can't see your picture because I'm behind a firewall that thinks that the site you posted the picture too is a virus infected site.

Describe how the switch is wired, AND why you didn't use the far simpler INPUT_PULLUP mode and wiring (one leg to ground; the other leg to the digital pin; no external resistor).