Pages: 1 2 [3] 4 5 6   Go Down
Author Topic: Millis Accuracy Again  (Read 6331 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 545
Posts: 27352
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

In my designs I use this slightly less expensive crystal
(35 cents vs 48 cents)
http://www.digikey.com/product-detail/en/ATS16B/CTX1085-ND/2640031
Frequency Stability ±50ppm
Frequency Tolerance ±30ppm


You could also sync to the 1 pulse per second from a GPS receiver.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A simple sketch printing the value of millis()/1000 every second shows that my UNO Rev 3 is losing a little over three seconds an hour, pretty consistently. I assume that's how accurate the resonator is.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm losing much more than that.. about 120 seconds in 4000+ seconds.  smiley-eek-blue

I'll probably use an external RTC to sanity-check against millis().  Short-term accuracy of millis() is OK, so this scheme should work.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm losing much more than that.. about 120 seconds in 4000+ seconds.  smiley-eek-blue

How about posting a sketch that demonstrates the problem? Preferably with extraneous code removed.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

With an external clock interrupting every 1 ms sharp and incrementing the value of an unsigned long, you'd be able to use that variable instead of millis().

It might be off if another interrupt is acting but ISR's are supposed to be short for a reason.

I wonder how short serial print() is? One way to influence serial print() time is to limit serial text and send values over as packed binary, and only send raw or compressed data. Set up a Processing sketch to get those bytes in the PC, process and make the CSV file and your Arduino will have more cycles for aiming and data capture.

I promise you, if you can code Arduino, you can code Processing. It will help greatly with resource headaches.
http://www.processing.org/
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried rolling my own millis() using an ISR. The ISR only increments a volatile global (absolute minimum).

It still loses time (about 3 seconds over a 1200-second interval) compared to my NTP-synced laptop clock. So it does seem that something (arctangent, SPI library.. or it could be Serial.print itself) is somehow causing both millis() and my custom ISR to lose ticks. Although I've reduced the frequency of the above to 1/second (hence only lose 3 seconds rather than  60). Time to look at an external RTC. Obviously I can't use the 1PPS to interrupt, I'd lose time too. I'll have to read the RTC in my main loop.
« Last Edit: April 17, 2013, 07:09:28 pm by orly_andico » Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did you try with an ***external*** oscillating source?
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No, I have not... but if the millis() or other ISR is getting masked, an external source would also lose ticks. I don't have a precise external time base anyway so the RTC seems the way to go. Looks like the PCF8583 is the way to go, 8-pin DIP, through-hole, 10ms accuracy.
« Last Edit: April 17, 2013, 07:47:14 pm by orly_andico » Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok someone just told me that the interrupt priority goes...

External interrupts, USB, WDT, Timer 1, Timer 0, SPI, USART...

So am I right in assuming that it's actually Serial.print() which is screwing with my timekeeping?

millis() / micros() uses Timer 0 right?

So if I hook up an external clock generator, I can get ticks that don't get masked by Serial.print() ?
« Last Edit: April 17, 2013, 11:48:04 pm by orly_andico » Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I sped thru the thread, but I want to say a couple things.  I'm sorry if I am redundant on this.

1)  millis() runs every 1.024 mS.  That means that it is always in error by some amount.  Every 40 or so times, millis() increments by 2 to get back on track.  Overall, millis() keeps great time and you can indeed make a clock using it as crossroads indicated by creating a "rolltime" and always adding 1000 to it.  I have one here that loses 30 seconds per day consistently because my resonator is off by 300ppm.  My other UNO is only off by a few ppm at room temp and should keep excellent time using the resonator.  I just haven't switched it to this other project because of all the jumper wires.  It should be accurate to within a couple of seconds per day using just a ceramic resonator.

2) since millis() only needs to handle rollover roughly once per mS, there is no reason that other "well behaved" ISRs would make millis() miss a count.  OTOH, millis() takes approx 6uS to execute and causes all kinds of jitter with other things.

« Last Edit: April 18, 2013, 12:02:18 am by afremont » Logged

Experience, it's what you get when you were expecting something else.

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok someone just told me that the interrupt priority goes...

External interrupts, USB, WDT, Timer 1, Timer 0, SPI, USART...

So am I right in assuming that it's actually Serial.print() which is screwing with my timekeeping?

millis() / micros() uses Timer 0 right?

So if I hook up an external clock generator, I can get ticks that don't get masked by Serial.print() ?
They don't get lost, they just get delayed. So if an external interrupt and timer0 interrupt happen on exactly the same clock cycle, it will run the external interrupt and, when it's done, run 1 instruction from the main program and then run the timer0 interrupt (the arduino will NOT stop one interrupt to run another of a higher priority, the priority list only comes into play in the extremely rare circumstance that they both happen on the same mid-clock cycle or whatever it says in the datasheet) You only have a problem when the external interrupt takes so long that two timer0 interrupts happen while it's running. Otherwise, the one instruction preformed between the two interrupts could make the time off, but unless that instruction is cli (which is executed as the second instruction in millis()) the time will be correct.

So: the time could be off by up to 2ms+time of an interrupt at a time, but only in extremely rare circumstances, and it will resync (ie no drift). However, if you have an interrupt that takes longer than 1ms to execute, you will start losing time and getting drift. Also, if the resonator is off your time will, obviously, be off.

Using an RTC with an external interrupt will have the same potential problems except there's no 1.024 thing which could make your time off by 2ms. And their crystals are often better.
Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I should add that SoftwareSerial can make millis() lose ticks if you use a baud rate of 9600 or slower since it takes excessive liberty with cli().  Use AltSoftSerial instead.  It uses a timer (Timer1 I think) to generate the outgoing bits instead of burning up cycles in a loop (with ints disabled) between bits.  It's also more clever during receive.
Logged

Experience, it's what you get when you were expecting something else.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1) I'm using Serial.  Not sure if this is SoftwareSerial or whatever.

2) Everything I read is that millis() shouldn't lose so much time.  But I see what I see.  My laptop clock could be wrong (even though its actively NTP-syncing).  But the telescope tracking is off, and this is detectable by watching a star (the ultimate reference).  So I know the Arduino is forcing the tracking off, which can only be explained by its losing time.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 98
Posts: 4813
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No, I have not... but if the millis() or other ISR is getting masked, an external source would also lose ticks. I don't have a precise external time base anyway so the RTC seems the way to go. Looks like the PCF8583 is the way to go, 8-pin DIP, through-hole, 10ms accuracy.

It will only be late by as much time as the current ISR takes to finish, then it should run. The next tick, being from external, will still come 1 ms after the last was -sent-. And it looks like Serial is the real bugger in this case.

I have Arduino-compatible Teensy's. Their Serial goes straight to USB, there's an IDE patch for them and they are cheap but I do recommend to get the pins unless you are very good soldering heavy pins very close to surface mount parts. Not me.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

2) Everything I read is that millis() shouldn't lose so much time.  But I see what I see.  My laptop clock could be wrong (even though its actively NTP-syncing).  But the telescope tracking is off, and this is detectable by watching a star (the ultimate reference).  So I know the Arduino is forcing the tracking off, which can only be explained by its losing time.
No, I'm saying that the SOFTWARE won't lose time. Everyone knows the resonator is only accurate to 0.5%, which could be up to be seven minutes over a day or 18 seconds per hour or 6 seconds per 1200 second period (twice what you measured)
Logged

Pages: 1 2 [3] 4 5 6   Go Up
Jump to: