millis() overflow question

I am periodically running a pump for 12 hour sets and I am currently using millis() to set a future time for the pump to shut off. ie if (millis()>futuremillis) digital.Write(LED, LOW). This works great except for the fact that I know that at one point around the 50 day mark I will hit the end of the millis() limit and it will probably mess up all my timing. I don't know exactly what will happen because I don't care to wait for 50 days to find out. I have thought of a way to fix it but I don't know exactly what the best way to fix it is. Here is my idea.

if (millis() > 45 days && timerOn= false)
{
"Set millis() back to zero!!!"
or
"Reset the whole arduino!!"
}

I figure this might work just because if the timer is not on I really don't care if it is resting itself or messing with millis(). If this is an okay idea my question is, How do I reset millis() back to zero? or Is there a way to reset the arduino without using setting the reset pin high (I don't like doing this just because I prefer to use the least amount of wires possible.)

Here is a portion of my current code

void time(int value)
{
  Serial.println("Value to be Used in Timer");
  Serial.println(value);
  futuremillis=value*10UL+currentmillis;
  timerOn=true;


void loop()
{
  currentmillis = millis();
 if(futuremillis< currentmillis && timerOn == true) 
    {
      digitalWrite(led, LOW);
      timerOn=false;
      textForSMS = "Timing Sequence Complete Device Turned Off";
      Serial.println("Timing Sequence Complete");
       }

and I am currently using millis() to set a future time for the pump to shut off. ie if (millis()>futuremillis) digital.Write(LED, LOW).

That is the wrong way to do it. You need to record when the pump was turned on, and, periodically, see it it has been on long enough (now - then >= on time).

This way, it won' matter iff millis() rolls over (as long as on time is less than 49+ days).

Why do you want to reset the Arduino or reset millis()?

millis() runs, overflows, and keeps running.

Always use unsigned long for millis(), and for any other variable that stores it.

When you want an elapsed time, do this...

startTime = millis() //set start time, but do NOT calculate the future desired value

and later,

duration = millis() - startTime // calculate the duration, and check it for enough

The only problem you'll run into is if millis() overflows more than once.

It works because of the way unsigned math works.

lar3ry:
duration = millis() - startTime // calculate the duration, and check it for enough

Okay I think I understand. My problem might be that I don't understand the unsigned math. You are saying. I will set duration to 12 hours and record start time and have something like this

if(millis()-startTime >= duration) Shut er down!

I am okay with this but I would like to know why this is right. For example I set it for a 12 hour set at 49.9 days (we will say it roles over at 50 for simplicity) This means that I would want it to shut off when millis()= 0.4 days

Okay

what happens when it just roles over
if(0.01 days - 49.9 days >= 0.5 days "12 hrs") Wouldn't this return a negative number until it reaches 49.9 days? But wait I remember that the unsigned numbers can only be positive. Wouldn't that mean that it would shut off as soon as it rolled over?

I am a stupid mechanical engineer playing in your world of electrical engineering. Help me understand.

Thanks again

see

Okay in summary unsigned long has different mathematical properties and because of them I don't have to worry about the millis() wrap so change your system to use the above subtraction method and don't complain.

jacob84401:
Okay in summary unsigned long has different mathematical properties and because of them I don't have to worry about the millis() wrap so change your system to use the above subtraction method and don't complain.

It's all in the algorithm. There's nothing tricky or sneaky about it... just plain ordinary unsigned math that does exactly what it is supposed to do, and in this case, exactly what you wanted it to do. Did you try Nick's example on the Mac calculator? If not, the Windows-supplied calculator also has a Programmer's calculator View. Run through his example, paying attention to the binary values as you put the numbers in, and at the end, showing the result.

Given that millis returns you an unsigned long, you could do some experiments with unsigned longs near the limit to demonstrate what happens at rollover - no need to wait for the ~50 days.

Or, "change your system to use the above subtraction method and don't complain." :stuck_out_tongue:

unsigned is a red-herring, the lower bits of differences/sums of signed or unsigned
values are always correct when the higher bits are truncated because no result
bit depends on any more significant bits of the arguements.

Or put another way an unsigned long is arithmetic modulo 2^32, and modular
subtraction works modulo 2^32!

This works in decimal too, if modulo 10 or 100 or 1000 or some power of ten.