Millis doesn't function with longer time interval

Hi,

I have a problem. I'm using Millis to create a timer. I two timers, which are connected to relays. The first timer need to go on after 20min (120000) and the other timer after 30min (180000) and they need to go off after 5sec. (5000). But its not working.

Here is my code:

// PUMP 1
int PUMP1_DELAY = 120000; //Pump 1 Change for dalay (1000 = 1 second)
int PUMP1_TIME_ON = 5000; //Pump 1 Change for pump running time (1000 = 1 second)

// PUMP 2
int PUMP2_DELAY = 180000; //Pump 2 Change for dalay (1000 = 1 second)
int PUMP2_TIME_ON = 5000; //Pump 2 Change for pump running time (1000 = 1 second)

// ------------------------------------------------------

const int RELAY1 = 2;
const int RELAY2 = 4;

int INTERVAL_PUMP1 = PUMP1_DELAY;
int INTERVAL_PUMP2 = PUMP2_DELAY;

unsigned long time_1 = 0;
unsigned long time_2 = 0;

boolean PUMP1_ON = true;
boolean PUMP2_ON = true;
boolean TURN_PUMP_ON=LOW;
boolean TURN_PUMP_OFF=HIGH;

void print_time(unsigned long time_millis);

void setup() {
Serial.begin(115200);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
digitalWrite(RELAY1, TURN_PUMP_OFF);
digitalWrite(RELAY2, TURN_PUMP_OFF);

}

void loop() {

//Pump 1
if (millis() > time_1 + INTERVAL_PUMP1) {
time_1 = millis();
print_time(time_1);

if (PUMP1_ON) {
digitalWrite(RELAY1, TURN_PUMP_ON);
Serial.println("Pump 1 on!");
PUMP1_ON = false;
INTERVAL_PUMP1 = PUMP1_TIME_ON;
} else {
digitalWrite(RELAY1, TURN_PUMP_OFF);
PUMP1_ON = true;
Serial.println("Pump 1 off!");
INTERVAL_PUMP1 = PUMP1_DELAY;
}

}

//Pump 2

if (millis() > time_2 + INTERVAL_PUMP2) {
time_2 = millis();
print_time(time_2);

if (PUMP2_ON) {
digitalWrite(RELAY2, TURN_PUMP_ON);
Serial.println("Pump 2 on!");
PUMP2_ON = false;
INTERVAL_PUMP2 = PUMP2_TIME_ON;
} else {
digitalWrite(RELAY2, TURN_PUMP_OFF);
PUMP2_ON = true;
Serial.println("Pump 2 off!");
INTERVAL_PUMP2 = PUMP2_DELAY;
}
}
}

//Function for printing to serial. Debug only.
void print_time(unsigned long time_millis) {
Serial.print("Time: ");
Serial.print(time_millis / 1000);
Serial.print("s - ");
}

int PUMP1_DELAY = 120000; //Pump 1 Change for dalay (1000 = 1 second)

// PUMP 2
int PUMP2_DELAY = 180000; //Pump 2 Change for dalay (1000 = 1 second)

What is the largest number that a signed int can hold ?
Make these variable long or unsigned long

Thanks! I think I haven't defined this in my code yet. I'm not sure how to, I'm pretty much a beginner. Can you show me how?

Declare all of the variables associated with time as unsigned long as you have done for time_1 and time_2

I can't figure out, its not working. I tried several variables.

// PUMP 1
int PUMP1_DELAY = 120000; //Pump 1 Change for dalay (1000 = 1 second; 60000 = 1 min)
int PUMP1_TIME_ON = 5000; //Pump 1 Change for pump running time (1000 = 1 second)

// PUMP 2
int PUMP2_DELAY = 1000; //Pump 2 Change for dalay (1000 = 1 second)
int PUMP2_TIME_ON = 5000; //Pump 2 Change for pump running time (1000 = 1 second)

// ------------------------------------------------------

const int RELAY1 = 2;
const int RELAY2 = 4;

int INTERVAL_PUMP1 = PUMP1_DELAY;
int INTERVAL_PUMP2 = PUMP2_DELAY;

