resetting millis()

Hi

I want to reset the millis() function to zero each 24 hours. I cant find a post in the forum that describes this, is there anyone that can help me?

best regards

Fredrik

There is no need to reset the value of millis(). Just calculate the amount of time between one reading of millis() and the next.

Have a look at how millis() is used to manage timing in several things at a time

...R

{sigh}

Do you feel the need to reset your watch every time you need to do something? You don't need to reset millis(), either.

How would you know that it was a new day, and time to reset millis(), anyway? If you KNOW that, you have an RTC, which should be the source of all your timing information, anyway.

Hi

thanks for the swift replies.

The reason for wanting to reset it is that I don't know how to handle the rollover of the counter. I need to do something each 24 hours. The ideal thing would be to get an interrupt each 24 hours.

fredrik

thanks AWOL, I crawl in the dust :)

Hello,

This overflow is an interesting issue that comes up with the millis() function. I have not had to address this myself because most of the stuff i had done so far dont have to run for more than a few days or maybe a week at most.

I would think though that if we did the differential time measurement thing that would work up to the rollover point, and once that happens if we checked also for a lower value than before then we could tell when it rolled over and make adjustments if needed.

For example, if we had a counter that counted from 0 to 10 once every two hours starting from hour 1, the differential count would be: olddiff=count-olddiff

so olddiff would always be equal to 2, except when the rollover occurred, when it would equal: olddiff=1-9=-8

Now seeing that the olddiff went negative, it would seem easy to correct the differential time, just by adding 3 to the result, or by knowing the max count is 10 perhaps 10+(-8)=2.

We would see counts coming in as: 1,3,5,7,9,1,3,5,...

and so when we see very low number like 1 or so we know it rolled over so we should be able to correct it. We just have to be well aware of the max count value, which i think is 2^32-1 or maybe 2^31-1 i'd have to check the type again.

For testing we could create a fictitious counter and load it with a higher value and test the routine.

The only question left i think is do the other libraries being used take this roll over into account also or do they crash in some manner.

Doesnt seem too hard to do right?

This thread looks to me like a typical new thread about a xy-problem.

The actual problem is "x", but you don't tell a word about the actual problem you want to solve - instead you think that "y" (resetting the return value of millis()) might be the solution - then you start a new thread and want to discuss "y" (what you think is the solution), but you don't want to discuss the actual problem "x".

Meanwhile I really hate reading such newly created threads about xy-problems.

So the only thing I can tell is: Resetting millis() is never any solution, it's pure bullshit. Of course its possible to use bullshit coding to do something useful. In case of the millis() function possibly one file of the Arduino core library needs to be modified.

But hy modify any Arduino core library file, if it is completely unknown, which problem is to be solved with a modified core library?

In case you "need to do something each 24 hours" it is a very bad idea to rely on internal "millis() timing. Internal timing is very inaccurate and in worst case and with boards in R3 design (which are clocked by rather inaccurate ceramic resonators), the clocking might be off up to 0.8% from real timing, so using millis() over 24 hour periods may lead to timing inaccuracy of up to more than 10 minutes per day. For "doing something each 24 hours with a fairly good accuracy, I'd say you need a RTC (realtime clock) module.

@MrAl, have you read any of the linked pages? By simple checking it like

millis() - previousMillis >= interval

You don't have to worry (or check) about (/for) a rollover. So a good library will do it that way and don't have a problem ;) And if they don't, it's a shitty library. Edit the code and create a pull request to fix it ;) And if you want to know why, just Google about it :D

@fredrik2556, keep in mind the timing of the Arduino on it's own isn't very accurate. A couple of minutes off in 24 hours isn't a strange thing. 10 minutes, which may seem like a lot, is still less then 1% of error. If you want minute (or second) accurate 24 hour timing you need to switch to a RTC.

fredrik2556: Hi

I want to reset the millis() function to zero each 24 hours. I cant find a post in the forum that describes this, is there anyone that can help me?

best regards

Fredrik

You may want to, but that's not how it works. You set a variable to the value of millis() at the start of each day as the reference point, and use the difference between that millis().

The variables used to calculate millis() aren't explicitly available to you and one of them is a hardware counter register anyway.

fredrik2556: The reason for wanting to reset it is that I don't know how to handle the rollover of the counter.

The code in the link I gave you in Reply #1 deals with the rollover properly.

...R

septillion: @MrAl, have you read any of the linked pages? By simple checking it like

millis() - previousMillis >= interval

You don't have to worry (or check) about (/for) a rollover. So a good library will do it that way and don't have a problem ;) And if they don't, it's a shitty library. Edit the code and create a pull request to fix it ;) And if you want to know why, just Google about it :D

@fredrik2556, keep in mind the timing of the Arduino on it's own isn't very accurate. A couple of minutes off in 24 hours isn't a strange thing. 10 minutes, which may seem like a lot, is still less then 1% of error. If you want minute (or second) accurate 24 hour timing you need to switch to a RTC.

Hi

Thanks.

