I just wondered. The "millis()" function starts the timing after Arduino started. Its maximum value is directly related with the used variable, unsigned long. When I calculate it and convert it in terms of seconds, I get the operating time is up to 50 days ,approximately.
Again, I just wondered,
Did anyone use this function more than a few days ?
If it is like that, did the reading value correspond to the real one ?
(In fact, I am not expecting that it will give the real value, since there can be some noise due to the environment. However, I expect some very acceptable value.)
I will be glad to know your experiments about that.
I built a display that used multiple Arduinos all running the same code and all using micros(); for timing. Within a minute you could see them getting out of sync. Actually, they went out of sync so fast I had to redo the code so one processor was "master" and ran the others as slaves to it.
So my vote is the timers are not all that accurate.
The timer is inaccurate for sure - I built analog RTC circuits that use millis() to keep track of the time. As long as the temperature is kept within a few degrees or so, they are consistent. My clocks use crystals with well matched capacitors, right next to the tiny85 microprocessor. I calibrate them against the WWVB clock by scaling the count to a measured value.
My oldest clock, has been running since September 2015, and it is accurate to no more than 15 minutes over 14 months. A companion DS3231 which I set at the same time, is less than a minute and a half off.
If you use subtraction with millis() - for example if (millis() - previousMillis >= interval) it will work properly for ever, even when the counter overflows at the end of about 49 days
The Arduino 16MHz oscillator does not run at precisely 16MHz so timekeeping with millis() will not stay in sync with a proper clock. If that matters you need to use a Real Time Clock (RTC) module.
jimLee:
I built a display that used multiple Arduinos all running the same code and all using micros(); for timing. Within a minute you could see them getting out of sync. Actually, they went out of sync so fast I had to redo the code so one processor was "master" and ran the others as slaves to it.
So my vote is the timers are not all that accurate.
-jim lee
Timers are as accurate as the source that feeds them
I'm writing this sketch to measure and provide a correction value for millis, it's still a work in progress but works as is. Connect a button between pin 4 and ground, start Serial monitor, use an accurate clock (I prefer a sweep second hand), when the hand is dead on 12 press and release the button quickly and just let it run for a couple of hours, if the Arduino is off by more than 3 seconds, wait until the second hand is dead on 12 and press & release the button, it will tell you how much the Arduino is off and add or subtract that from the "milsPerMinute" variable, let it run for a few more hours and after it gets off by at least 2 or 3 seconds, do it again. I had one Chinese Nano that was off by a second every 14 minutes and was able to tune it to 1 second off in 54 hours, the final "milsPerMinute" was 60081. So a milli is really 998.652 micros.
Feel free to crack, hack and repack.
extern volatile unsigned long timer0_millis; // temporary kludge
unsigned long startTime;
long milsPerMin = 60000, currentMils, diff;
unsigned int minutes, currentMin;
const byte btnPin = 4, ledPin = 9;
bool btn = true, oldBtn = true;
void setup()
{
Serial.begin(9600);
pinMode(ledPin,OUTPUT);
pinMode(btnPin,INPUT_PULLUP);
delay(2);
while(bitRead(PIND,btnPin)); // wait for button press
while(! bitRead(PIND,btnPin)) // & release
{
timer0_millis = 0; //reset millis()
startTime = millis();
}
}
void loop()
{
// minute flash *************************************************
if(millis() - startTime >= milsPerMin)
{
startTime += milsPerMin;
minutes++;
Serial.print(minutes); Serial.print("\t");
Serial.println(millis());
digitalWrite(ledPin,HIGH);
}
if(millis() - startTime > 30)
digitalWrite(ledPin,LOW);
//***************************************************************
// check for button press ***************************************
btn = bitRead(PIND,btnPin);
if(!btn && btn != oldBtn)
update();
oldBtn = btn;
}
//***************************************************************
void update()
{
currentMils = millis(); // save current millis()
currentMin = minutes; // " " minutes
if(currentMils % milsPerMin > milsPerMin / 2) // if past 1/2 minute, increment current minute
currentMin += 1;
diff = (currentMils - currentMin * milsPerMin) / currentMin; // difference in what it is & should be
milsPerMin += diff; // apply correction to milsPerMinute
minutes = 0;
timer0_millis = 0; // reset millis, will eliminate this in future :-)
startTime = millis();
Serial.print(currentMin); Serial.print("\t");
Serial.print(currentMils); Serial.print("\t");
Serial.print(milsPerMin); Serial.print("\t");
Serial.print(diff); Serial.println();
delay(500);
oldBtn = btn;
}
Of course the resonator (oscillator) is still subject to drift with VCC and temperature variation.
That's similar to the method I use, but the Arduino ceramic resonnator has about ten times the drift of a quartz crystal. Also temperature stability is very important. Some RTC devices use a little heater.
jimLee:
I built a display that used multiple Arduinos all running the same code and all using micros(); for timing. Within a minute you could see them getting out of sync. Actually, they went out of sync so fast I had to redo the code so one processor was "master" and ran the others as slaves to it.
So my vote is the timers are not all that accurate.
-jim lee
The "micros()" command might be a bit worse than the "millis()" command, since it counts as the level ten to the power six. It's my opinion, of course
sterretje:
Timers are as accurate as the source that feeds them
Also that depends on the thing what @sterretje However, it's a better way to measure it. Thank you for the experiment..
ChrisTenone:
The timer is inaccurate for sure - I built analog RTC circuits that use millis() to keep track of the time. As long as the temperature is kept within a few degrees or so, they are consistent. My clocks use crystals with well matched capacitors, right next to the tiny85 microprocessor. I calibrate them against the WWVB clock by scaling the count to a measured value.
My oldest clock, has been running since September 2015, and it is accurate to no more than 15 minutes over 14 months. A companion DS3231 which I set at the same time, is less than a minute and a half off.
Which Arduino board did you use ? (I mean, that error may be changed by the board capabilities in terms of hardware inside of it.) However, it's acceptable value for over 14 months
Robin2:
Two different issues have been mentioned here.
If you use subtraction with millis() - for example if (millis() - previousMillis >= interval) it will work properly for ever, even when the counter overflows at the end of about 49 days
The Arduino 16MHz oscillator does not run at precisely 16MHz so timekeeping with millis() will not stay in sync with a proper clock. If that matters you need to use a Real Time Clock (RTC) module.
outsider:
I'm writing this sketch to measure and provide a correction value for millis, it's still a work in progress but works as is. Connect a button between pin 4 and ground, start Serial monitor, use an accurate clock (I prefer a sweep second hand), when the hand is dead on 12 press and release the button quickly and just let it run for a couple of hours, if the Arduino is off by more than 3 seconds, wait until the second hand is dead on 12 and press & release the button, it will tell you how much the Arduino is off and add or subtract that from the "milsPerMinute" variable, let it run for a few more hours and after it gets off by at least 2 or 3 seconds, do it again. I had one Chinese Nano that was off by a second every 14 minutes and was able to tune it to 1 second off in 54 hours, the final "milsPerMinute" was 60081. So a milli is really 998.652 micros.
Feel free to crack, hack and repack.
extern volatile unsigned long timer0_millis; // temporary kludge
unsigned long startTime;
long milsPerMin = 60000, currentMils, diff;
unsigned int minutes, currentMin;
const byte btnPin = 4, ledPin = 9;
bool btn = true, oldBtn = true;
forty69:
Which Arduino board did you use ? (I mean, that error may be changed by the board capabilities in terms of hardware inside of it.) However, it's acceptable value for over 14 months
I didn't use an Arduino board, I used a tiny85 with a 16 MHz crystal.