unsigned long time_1 = 0;
unsigned long time_2 = 0;
unsigned long RELAY1 = 0;
unsigned long RELAY2 = 0;

boolean PUMP1_ON = true;
boolean PUMP2_ON = true;
boolean TURN_PUMP_ON=LOW;
boolean TURN_PUMP_OFF=HIGH;

void print_time(unsigned long time_millis);

void setup() {
Serial.begin(115200);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
digitalWrite(RELAY1, TURN_PUMP_OFF);
digitalWrite(RELAY2, TURN_PUMP_OFF);

}

void loop() {

//Pimp 1
if (millis() > time_1 + INTERVAL_PUMP1) {
time_1 = millis();
print_time(time_1);

if (PUMP1_ON) {
digitalWrite(RELAY1, TURN_PUMP_ON);
Serial.println("Pump 1 on!");
PUMP1_ON = false;
INTERVAL_PUMP1 = PUMP1_TIME_ON;
} else {
digitalWrite(RELAY1, TURN_PUMP_OFF);
PUMP1_ON = true;
Serial.println("Pump 1 off!");
INTERVAL_PUMP1 = PUMP1_DELAY;
}

}

//Pump 2

if (millis() > time_2 + INTERVAL_PUMP2) {
time_2 = millis();
print_time(time_2);

if (PUMP2_ON) {
digitalWrite(RELAY2, TURN_PUMP_ON);
Serial.println("Pump 2 on!");
PUMP2_ON = false;
INTERVAL_PUMP2 = PUMP2_TIME_ON;
} else {
digitalWrite(RELAY2, TURN_PUMP_OFF);
PUMP2_ON = true;
Serial.println("Pump 2 off!");
INTERVAL_PUMP2 = PUMP2_DELAY;
}
}
}

//Function for printing to serial. Debug only.
void print_time(unsigned long time_millis) {
Serial.print("Time: ");
Serial.print(time_millis / 1000);
Serial.print("s - ");
}

int PUMP1_DELAY = 120000;

An unsigned int, which is what this variable is declared as, can only hold a value of up to 32,757. Can you see a possible problem when you try to put 120000 in it ?

As an illustration of the problem try this

int PUMP1_DELAY = 120000;
void setup()
{
  Serial.begin(115200);
  Serial.println(PUMP1_DELAY);
}

void loop()
{
}

What does it print ?

Change the declaration to

unsigned long PUMP1_DELAY = 120000;

Now what does it print ?

yeah, now I understand why its not working.

I changed it to this:

// PUMP 1
unsigned long PUMP1_DELAY = 120000; //Pump 1 Change for dalay (1000 = 1 second; 60000 = 1 min)
int PUMP1_TIME_ON = 5000; //Pump 1 Change for pump running time (1000 = 1 second)

// PUMP 2
unsigned long PUMP2_DELAY = 180000; //Pump 2 Change for dalay (1000 = 1 second)
int PUMP2_TIME_ON = 5000; //Pump 2 Change for pump running time (1000 = 1 second)

// ------------------------------------------------------

const int RELAY1 = 2;
const int RELAY2 = 4;

int INTERVAL_PUMP1 = PUMP1_DELAY;
int INTERVAL_PUMP2 = PUMP2_DELAY;

unsigned long time_1 = 0;
unsigned long time_2 = 0;

boolean PUMP1_ON = true;
boolean PUMP2_ON = true;
boolean TURN_PUMP_ON=LOW;
boolean TURN_PUMP_OFF=HIGH;

void print_time(unsigned long time_millis);