Well you are saying: millis() - previousMillis >= interval and then saying you dont have to 'check' it for rollover, but isnt that checking for rollover? No pun intended, although it might be a little ironic. But then you also have to know what to do AFTER that check, which is to adjust your 'previousMillis' to stay synced properly. Maybe you could mention how you would do that too. I havent gotten to read up on this too good yet but hope to in the future.

Note i am not as worried about the pre existing libraries as much, just my own code because i made a timer a while back that uses millis() just to see how well it would work, and working with the millis() function for longer periods would just be interesting to do too, even if i dont usually run it that long. I may end up running a timer longer one day for some reason. I'll assume for now all the good libraries do it right, and just worry about my own personally written code for now, which i'll have to correct at some point. So if you have a good way to do it you might mention that also. Also note i use RTC also but dont need it for every project. I also dont need super super accurate timer timing either, for most stuff, except of course any real time clock projects. If my timer is off by 10 minutes per day, i use tuning code to get it down to seconds which makes up for the oscillator inaccuracy, but even that i dont really need for most stuff, as 10 minutes per day probably would not hurt most timer stuff i do.

millis() - previousMillis >= intervalTakes care of the rollover with no need to check and/or adjust previousMillis as long as you use unsigned long variables

Here is a thread about a clock I made: https://forum.arduino.cc/index.php?topic=408565.0 You can look at the code to see how I kept track of time.

MrAl: but isnt that checking for rollover?

No, it's just checking if an interval has passed since the time in previousMillis (if we set previousMillis equal to millis() on a given moment).

MrAl: But then you also have to know what to do AFTER that check,

Nothing if you just wanted to see if a period ha passed. And if you want to check for a new period (aka, keep doing stuff every interval) you set previousMillis to millis() and it starts over. The same you started the process

MrAl: But then you also have to know what to do AFTER that check, which is to adjust your 'previousMillis' to stay synced properly.

Look at the link I gave in Reply #1. It includes an extensive discussion of some of the finer details.

...R

septillion: No, it's just checking if an interval has passed since the time in previousMillis (if we set previousMillis equal to millis() on a given moment). Nothing if you just wanted to see if a period ha passed. And if you want to check for a new period (aka, keep doing stuff every interval) you set previousMillis to millis() and it starts over. The same you started the process

Hello again,

Well, the code fragment:

millis() - previousMillis >= interval

does not do anything at all in itself, we need more code to go with that. We need to see what else you are doing after that, and did you really mean to have this be an "if" statement?

I think what you are saying is that the interval still works if we use type unsigned long.

I'll be checking the other links also.

That's why I said you need to check it ;) And indeed, if is the simplest for of checking something. And all the code is in the Blink without delay. But two forms

Check once

unsigned long previousMillis;
bool waiting;
int interval = 1000;

void setup(){
  startWaiting();
}

void loop(){
  if(waiting && millis() - previousMillis >= interval){
    waiting = false;
    //do your stuff
  }
}


void startWaiting(){
  previousMillis = millis();
  waiting = true;
}

Check continues

unsigned long previousMillis;
int interval = 1000;

void loop(){
  if(millis() - previousMillis >= interval){
    previousMillis = millis();
    //or if time spacing is more critical
    //previousMillis += interval;
    //or if you expect the loop to be so slow (which it should not) that it can miss an interval
    //while(millis() - previousMillis >= interval){
    //  previousMillis += interval;
    //}

    //do your stuff
  }
}

And of course you need to set previousMillis somewhere. In real life you also have no idea if 5 minutes have passed by checking the clock if you didn't remember when you started watching...

And as you can see interval doesn't nee to be an unsigned long. As long as the desired interval fits it's fine. And if it fits in a signed type that's even okay (but he, you get double the resolution for free if you use unsigned).

And here, yes, previousMillis needs to be unsigned long because that's what millis() return. But if you are only interested in periods in the range of seconds then there is nothing wrong with truncing millis() to an unsigned int. But it has to be unsigned to not get negative times on roll over

unsigned int previousMillis;
unsigned int interval = 1000;

void loop(){
  unsigned int millisNow = millis(); //trunc millis to a uint
  if(millisNow - previousMillis >= interval){
    previousMillis = millisNow;
    
    //do your stuff
  }
}

Hello again septillion,

That’s very nice of you to post the code and explanations. Very commendable in a forum where some dont seem to like to do that.

My main concern was what happens after the rollover, but as you must already know when it rolls over we dont loose any time or anything like that, because with the unsigned long type we still get the same interval in the subtraction. I wasnt sure about that at first, that’s why i was looking into this more carefully. Now that i see that it works, i have no problem doing it that way.
So your code effectively eliminates the rollover problem completely. Thanks for sharing. Now i just have to put it into my timer program(s) and all will be well in Arduino Land :slight_smile:

Very commendable in a forum where some dont seem to like to do that.

Whether to post solutions as complete code or not is for me a difficult decision. Most of the time I don't do it so that the person wanting help has to write the code themselves which reinforces learning in most cases. Sometimes I will post complete solutions or an example that shows a technique and I have often posted pseudo code which is a sort of halfway house.

Each to their own.