Arduino: Independent On-Off Times with Millis()

When using delay() to flash a LED there is a time for the LED to be on and then off. This makes it easy to have independent control of the “on” and “off” times. The standard blink without delay example doesn’t give you this flexibility.

millis-cookbook-two-duty-cycles

This example code gives you complete independant control of how long a LED (or any OUTPUT pin) stays “ON” or “OFF”. This also demonstrates a very simple two-state state machine.

The variable “LED13state” is used to track what should happen each time the millis() event fires.

// On and Off Times (as int, max=32secs)
const unsigned int onTime = 1000;
const unsigned int offTime = 500;

// Tracks the last time event fired
unsigned long previousMillis=0;

// Interval is how long we wait
int interval = onTime;

// Used to track if LED should be on or off
boolean LED13state = true;

// Usual Setup Stuff
void setup() {
  pinMode(13, OUTPUT);
}

void loop() {
  // Set Pin 13 to state of LED13state each timethrough loop()
  // If LED13State hasn't changed, neither will the pin
  digitalWrite(13, LED13state);

  // Grab snapshot of current time, this keeps all timing
  // consistent, regardless of how much code is inside the next if-statement
  unsigned long currentMillis = millis();

  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillis) >= interval) {
    // Change wait interval, based on current LED state
    if (LED13state) {
      // LED is currently on, set time to stay off
      interval = offTime;
    } else {
      // LED is currently off, set time to stay on
      interval = onTime;
    }
    // Toggle the LED's state, Fancy, eh!?
    LED13state = !(LED13state);

    // Save the current time to compare "later"
    previousMillis = currentMillis;
  }
}

Long comments, URLs, and code tend to get flagged for spam moderation. No need to resubmit.

ALL comments submitted with fake or throw-away services are deleted, regardless of content.

Don't be a dweeb.

Leave a comment

