millisecond command in arduino IDE

I took up Digital Clock with temperature as my first project and I have been successful in writing the program for it.

While using millis() function, which gives milliseconds the program is running, I read that when the memory, holding millisecond counts, gets ‘full’ after about 54 days, its memory get reset to zero and count of milliseconds starts from 0.

I have, in my program starting hour, starting minute for a clock as initial setting-value in the set up part and the clock starts from that setting . Would the following part, at the beginning of the of the loop part of the program, take care for this eventuality?

Set starting minute and starting hour as then existing values of minutes and hour if mills() become zero; otherwise take those that are given by the set up part.

I am including that part in the program;however I would have to wait for long time to see whether it is one of possible solutions.

Your clock should not depend on the absolute value of the milliseconds variable. However, if all calculations relating to milliseconds are done as “unsigned long integer” comparisons, then there is no problem with rollover. For example, if your program loop were to increment the seconds every time 1000 milliseconds has passed, if will continue to work even if the counter rolls over after 50 days.

unsigned long lastmillis;
...
if ( (millis() - lastmillis) >= 1000) {
  lastmillis=millis();
  seconds++;
 }

The millis value is an unsigned long. It will ‘overflow’ after it passes that 50-odd day length of time. After 4294967296 ticks comes 0 again. 2^32 millis ticks= 4294967.296 seconds (assuming the resonator or quarzcrystal is perfect, which it isn’t!), is 49day+17hour+2min+47.296 sec. When that passes then you’ll be around 50 days back in time. So not only 49 days, but also at the wrong hour, minute and second of the current day.