void setup() {

Do you think I also need to do this?

Everything to unsigned long?

// PUMP 1
unsigned long PUMP1_DELAY = 120000; //Pump 1 Change for dalay (1000 = 1 second; 60000 = 1 min)
unsigned long PUMP1_TIME_ON = 5000; //Pump 1 Change for pump running time (1000 = 1 second)

// PUMP 2
unsigned long PUMP2_DELAY = 180000; //Pump 2 Change for dalay (1000 = 1 second)
unsigned long PUMP2_TIME_ON = 5000; //Pump 2 Change for pump running time (1000 = 1 second)

JaGa:
Do you think I also need to do this?

Everything to unsigned long?

You can see the capacity of each data type here.

Thanks, normally I would say that 'int' could work with 5000 (5 sec) but, in my scenario it wasn't.

JaGa:
Thanks, normally I would say that 'int' could work with 5000 (5 sec) but, in my scenario it wasn't.

It works for me....

Code below with myInterval as an int of 30000, gives this output:

setup() finished at 0
30s count finished at 30000
int myInterval = 30000;
unsigned long lastMillis;


void setup()
{
  Serial.begin(9600);
  Serial.print("setup() finished at ");
  Serial.println(millis());
} //setup

void loop()
{
  if (millis() - lastMillis >= myInterval)
  {
    Serial.print("30s count finished at ");
    Serial.println(millis());
    while(1){}
  }
} //loop

:confused:

I tried this one, but its not working at all.

// PUMP 1
unsigned long PUMP1_DELAY = 120000; //Pump 1 Change for dalay (1000 = 1 second)
unsigned long PUMP1_TIME_ON = 5000; //Pump 1 Change for pump running time (1000 = 1 second)

// PUMP 2
unsigned long PUMP2_DELAY = 180000; //Pump 2 Change for dalay (1000 = 1 second)
unsigned long PUMP2_TIME_ON = 5000; //Pump 2 Change for pump running time (1000 = 1 second)

// ------------------------------------------------------

const int RELAY1 = 2;
const int RELAY2 = 4;

int INTERVAL_PUMP1 = PUMP1_DELAY;
int INTERVAL_PUMP2 = PUMP2_DELAY;

unsigned long time_1 = 0;
unsigned long time_2 = 0;

boolean PUMP1_ON = true;
boolean PUMP2_ON = true;
boolean TURN_PUMP_ON=LOW;
boolean TURN_PUMP_OFF=HIGH;

void print_time(unsigned long time_millis);

void setup() {
Serial.begin(115200);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
digitalWrite(RELAY1, TURN_PUMP_OFF);
digitalWrite(RELAY2, TURN_PUMP_OFF);

}

void loop() {

//Pimp 1
if (millis() > time_1 + INTERVAL_PUMP1) {
time_1 = millis();
print_time(time_1);

if (PUMP1_ON) {
digitalWrite(RELAY1, TURN_PUMP_ON);
Serial.println("Pump 1 on!");
PUMP1_ON = false;
INTERVAL_PUMP1 = PUMP1_TIME_ON;
} else {
digitalWrite(RELAY1, TURN_PUMP_OFF);
PUMP1_ON = true;
Serial.println("Pump 1 off!");
INTERVAL_PUMP1 = PUMP1_DELAY;
}

}

//Pump 2

if (millis() > time_2 + INTERVAL_PUMP2) {
time_2 = millis();
print_time(time_2);

if (PUMP2_ON) {
digitalWrite(RELAY2, TURN_PUMP_ON);
Serial.println("Pump 2 on!");
PUMP2_ON = false;
INTERVAL_PUMP2 = PUMP2_TIME_ON;
} else {
digitalWrite(RELAY2, TURN_PUMP_OFF);
PUMP2_ON = true;
Serial.println("Pump 2 off!");
INTERVAL_PUMP2 = PUMP2_DELAY;
}
}
}

//Function for printing to serial. Debug only.
void print_time(unsigned long time_millis) {
Serial.print("Time: ");
Serial.print(time_millis / 1000);
Serial.print("s - ");
}

20 minutes = 20601000 = 1200000 milliseconds, not 120000.

thanks!

I changed everything to this, can someone check if this is right, please?

// PUMP 1
unsigned long PUMP1_DELAY = 1200000; //Pump 1 Change for dalay (1000 = 1 second) 
unsigned long PUMP1_TIME_ON = 5000; //Pump 1 Change for pump running time (1000 = 1 second)

// PUMP 2
unsigned long PUMP2_DELAY = 1800000; //Pump 2 Change for dalay (1000 = 1 second)
unsigned long PUMP2_TIME_ON = 5000; //Pump 2 Change for pump running time (1000 = 1 second)


// ------------------------------------------------------

int myInterval = 180000;
unsigned long lastMillis;

const int RELAY1 = 2;
const int RELAY2 = 4;

int INTERVAL_PUMP1 = PUMP1_DELAY;
int INTERVAL_PUMP2 = PUMP2_DELAY;

unsigned long time_1 = 0;
unsigned long time_2 = 0;

boolean PUMP1_ON = true;
boolean PUMP2_ON = true;
boolean TURN_PUMP_ON=LOW;
boolean TURN_PUMP_OFF=HIGH;

void print_time(unsigned long time_millis);

void setup() {
  Serial.begin(115200);
  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  digitalWrite(RELAY1, TURN_PUMP_OFF);
  digitalWrite(RELAY2, TURN_PUMP_OFF);

  
  Serial.print("setup() finished at ");
  Serial.println(millis());


       
}
  

void loop() {

  {
  if (millis() - lastMillis >= myInterval)
  {
    Serial.print("30s count finished at ");
    Serial.println(millis());
    while(1){}
  }
} //loop

  //Pimp 1
  if (millis() > time_1 + INTERVAL_PUMP1) {
    time_1 = millis();
    print_time(time_1);

    if (PUMP1_ON) {
      digitalWrite(RELAY1, TURN_PUMP_ON);
      Serial.println("Pump 1 on!");
      PUMP1_ON = false;
      INTERVAL_PUMP1 = PUMP1_TIME_ON;
    } else {
      digitalWrite(RELAY1, TURN_PUMP_OFF);
      PUMP1_ON = true;
      Serial.println("Pump 1 off!");
      INTERVAL_PUMP1 = PUMP1_DELAY;
    }

  }

  //Pump 2

  if (millis() > time_2 + INTERVAL_PUMP2) {
    time_2 = millis();
    print_time(time_2);

    if (PUMP2_ON) {
      digitalWrite(RELAY2, TURN_PUMP_ON);
      Serial.println("Pump 2 on!");
      PUMP2_ON = false;
      INTERVAL_PUMP2 = PUMP2_TIME_ON;
    } else {
      digitalWrite(RELAY2, TURN_PUMP_OFF);
      PUMP2_ON = true;
      Serial.println("Pump 2 off!");
      INTERVAL_PUMP2 = PUMP2_DELAY;
    }
  }
}


//Function for printing to serial. Debug only.
void print_time(unsigned long time_millis) {
  Serial.print("Time: ");
  Serial.print(time_millis / 1000);
  Serial.print("s - ");
}

can someone check if this is right, please?

unsigned long PUMP2_TIME_ON = 5000;

Well my code above proves that an int of 30000 actually works...

Did you run my short sketch?

Yes I tried your code, its working

but I am not able to apply this to my code.

JaGa:
Yes I tried your code, its working

but I am not able to apply this to my code.

Well I didn’t mean you to drop my short test sketch into your main sketch and then edit your post to contain that, as if it was some fix by me for your main sketch. (Especially since my test sketch has a wait(1) in it…)

My test sketch was just to verify that your problem with an int not working for 5000, when we know it’s supposed to work to 32k, actually worked for me with an int of 30000.

My advice would be to use unsigned long for all variables associated with millis() timing. That includes start the start time of any period, the period itself as well as the current time.

That way you don't have to worry about whether an int is big enough and whether the value will go negative if it is increased. Using unsigned long does waste a few bytes of memory but if you are so short of memory that it causes a problem then you have more than timing variables to worry about

UKHeliBob:
Using unsigned long does waste a few bytes of memory but if you are so short of memory that it causes a problem then you have more than timing variables to worry about

No argument there, but if OP's original sketch was going wrong with an interval int of 5000....

Yes, but he also had timing variables for each pump that exceeded the limits for an int so the fact that some of them could be held by an int is not relevant