56 thoughts on “Arduino: Independent On-Off Times with Millis()

  1. Hi There all

    I hope someone can help me here.

    So a quick question, I have a built a small greenhouse controller, with relays controlling the Humidifier and Temperature, that’s all working great with some sketch I found online.

    The question I`m asking is when the humidity drops in the greenhouse the relay kicks in and starts a fine mist spray system, which is great but goes continuously until the humidity is back up above the trigger level, what I want is for the relay once its on to stay on for say one minute then off again for ten and repeat, until the humidity is up high again

    I`m assuming its a very simple line of code to do that, but at this early stage in my learning of the code, I have no idea how to do that.

    So if anyone can tell me how, or point me in the right direction of how I can make the relay output stay on for a bit, go off and repeat, I would be very happy.

    Cheers Alan

    • The code on this example can do exactly that. The only caveat is when you setup the intervals. If you put something like “interval_OFF = 60000 * 10;” you’re going to run into a casting problem. So if you use inline math to calculate the interval, the compiler you intended to use an unsigned long, like this: “interval_OFF = 60000UL * 10UL;”

      Lastly you might want to look at Delayed Events after a Button Press. Of course you aren’t using a button press in this case, but it shows how to “trigger” a timer.

  2. How would you/ or can you, go about using this to delay the on/off of a relay?
    Would it be the same as the LED

    Yes, it’s the same.

    • Thank you, I can get your sketch working, and have played with it a bit within the scope of the LED’s. I wondered if you have another tutorial similar to this but dealing with temperature or other variable that is not directly controlled by the user… (more of an if/then). Such as temp or other such sensor controls the LED(s), but the LED(s) stay on/off for set time before resetting to the original if/then condition. I get how this works by looking at the previous state, but either overthinking or missed how this could be used in something like my example where on or off is set by an IF statement, but delayed where the rest of the code still runs.

  3. I am doing a double traffic light project that also has a button, for pedestrian crossing, and a photo-sensor, for emergency vehicles. I’m trying not to use delay(); since if I press the button while the lights are on the program is on pause and won’t respond.

  4. Hi James.
    I am new to arduino, and want to control 3 or 4 relays, triggering at different times, in sequence of each other. However the timing in between each step is not the same. I’ve writtin the code using “delay”, as it was the first example I got, and seemed easy. Now its restricting me to go further, and for example have an count down timer indicating time left untill all steps are completed. Please note the time I’ve put in is only for testing.The actual times are 1-8hours.

    See below:

    int right=8;//right relay//
    int left=10;//left relay//
    int down=13;//down relay//
    int ButtonTwo=2;//trigger 2 day programme//
    int ButtonFive=4;//trigger 5 day programme//
    int ButtonSeven=7;//trigger 7 day programme//
    
    
    void setup() { //Setup runs once//
    
      pinMode(right, OUTPUT); //Set right as an output//
      pinMode(left, OUTPUT); //Set left as an output//
      pinMode(down, OUTPUT); //Set down as an output//
      pinMode(ButtonTwo, INPUT_PULLUP); //Set twoDay as an input//
      pinMode(ButtonFive, INPUT_PULLUP); //Set fiveDay as an input//
      pinMode(ButtonSeven, INPUT_PULLUP); //SetsevenDay as an input
    
    }
    
    void loop() { //Loop runs forever//
      if(digitalRead(ButtonTwo)==LOW)
      {
      delay(1000);            //for 3.5 seconds//  
      digitalWrite(right,HIGH); //Motor runs clockwise, Step 1// 
      delay(1000);            //for 3.5 seconds// 
      digitalWrite(right, LOW); //Motor stops//
      delay(1000);              //Motor right wait for 2hours//
      digitalWrite(left,HIGH); //Motor runs left//
      delay(1000);            //for 1 second//
      digitalWrite(left,LOW); //Motor left Stops//
      delay(1000);            //Motor left stop for 1 second//
      digitalWrite(left,HIGH); //Motor runs left//
      delay(1000);            //for 1 second//
      digitalWrite(left,LOW); //Motor left Stops//
      delay(1000);            //Motor left stop for 1 Second//
      digitalWrite(left,HIGH); //Motor runs left, Step 4//
      delay(1000);            //for 1 second//
      digitalWrite(left,LOW); //Motor left Stops//
      delay(1000);
      digitalWrite(right,HIGH); //Motor runs clockwise, // 
      digitalWrite(down,HIGH); //Motor runs down, //
      delay(1000);            //for 3.5 seconds//  
      digitalWrite(right, LOW); //Motor stops//
      digitalWrite(down, LOW); //Motor stops//
      delay(1000);
    

    And so it goes on to five and seven day as well.

      • James, I was able to get your Arduino code to work. I do have a particular problem I’m trying to solve using the Arduino though. I’m using a 12v LED and having to power it with a separate power source using a transistor. What I need the LED to do is (1) when a switch is closed LED is off (2) When switch first opens the LED flashes briefly then turns off. I have a circuit that works, but to throw an additional issue into the mix, I can only run one wire to the LED due to physical limitations. The circuit I have connects the LED to +12vdc then to the drain of a transistor. I do have the ability to run a ground to the case from one side of the LED. Would you happen to have any suggestions.

  5. I am trying to calculate the time after occurrence of two different events (cool and heat), totally independent from each other.  for starting cooling I have to wait for a specific time from last turn off, if time interval is reached and temperature condition also satisfied the cool function will start but heat should not start at same time. for heat also need to check the time from last turn off to now and by satisfying temperature condition  the heat function will start. I tried to use millis but millis is turning on both functions with a very slight time difference. How i can use millis to independently monitor time interval for two independent tasks.

  6. wow, this great, thanks for sharing,…
    how if I use 3 or more led with diffrent on time and off time?

    blinkLed(red, 50, 1000); //led color, on delay, off delay
    blinkLed(blue, 500, 50); //led color, on delay, off delay
    blinkLed(green, 1000, 2000); //led color, on delay, off delay