I know I should post some code that maybe cleaner but really I am just in need of a answer to a problem I seem to run into a lot when using mills() in place of delay(), whilst making a Christmas light display.

Maybe it's me but I do not get contestant switching over of mechanical relays when I try to use mills() timing to switch relays . I seems like the code trips the relay then untrips the relay in milliseconds and not really latching the relay like I get with delay(). Is this the nature of the mills() choice where the output is triggered every cycle but is not truly an output during the whole process cycle? Now if this is true, then is there a good way to latch a relay with out using a delay()?

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

  unsigned long currentMillis = millis();
  unsigned long previousMillis = millis();
  int interval_on = 2000; //  Length of time On

  unsigned long currentMillis_off = millis();
  unsigned long previousMillis_off ;
  int interval_off = 2000; // length of time off

#define button 4
int Lite_1=0;

RF24 radio(7, 8); // CE, CSN

const byte address[6] = "00001";
boolean buttonState = 0;

unsigned long time;

void setup() {

void loop() {
  unsigned long currentMillis = millis();        // must be in loop
   unsigned long currentMillis_off = millis();  // Must be in loop
  //                             const char text[] = "Hello World";
 //                       radio.write(&text, sizeof(text));

   //                       delay(5); Removed to help in timing
   //                       radio.stopListening(); removeded to help in timing 
   // Lite_1 = 1;
    radio.write(&Lite_1, sizeof(Lite_1));
  //    delay(1000);
 //   Lite_1 = 0 ;
 // radio.write(&Lite_1, sizeof(Lite_1));
  // delay(250);

  if (Lite_1 == 0 && currentMillis - previousMillis > interval_off) 
    previousMillis = currentMillis;
    previousMillis + 10;
    previousMillis_off = currentMillis_off  ;
    Lite_1 = 1;
    Serial.println(currentMillis);    //prints time since program started
  // Serial.print("Time: ");
 // time = millis();

 // Serial.println(time);    //prints time since program started
//  Serial.println(currentMillis);    //prints time since program started
//  Serial.println(previousMillis);    //prints time since program started
//  Serial.println(previousMillis_off);    //prints time since program started
 // Serial.println(currentMillis_off);    //prints time since program started

    if (Lite_1==1 && currentMillis_off - previousMillis_off > interval_on) 
    previousMillis_off = currentMillis_off;
    previousMillis = currentMillis;
    previousMillis + 10;
    Lite_1 = 0;
    Serial.print("OFF: ");
    Serial.println(previousMillis_off);    //prints time since program started

  • Format your code correctly by editing your question,selecting the code and click the {} button in the editors toolbar or press Ctrl+k on the keyboard.
    – chrisl
    Nov 1 '18 at 1:55
  • At which part of the code do you switch the relays? I don't see any digitalWrite() or similar, which could be used to switch something. Only Serial output.
    – chrisl
    Nov 1 '18 at 1:58
  • What should it do? Is it to turn on the relay half a second with 2 seconds in between? Is that continuous or is that triggered by an event? Please add the extra information to your question.
    – Jot
    Nov 1 '18 at 7:34
  • Ron, you can't answer comments until you register to SE. Check your email.
    – Juraj
    Nov 1 '18 at 8:02
  • Can you explain the role of nrf24L01 in this code? There may be other ways to achieve the functionality that you need.
    – MichaelT
    Nov 3 '18 at 12:42

Something like this works.

  unsigned long currentMillis;
  unsigned long previousMillis;
  unsigned long nextEventTime;

  unsigned long interval_on  = 2000;        // length of time On
  unsigned long interval_off = 2000;        // length of time off

  bool Lite_1;

  void setup() {

    previousMillis = millis();

    Lite_1 = false;                                     // start at the begining of the off cycle
    nextEventTime = previousMillis + interval_off;      // start at the begining of the off cycle

    Serial.print("starting in OFF cycle\t");

  void loop() {

    if (millis() > nextEventTime) {                     // check the interval before doing any other checks

    currentMillis = millis();

    if (Lite_1) {

      nextEventTime = currentMillis + interval_off;     // do the calculation only once

    } else {

      nextEventTime = currentMillis + interval_on;

    Lite_1 = !Lite_1;                           // invert value
    Serial.println(currentMillis);              // prints time since program started
  • When a value is added to a value from millis, and then compared to millis, that causes a rollover problem. Always subtract a previous millis from the current millis.
    – Jot
    Nov 1 '18 at 7:36
  • Then how would I do this math if I can not add to the Millis()? Nov 5 '18 at 0:01
  • 1
    I believe the way to make that work is nextEventTime - currentMillis > interval_of. Informally speaking, doing that subtraction instead of an addition guarantees that we are going to be doing the inequality with a small number, rather than a number that's potentially large enough to roll over when interval_off is added to it.
    – Cort Ammon
    Dec 3 '18 at 18:36
  • Firstly, what is the purpose of declaring all variables as global ones? Secondly, if (millis() > nextEventTime) - this will not work properly around the moment of millis() rollover.
    – AnT
    May 2 '19 at 18:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.