Millis after 50 days

Hello Arduiners!

Few months ago I created automated boat waterpump and I have some problem with long term run. I think that I have problem when millis go back to zero. After more than a month my arduino is unable to detect water in a boat or just cannot activate timer for a pump. Project works well first few weeks. I am using infrared water sensor which activates pump for 1-2 minutes you can see it glued on the top of the pump.

Is there any problem with this part of a code in long term?

//const long interval = 120000;  do I need to put unsigned long here?

   timer=millis();
   while (millis()-timer<=interval) {     
      digitalWrite(pumpa, LOW); // only part of the code where pump is activated    
    }

Here is full code:

#include <LowPower.h>
int napajanje_senzora=15;  //sensor power
int senzor=21;
int pumpa=2;//water pump
int led=13;
unsigned long timer = 0; 
const long interval = 120000; 


void setup() {

  // Serial monitor output
  Serial.begin(9600);
  pinMode(pumpa,OUTPUT);
  pinMode(led,OUTPUT);
  pinMode(napajanje_senzora,OUTPUT);
  digitalWrite(pumpa, HIGH);
  digitalWrite(napajanje_senzora, HIGH);
}

void loop() {
  

  Serial.println( analogRead(senzor));

  //if detects water activate timer for 1-2minutes
if( analogRead(senzor)<50){
   timer=millis();
   while (millis()-timer<=interval) {     
      digitalWrite(pumpa, LOW); // activate pump relay   
    }
                   
    
    
}
                      

else {
  digitalWrite(pumpa, HIGH); // deactivate pump relay
  digitalWrite(napajanje_senzora, LOW); //power off sensor power
  delay(200); 
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); //put arduino in sleep for 8 seconds
  delay(200); 
  digitalWrite(napajanje_senzora, HIGH); // power on sensor
}

  delay(250);
}

I know that I can do this with just 2 minute delay but I want to learn to use millis timers. It’s really hard to wait 50 days to see if some change of mine will fix the project code

I appreciate any help

Is there any problem with this part of a code in long term?

Yes.
The constant “interval” is commented-out

millis() is going to roll over back to zero after roughly 49.7 days on a Uno / Mega.

The ESP32 has a micros API that uses an unsigned 64 bit int that rolls over after 200+ years.

TheMemberFormerlyKnownAsAWOL:
Yes.
The constant "interval" is commented-out

I commented it there because that part needs to be in void setup but not in loop. Full code is down.

do I need unsigned long variable for a interval? is that problem or not?
Currently I use const long for interval

You can use any type for an interval as long as it will hold the interval value. But if it's declared as a 'const', it won't occupy any storage anyway. Suppose your interval fits in an int today. After a few months, you increase it without looking carefully... bam! overflow. If it's not const (I suppose because you'll change the value dynamically), and you're concerned about memory usage, you can use a smaller than long type and it will be promoted automatically to the long arithmetic used in your comparison statement.

I don't think your millis code is a problem - you're using subtraction in the approved manner so it should be fine.

For testing, use micros instead and you can see relatively quickly whether rollover is actually doing any damage.

You’re not using millis() correctly anyway, so why bother?
The whole point of using millis() for timing is to avoid blocking loops.

Perhaps interval should be unsigned long to match timer and millis()?

I used millis() so I can easily add more sensors and LCD. Just I change while to if. I know I can to same thing with just delay(120000) but I would love to know what is making problem here.

Does too many serial prints caused problem or millis overflow or maybe arduino blocks in sleep.

Does your code work "in the short term", notwithstanding its behaviour in "the long term"?

in 2 weeks there was few heavy rains and arduino worked great. Few times water didn't touch sensor but I soon I spray water on sensor arduino turned pump on for declared time. After more than a month arduino won't detect water even if sensor is in water all time. As soon as I make power reset arduino again works great. Arduino is always connected to battery without disconecting 24/7

Arduino is in sleep so when I spray water on sensor I need to wait few seconds to wake up arduino and turn on powersuply on sensor