How about checking in the loop if the current value of millis() is 1000 larger then the previous recorded value. In other words, check if you are a second later. If that happens you update your own seconds, minutes, hours, days, months and year counters. If not, then do something else that takes less than a second, or go for your next loop turn. That way you’ll always have the right time. Just don’t do [Y2K, will ya! :wink:

http://arduino.cc/en/Reference/millis#.UysPaj5quvQ](Year 2000 problem - Wikipedia)

I’m not sure I understand what your proposed solution is. It sounds like you’re willing to loose 1 sec when the rollover occurs. In any case I will asy trying to catch millis() = 0 implies that your loop() runs faster than once/msec, otherwise millis() may increment past 0 before you poll it in your loop().

One thing you know for sure, that real time always increments. That if you store some value for time and then later ask what the time is now, that the new “now” time should be > than the stored time. If it isn’t then something odd has occurred and I’m pretty sure it wasn’t a time-warp due to a wormhole. Perhaps that’s a better indication that rollover has happened vs trying to catch millis() = 0 ?

EDIT: Looks like valen is a faster typer than I am ! :mrgreen:

Mee_n_Mac:
EDIT: Looks like valen is a faster typer than I am ! :mrgreen:

As was jremington for me. :mrgreen:

Ehm, correction on what I said. Just update the second counter with the difference of the current millis vs. the last millis value divided by 1000, and you’ll always be on-time. Even if you have a varying loop duration and it could (God forbid) take longer than 1 second to make a tick. Though, at the time of overflow it might be much bigger than usual (4294967.296 seconds minus a bit), so you will need to check if the change is less than a minute or so. Or else you’ll be 50 odd days in the future.

Alas jr’s code will not keep exact time during rollover.

    unsigned long lastmillis;
    ...
    if ( (millis() - lastmillis) >= 1000) {
      lastmillis=millis();
      seconds++;
     }

Ask what happens should lastmillis = 4294967295 - 500 ? At 4294967295 ticks the >= 1000 condition still isn’t satisfied. On the next tick millis() = 0 and you have the test of 0 - 4294967295 = ? It’s either a negative number or some large positive number, depending on whether it’s treated as a signed or unsigned result. The former fails the test (and will for a long time) while the latter passes the test too soon (500 msec in this example). What if the code were …

    const unsigned long maxtime = 4294967295;
    unsigned long lastmillis;
    ...
    if(millis() > lastmillis){
      //no rollover, do normal calcs
      if((millis() - lastmillis) >= 1000) {
        lastmillis=millis();
        seconds++;
      }
    }
    else{
      //rollover has occurred
      if((millis() - (maxtime - lastmillis)) >= 1000) {
        lastmillis=millis();
        seconds++;
      }
    }

(I may be off by 1 msec in the above, I’ll let you figure that out)

On the next tick millis() = 0 and you have the test of 0 - 4294967295 = ? It’s either a negative number or some large positive number, depending on whether it’s treated as a signed or unsigned result.

For manipulations with millis(), it is required to perform unsigned long math on unsigned long integers, in which case 0 - 4294967295 = 1. Try it!

The code does work and it does function properly during rollover. This has been discussed many times on the Arduino forum but the concept continues to confuse people, so someone provided an exposition: http://playground.arduino.cc/Code/Timin … ytHdc4xZjs

jremington:
the concept continues to confuse people

I guess I was in that group. Thanks for the link. :mrgreen:

Valen:
Or else you’ll be 50 odd days in the future.

Excellent. So for $30 I can find out who wins March Madness, right?

Hi to all respondents to my query. Many thanks for inputs.That I am so new to this field that millis() reverts to zero after 4294967295 milliseconds was information to me. My sketch envisages giving manually IntialHour,InitialMintue to start the loop part of the sketch,since Seconds and milliseconds would not be accurate manually! I could do so by connecting to PC,downloading current time of PC and start clock at that time. However, it is presently beyond my skill!

But can I have something similar to below to continue the lock after rollover crisis?

Loop

if (millis() !=0)

{regular working part of the program;}

else {InitialHour=PresentHour;InitalMinute=PresentMinute;InitialSecond=PresentSecond ;InitialMilli=PresentMilli;

regular working part of the program;}

sureshparanjape

sureshparanjape:
Hi to all respondents to my query. Many thanks for inputs.That I am so new to this field that millis() reverts to zero after 4294967295 milliseconds was information to me. My sketch envisages giving manually IntialHour,InitialMintue to start the loop part of the sketch,since Seconds and milliseconds would not be accurate manually! I could do so by connecting to PC,downloading current time of PC and start clock at that time. However, it is presently beyond my skill!

The pc would need to have a program running that sends the current system time in some sort of packet over the serial port. And your Arduino sketch would need to be able to recognize this has arrived and interpret it. That is indeed quite dificult for a beginner to setup. And requires more than just Arduino knowledge. I don’t know of any other examples that you can replicate this from. Most often you see hardware solutions that use a special clock chip to count the time and date. Or use a radio-receiver to pull a special signal out of the air. But that is location specific. I don’t know if there is such a radio transmitter in India (or whatever your country is, I’m just guessing based on your name) Using a hardware GPS receiver is also a possibility to synchronise your clock with atomic time. But somewhat expensive and requires line-of-sight with the satelites.

The solution below, which is already suggested, is more simple. It should keep running indefinitely until your battery runs out. As time passes by you’ll notice there is a slight difference with other clocks. But that is normal, as it is not an atomic-accurate clock. No clocks tick in the exact same rate. Depending on how many years you can count, it should go on forever.

But can I have something similar to below to continue the lock after rollover crisis?

Loop

if (millis() !=0)

{regular working part of the program;}

else {InitialHour=PresentHour;InitalMinute=PresentMinute;InitialSecond=PresentSecond ;InitialMilli=PresentMilli;

regular working part of the program;}

sureshparanjape

What happens to your clock when millis() rolls over, but never becomes exactly 0 when you call it? (Your Arduino might be doing other code during that specific milisecond) The millis value just before and after the roll over, is not equal to 0. So you have to be really really lucky to find millis() to be exactly 0, and have that PresentHour/Minute/Second initialisation taking place. It might not happen until the next 50-ish day event, or 99-ish, or 149-ish… or … you know.

Instead, use it to notice when a seconds roll over (or smaller values if you want that kind of precision) and count your own clock-second values. This happens much more often, and with longer duration. Whenever it is 1000 (or 100 or whatever) higher than previous, you have a new (deci-)second. Now, when it is count 60 seconds also increase the minute and set seconds to 0. If it is also 60 minutes increase the hour and set minutes to 0. And so on.

Thanks for pointing out the difficulty in using command “millis() !=0”. If this is replaced something like “millis()<500” with the rest remaining as before, would it work ? or still “It might not happen until …” might become probable but very unlikely!

BTW your guess,from where I am, is quite correct.

sureshparanjape

sureshparanjape:
Thanks for pointing out the difficulty in using command “millis() !=0”. If this is replaced something like “millis()<500” with the rest remaining as before, would it work ? or still “It might not happen until …” might become probable but very unlikely!

BTW your guess,from where I am, is quite correct.

sureshparanjape

“If millis()<500” in your previous code snippet would cause the first {regular working part of the program;} to only happen during the first half-second, and no sooner than the roll-over at 49 days later again. For just another half second. And the rest of the time the else-part will execute. So that is not going to help anything.

You really need to forget about testing the absolute value of millis() being bigger or smaller than a constant or within some range. Or else you only get a 50-day ‘stopwatch’. Not a real clock or calender. The difference since the last recorded millis() is what shows the passage of time indefinately in discrete steps.

Sorry,Sorry… for the last mail. afterthought did suggest me what will happen. Here is one possible solution. Introduce two memories, a and b. b stores millis() at the end of loop and a stores at the beginning of loop.“If condition” would depend on the sign of a-b.When he rollover occurs a-b would be negative. Can it be a solution?

sureshparanjape

can I have something similar to below to continue the lock after rollover crisis?

**There is no "rollover crisis"**, and the reason for that has been discussed in the previous posts of this very thread.

“a-b” is negative pretty much all the time if a is stored before b, as b would be higher when the loop takes more than 1 milisecond. If it is short enough to be within 1 milisecond, the difference a-b is 0. If the rollover happens between the storage of a and b, then a-b is positive. Consider, a is close to the maximum value of an unsigned long integer, but b is close to 0. Large minus 1 is still large.

If the rollover happend between the storage of b and the next storaget of a, so outside of the duration of the loop (which would be a very very short time period, if at all) then b is larger than a, and would cause the difference to be negative. But this occurance is very unlikely as a loop restarts almost immediately after its end. But I’m not really sure what goes on in Arduino’s core functions (which loop() is) so I might be wrong. But with clocks you don’t want to leave any possible state undefined.

I’m not terribly familiar with all of this, my thoughts may not be possible. It seems like it would be best to take control the rollover. Instead of waiting for the millis to overflow and reset on it’s own. Wouldn’t it make more sense to reset it after a given length of time? Once every second or every 30 days? At the end of every cycle (provided a cycle is less than 50 days) At time X set millis = 0 Depending on the functionality you’d probably lose time during the “manual” rollover. But you’d avoid the risk of an unexpected rollover.

If that’s not possible perhaps you could set up a wait loop condition, when Maxmillis - millis < 1000 do nothing until rollover. You might have to make that loop longer if it takes longer than 1ms to run through the other operations. Once every 50 days you’d have a pause in the operations.

Interesting topic.

There is no need to take over control of the rollover, or reset it somehow. You can notice when it happens because the change is outragiously large, and it can be corrected for it exactly. But after 50-odd days there are not enough bits in an unsigned long integer to keep track of time in the future. So you have to resort to an additional counter variable anyway.

But parsing the 32-bit value into seconds, minutes, hours and days at every moment is much more computationally intensive than subtracting the current millis from last recorded time and incrementing some variables. Also, when done impropperly rounding error might show up.

Incrementing the seconds, minutes, hours and days, or reseting them when they roll over takes no effort at all. And is much more comprehensive.

But I’ll leave my soapbox for now. Seems like I scared the thread-starter away.