Timer Function Roll Over

Hi All.
To give a quick explanation first, I'm wanting to create a simple function for Timer On Functionality. This is to replicate what is used in all PLC type of programming where you Set the Time value and then set a Bit to say Start timer. When the Time is reached a Dun bit will turn True to state the Time has elapsed. BUT lol there will be plenty things happening in between the start and completion of the Time so cant use the simple Delay() function. I know there is far better accuracy using a RTC board but I want to make it available for use in Every day simple programs on a single Arduino board. I'm certified as Severely Sight Impaired so when I've exhausted myself looking through the Arduino documentation I fall back to asking simple questions on forums to help me find the answer. To also add that I have been a PLC design and build engineer for over 20 years so understand how to program in C as well as a few other languages. I have written this Timer code for the Arduino and tested it and it works fine but I have a problem when the Time rolls over hence my question below.

Question:
When using the micros() when does the Time Roll Over i.e. what is the Maximum Time count using the micros().

I know the documentation says approximately 50 days but I need to know what the exact max number is so I can compensate for roll over.

Any help is very much appreciated.

Here:

The return value is unsigned long.
It is 2^32-1 maximum value.
Roll over is about 71min. and 35 sec.

You've asked about micros() but it is similar with millis().

Hello,

50 days is for millis(). Micros() is about 70 minutes. But why rollover is a problem?

millis() overflow ... a bad thing?

1 Like

It's a 32 bit unsigned long so

((((2^32) / 1000) / 60) / 60) / 24 =

49.7102696296 days to rollover.

See also

HTH

a7

the following is a pretty convention approach to using a timer that allows the period to be programmed as well as disabled. the timer is also conditional on msecPeriod being non zero, perhaps the inverse of you Dun bit

the timer could either reset itself by setting msecLst or disabling itself by setting msecPeriod to zero.

    unsigned long msec = millis ();
    if (msecPeriod && msec - msecLst >= msecPeriod)  {
#if 0
        msecLst = msec;
#else
        msecPeriod = 0;
#endif
        Serial.println ("timer expired");
    }

This works because the variables are unsigned integers.
Unsigned means there are no negative values

You can test this if you calculate

unsigned long my1stUL = 0;
unsigned long my2ndUL = my1stUL - 5; // result is a very large number simulating beeing near of a rollover
my1stUL = 1; // simulating beeing just after the rollover

unsigned long my3rdUL = my1stUL - my2ndUL; // still a small number because of unsigned integer-math

best regards Stefan

Roll Over is required for accuracy of your Time completion.
Imagine if you set the Timer On (TON) for 30 seconds and lets, for the sake of explanation here, the Max time for the Milli or Miros is 3000 = 30 seconds. Now if you set the TON when the Count is 1500 and you don't know when the Max count is and now every time you check the timer has counted up to 3000 you have to add the last taken time to the new count. What will happen is you will get to 3000 counts and only have calculated 1500 counts when it Rolls Over. You will need to know the Max Count to determine how much to add to the new count.

I understand this is going to be fairly inaccurate anyway Especially over longer periods of seconds, minutes or hours, but what happens if you are doing a TON for very small Times?
The Accuracy is going to be worse.

@tokoloshe
I'm pretty good in math but I do not understand what you want to explain.
Can you please show all details with easy to follow example-numbers for everything
= example numbers and all detail calculations explicitly posted
that fit to each other?

3000 is 3 seconds not 30 seconds

best regards Stefan

No it is not. You need to learn how subtraction of unsigned numbers works. This has already been pointed out to you several times in the above posts.

No. Exactly as @gfvalvo and others wrote, the subtraction of unsigned numbers ensures that it does not matter where is the beginning and where is the end, the difference will be correct if the measured time period is less than maximal possible value.
The best way is to try it by yourself.

Graphically -

3 Likes

Are we to understand you need to time intervals exceeding 49.71 days with millis()?

Or is it intervals greater than 71.58 minutes that you need to use micros() for?

a7

lol Sorry mate I have very bad vision so missed the Zero on the end. Should have been 30 seconds

The wokwi-simulator uses a very detailed simulator of the Atmel328P
Though integer-math is on the level of c++.

Here is a short demo-code that demonstrates the behaviour of unsigned integer-math

You can upload this code to any microcontroller and test it yourself

best regards Stefan

1 Like

This is new for me. :+1:
Wokwi. Nice!

not sure what this is trying to say.

you do know the Max count by the variable type, in this case unsigned long, and so does the computer which does the math correctly when subtracting 2 unsigned long values, A - B even when B > A

Delta_G,
Thanks for that excellent explanation.

I wrote a simple sketch using the figures that you used in your example, just to verify your explanation.

unsigned long starttime = 4294967280;
unsigned long nexttime = 4294967284;

void setup() {
 Serial.begin(9600);
 Serial.print("                starttime = ");
 Serial.println(starttime);
 Serial.print("   4294967284 - starttime = ");
 Serial.println(nexttime - starttime);
 Serial.print("            1 - starttime = ");
 Serial.println(1 - starttime);
 Serial.print("        29984 - starttime = ");
 Serial.println(29984 - starttime);
}

void loop() {
}

and the results:
Screenshot 2023-05-17 092626

(note: I had to change your 29980 to 29984 to get an answer of 30000).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.