You do have some timing code which appears to be nested inside a sensor test.

 if ( analogRead(senzor) < 50) {
    timer = millis();
    while (millis() - timer <= interval) {

If the sensor test proved false continuously, the timing code would never be executed and then timed events would be ignored. Just a theory, I haven’t had time to look in detail yet.

Also, does the relay board share a power supply with the Arduino? That is often a problem.

I’ve formatted your code to remove all the superfluous spaces that get no love around here:

#include <LowPower.h>
int napajanje_senzora = 15; //sensor power
int senzor = 21;
int pumpa = 2; //water pump
int led = 13;
unsigned long timer = 0;
const long interval = 120000;

void setup() {
  // Serial monitor output
  Serial.begin(9600);
  pinMode(pumpa, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(napajanje_senzora, OUTPUT);
  digitalWrite(pumpa, HIGH);
  digitalWrite(napajanje_senzora, HIGH);
}

void loop() {
  Serial.println( analogRead(senzor));
  //if detects water activate timer for 1-2minutes
  if ( analogRead(senzor) < 50) {
    timer = millis();
    while (millis() - timer <= interval) {
      digitalWrite(pumpa, LOW); // activate pump relay
    }
  }
  else {
    digitalWrite(pumpa, HIGH); // deactivate pump relay
    digitalWrite(napajanje_senzora, LOW); //power off sensor power
    delay(200);
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); //put arduino in sleep for 8 seconds
    delay(200);
    digitalWrite(napajanje_senzora, HIGH); // power on sensor
  }
  delay(250);
}

Also, why is there a delay() at the end of loop()?

12V from battery goes to Vin pin of arduino nano and water pump. Relay is connected to 5V pin on arduino.

I put that delay just to make sure that there is power on sensor before new loop

fibra59:
12V from battery goes to Vin pin of arduino nano and water pump. Relay is connected to 5V pin on arduino.

I put that delay just to make sure that there is power on sensor before new loop

Then why not put it inside the else clause? Does it really need to delay every time through loop()?

Relay is connected to 5V pin on arduino.

Not a good idea at all. You should power the relay from 12V instead (using a 12V relay, of course). It's very common for relay switching to throw noise at the Arduino. The 5V rail is especially vulnerable to that.

I have tried this lot of times before putting it in to the boat. Arduino didn't make any problems. I have tried few times in a row to put sensor in glass of water any every time arduino worked perfectly. Noise will be there just at the time water pump is working and that is around 2-3 times in month

fibra59:
Noise will be there just at the time water pump is working and that is around 2-3 times in month

Isn’t that consistent with the failure intervals? You said it ran and failed after a month. That would be after 2 or 3 activations. With noise, there is an element of chance involved. Sometimes it will fail, sometimes not. A good test is to substitute an LED for the relay and see if it still fails. But in this case, I guess that would take a long time to run the test.

A danger with intermittent failures, is getting bogged down in speculation. One has to guess a little to design experiments to help isolate the cause, but that is as far as the thinking alone will get you.

Can you post a wiring schematic?

Getting back to code, this section merely emulates delay(), so if you’re going to do it, you may as well just use delay()…

    timer = millis();
    while (millis() - timer <= interval) {
      digitalWrite(pumpa, LOW); // activate pump relay
     }

is almost the same as

      digitalWrite(pumpa, LOW); // activate pump relay
      delay(interval);

except that with delay, you don’t continously write the same value to the pump.

auuh hahah… Before instalation in boat I have tried lot of times and there were no any problems detected.
Every time arduino woke up from sleep detects water and start water pump. That is why I think that problem is in millis() function after overflow. Maybe if condition is not true for some reason.

I can easily put this kind of code but I thought that someone had similar problem. I thought that someone will say lot of serialprints blocks arduino after a while or maybe millis is not good for long term projects.

if( analogRead(senzor)<50){   
 digitalWrite(pumpa, LOW);
 delay(120000);  }

else {
  digitalWrite(pumpa, HIGH); 
  digitalWrite(napajanje_senzora, LOW); 
  delay(200); 
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  digitalWrite(napajanje_senzora, HIGH);
}

You only used millis() to emulate your own custom version of delay(). If you replace it with delay() as I showed you, you can take that possibility out of the equation.

millis() is just fine for long term projects. I ran an ethernet web server for 8 months non stop with no problems using millis().

Also there is no logical reason that you can point to, in the design or implementation of millis() that would cause it to glitch. If there was one, thousands of users would have noticed it by now.

Maybe there is the ghost of a pirate, or something like that in your boat... :slight_smile:

Not very wise to rely on electronics for such a critical mission.

Just use a marine-grade float switch, nothing else.
Leo..

aarg:
millis() is just fine for long term projects. I ran an ethernet web server for 8 months non stop with no problems using millis().

Also there is no logical reason that you can point to, in the design or implementation of millis() that would cause it to glitch. If there was one, thousands of users would have noticed it by now.

Maybe there is the ghost of a pirate, or something like that in your boat... :slight_smile:

So my condition of while loop is correctly written and variables are declared good?

I don't think that pirates are the problem

So my condition of while loop is correctly written and variables are declared good?

You should not use a while loop in the first place. Using it causes blocking code just as much as using delay()

Take a look at Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE to see the proper use of millis() for non blocking timing