Pages: [1]   Go Down
Author Topic: millis() overflow when? (UNO+22)  (Read 1321 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hallo,
i wanted to make a timer with my LCD so i drafted an early scetch to test its practicality. From general reading on the old forum I was 99% certain that arduinos millis() function would overflow every 9.5 hours or so but mine is still correctly counting for the last 23 hours.

This is the scetch from 0022 IDE running on an UNO

Code:
#include <LiquidCrystal.h>

extern volatile unsigned long timer0_millis ;

unsigned long currentTime;

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

char out[17] ="";

void setup() {
  lcd.begin(16, 2);
  lcd.print("Timer");
  pinMode(9, OUTPUT);
  analogWrite(9, 40);
 
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
}

void reset () {
  timer0_millis = 0UL;
}

void loop() {
  if (!digitalRead(A0)) {
    currentTime=millis();
    //unsigned long days    =currentTime / 86400000;
    unsigned long hours   =currentTime % 86400000 / 3600000;
    unsigned long minutes =currentTime % 86400000 % 3600000 / 60000;
    unsigned long seconds =currentTime % 86400000 % 3600000 % 60000 / 1000;
    unsigned long millisec=currentTime % 86400000 % 3600000 % 60000 % 1000 / 10;
   
    sprintf(out, "  %.2lu:%.2lu:%.2lu.%.2lu", hours, minutes, seconds,millisec );

    lcd.setCursor(0, 1);
    lcd.print(out);
    lcd.setCursor(8, 0);
    lcd.print("Running ");
  } else {
    timer0_millis = currentTime;
    lcd.setCursor(8, 0);
    lcd.print("Paused  ");
  }
 
  if (digitalRead(A1)) {
    timer0_millis = 0UL;
  }
}

So when does the millis() function overflows?


* 18032011056.jpg (709.31 KB, 2592x1944 - viewed 16 times.)
Logged

Portugal
Offline Offline
God Member
*****
Karma: 5
Posts: 962
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Milis uses an 32 bits variable, that as a maximum value of 4294967295 ms, so, in hours its about 1 193.04647, or in days 49.7102696.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That was fast smiley
Thanx so i should propably change my code to include days.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could keep going forever.  Start with a base time of 0:0:0:0.000

Code:
If (millis() < lastmillis) // Rolllover
    {
    baseMillis += 297;
    if (baseMillis > 999)
        {
        baseSeconds++;
        baseMillis %= 1000;
        }

    baseSeconds += 47;
    if (baseSeconds > 59)
        {
        baseMinutess++;
        baseSeconds %= 60;
        }

    baseMinutes += 2;
    if (baseMinutes > 59)
        {
        baseHours++;
        baseMinutes %= 60;
        }

    baseHours += 17;
    if (baseHours > 23)
        {
        baseDays++;
        baseHours %= 24;
        }

    baseDays += 49;

(The millis timer rolls over at 49 days, 17 hours, 2 minutes, 47 seconds, and 297 milliseconds.)

Of course the Arduino CPU clock is only good to about ten minutes a day accuracy so you'll be off pretty far by the time you need to worry about rolling over.
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 178
Posts: 12288
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Of course the Arduino CPU clock is only good to about ten minutes a day accuracy

10 / (24*60) * 100 = 0.69%

The internal oscillator is more accurate than that (after calibrating).  If you have an Arduino with a processor clock that is performing that poorly you need to return it as defective.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, there's no calibration done for millis() -- it assumes that the CPU frequency is its nominal value. And the crystals on the Arduino boards aren't very good ones. But no, they're not that bad. A lousy one might be out by as much as 1 second per week.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 178
Posts: 12288
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
A lousy one might be out by as much as 1 second per week.

(1 / (24 * 60 * 60 * 7)) * 1 000 000 = 1.65343915 ppm

You have an interesting definition of the word "lousy".
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 32
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Brain fart. Actually had meant to say "10 minutes a week" (around a 1000ppm error, although most seem to be within a few hundred) vs. the previous post's "10 minutes a day", but lost the thought before I posted smiley
Logged

Lancashire, UK
Offline Offline
Edison Member
*
Karma: 8
Posts: 1992
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Of course the Arduino CPU clock is only good to about ten minutes a day accuracy so you'll be off pretty far by the time you need to worry about rolling over.

Depends on the Arduino and the coding, I have a couple of Duemilanoves that keep better time than the watch on my wrist (gain around half a second a day).  My Uno was OK to 30 seconds a day.  These are long term tests, the slighty oddball way it increments millis can put it out in the short term.  Without trying to work increments and counting millis() from start and always working from that, its pretty accurate.     

Just checking up on my systems, one Arduino (A real Duemilanove) gained less than 8 seconds over a period of 37 days and the other (cheap Chinese clone) gained 38 seconds over a 17 day period.  These are timed against an NTP synchronised computer.  Once a minute the Computer gets data from the arduinos including millis() and logs them.  The two systems have been running over 18 months, but a HDD failure means my present logs only go back to the end of December 2010. 
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you all for your answers smiley
I dont think I will deal with overflow because 49 days is already an overkill for a timer.Plus I will let Arudino run for a day and measure its drift with my ntpd server.

I did some profiling though. By simply counting how many millis() it takes to complite a loop() i arived at the conclusion tha writting to the LCD is VERY slow.
This two take roughly 4ms to complete
Code:
    lcd.setCursor(8, 0);
    lcd.print("Running ");

and these two onother 5ms (sprintf takes no time)

Code:
    sprintf(out, "%.2ud%.2u:%.2u:%.2u.%.2u",days,hours,minutes,seconds,millisec);
   
    lcd.setCursor(1, 1);
    lcd.print(out);

The rest of the code is way too fast to be counted by millis total ~9ms.
Logged

Netherlands
Offline Offline
God Member
*****
Karma: 5
Posts: 615
A naughty mind is a joy forever.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I did some profiling though. By simply counting how many millis() it takes to complite a loop() i arived at the conclusion tha writting to the LCD is VERY slow.

I don't know your set-up, I did read that driving a LCD using 4 pins of its data-bus is a lot slower as using all 8, maybe you could use it to your advantage.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah it is four pin for the data but there arent many spare outputs left cause in some other projects which I use the same LCD  I have the ethernet Shield pluged in. I should propably update only the parts of the screen that i need but lcd.cursor is slower than printing a single character.... but for the running/paused timer status I will have to figure something more efficient.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To answer the questions regarding the accuracy of the internal oscilator
My little arduino lost 49sec for a run of 2days 17:23:49 so with my calculations it looses 1 sec every 4804 sec which translates to around 1 hour and 20 min and 208ppm

I have upgraded the the code for this project. It can also operate as a Stopwatch Timer and a Countdown Timer with adjustable start times.

I will post the code as soon as I finish the project.
Logged

Pages: [1]   Go Up
Jump to: