millis() off by 20%?

hi folks,

i've been having timing issues with one of my sketches, and eventually figured out that millis() is fast by about 20% on my board (Uno). In my sketch, i log a line once every 1000ms (as received by millis()). I've also got a GPS attached, so i can check the internal time against the GPS time.

It's pretty consistent, but for every 10s that passes on the GPS, about 7800ms (give or take a hundred or so ms to account for lag) passes on the internal clock.

Does anyone know why this might be happening? I googled around for others having this problem, but i only found folks talking about millis being off around 5s per day.

Thanks.

Have you changed the crystal?

I don't find it all that remarkable that the ceramic resonator is off by 20%.

Really?

I would find that very remarkable and if so, put it off as a mismarked resonator or defective.

SparkFun rates their 16mhz resonator at +/-0.5% or better from -20C-+80C.

PS: A resonator with a 20% error would not even be able to upload sketches from the IDE as the bootloader sets up the baudrate assuming a 16mhz clock frequency.

Lefty

Which is exactly why the Arduino folks used a real crystal in the "USB" processor and not a ceramic resonator. Your honor, I rest my case.

Your honor the witness doesn't know what he is talking about. Even if the 8u2 clock was 100% accurate the serial communications between the 328p and the arduino IDE couldn't possibly work if the 328p clock was 20% off as it is what determines what speed the serial data is clocked into or out of the hardware usart in the 328p. The hardware serial library calculates the baudrate divider hardware in the 328p assuming a 16mhz clock, as does the bootloader code to allow uploading of a sketch. An arduino with a processor clock error of 20% just wouldn't function with the IDE.

Are you sure you wish to rest your case before the jury?

Lefty

__Tango:
i've been having timing issues with one of my sketches, and eventually figured out that millis() is fast by about 20% on my board (Uno). In my sketch, i log a line once every 1000ms (as received by millis()). I've also got a GPS attached, so i can check the internal time against the GPS time.

It's pretty consistent, but for every 10s that passes on the GPS, about 7800ms (give or take a hundred or so ms to account for lag) passes on the internal clock.

Does anyone know why this might be happening? I googled around for others having this problem, but i only found folks talking about millis being off around 5s per day.

It seems very strange that millis() seems to be 20% out but the serial port is working normally. Can you post your sketch? Are you using arduino-0022?

KE7GKP:
And yet __Tango's Uno appears to be accepting (and presumably sending) serial data between the Arduino processor and the USB processor. Even with a 20% error.

I haven't even looked into Tango's problem. I'm just responding to your statement that ceramic resonators can have up to 20% error. Again I will state, the Arduino board could not even function with the IDE if the clock was 20% off value from 16mhz. I showed you accuracy specification of one rather inexpensive resonator showing it's accuracy specification. Have you any links to datasheets showing a 16Mhz ceramic clock resonator for sale with a 20% accuracy tolerance specification?

What is your theory for why they used a real crystal on the USB processor, but a cheap ceramic resonator for the Arduino processor? Upon casual observation, that would seem backwards.

I have no idea what drove the Arduino people to use both a crystal and a resonator on the board. I know on first release the Uno board's picture showed using two crystals.

Lefty

Tang;

Yes, please show your sketch. The only thing I can think of that could cause such a large error in you millis() function over time is if you are somehow directly or indirectly causing interrupts to be disabled for long periods of time. As millis() utilizes a timer interrupt, it's important not to disable interrupts any longer then necessary.

Lefty

For my own sketch using millis() and Serial.print*() I found that sending data with Serial.println() messes up the counted millis. And the lower the serial console baud rate, the bigger the effect. My conclusion was that the two interfere.

At least setting the baud rate as high as possible solved the problem for the most part.

Dear __TANGO,

could you post your sketch that has the 20% error? maybe there is some logic stopping the millis() clock in it ... That happens sometimes with interrupts etc.

KE7GKP:

  1. __Tango would be reporting a DIFFERENT problem (that he couldn't upload sketches) if there were a problem communicating between the USB processor and the Arduino processor. The fact that he is able to upload code and download test results would appear to be prima facia evidence that the serial and USB communication are operational.

Agreed, and that means the clock frequency of the 328p is accurate enough to support the 115200 baudrate of the bootloader, not something possible if the resonator was off by 20%.

  1. The places that fabricate and assemble PC boards for cheap are deep in the interior of a place where datasheets (even if they did exist) are written in a language foreign to both of us. And those assembly vendors concentrate on delivering the minimum requirement for the lowest price. That is how they survive in their industry. OTOH, if "official" Arduino boards are really manufactured in Italy then we must come up with some other explanation. Or __Tango could have a counterfeit or clone for all we know.

"Official" Arduino boards are made in Italy, however they have lincensed some firms (SparkFun? other?) to manufacture some of their board types. Of course the vast number of Asian 'arduino' boards are not official but are made and sold without regards to and violating the Arduino trademark.

  1. I suspect that the board manufacturer (Arduino?, their vendor?, a counterfeiter?) saves money by requiring only some sort of functionality test at the end of the assembly line and does not reject boards for clock frequency excursions. I continue to reject the notion that a u-proc clock can be used for timekeeping in any meaningful way. We have RTC and TCO for that sort of thing.

Time keeping over longer periods is best done using a RTC or other methods, no disagreement there. Even if one used a high accuracy crystal or TCXO or OCXO clock oscillator, the fact that interrupt useage can effect millis() accumulation over time is a good reason not to use software RTC functions.

  1. They left the hole patterns for a proper crystal for those who find the cheap ceramic resonator intolerable.

Or to give them flexiblity on sourcing parts for batch manufacturing runs. There wanting and receiving FCC type acceptenace for the Uno board could be another reason for their resonator choice. Only someone from the Arduino firm could answer those questions.

  1. I agree that there could be other reasons for __Tango's reported results. But apparently my world-view is not as tidy and accurate as yours. An Arduino board is low-end mass-market consumer goods. Not intended to be any kind of accurate laboratory- (or even industrial-) grade product. Note that there is no published spec for the Uno clock accuracy.

It is a mass-market product for sure, but must have a time base accuracy good enough to support the 115200 baudrate used by the bootloader.

electrickery:
For my own sketch using millis() and Serial.print*() I found that sending data with Serial.println() messes up the counted millis. And the lower the serial console baud rate, the bigger the effect. My conclusion was that the two interfere.

Which one would expect. Serial.print() blocks until the string it has been given has been transferred. So in your case you were actually measuring how long it took to transfer data and not the accuracy of millis().

This is why it is important for the OP to post their code. It is more likely their method for measuring millis() is at fault and not the board itself.

Gentlemen,

Any chance you guys could take your "discussion" offline? It isn't relevant (anymore) to the original poster's question.

Thanks.

Actually I think we scared him away?

Lefty

My Arduino Ethernet is receiving lots of data via NewSoftSerial (actually, the latest version named 'SoftwareSerial' internally) and saving it to an SD card.

I've been using RTClib's millis()-based clock, and it's slow by four hours or more after a 24-hour period. I know NewSoftSerial uses pin change interrupts a lot - could these be getting in the way of the millis() timers?

(The solution is, of course, to use a hardware RTC. And I've discovered one lives in the VC0706 camera. I'm going burrowing...)

I think the problem is that SoftwareSerial disables interrupts for a whole character period when sending or receiving a character. If you are sending or receiving at 9600 baud or slower, this is more than a millsecond and you will lose some of the timer interrupts that are needed for millis() to return the correct value. You could try using a higher baud rate, but a better solution is to use a hardware UART.

If you already are using a higher baud rate, then try setting whatever is sending the data to use 2 stop bits instead of 1.

if it makes you guys feel better, I got a hold of some SF resonators and OMG they are crap, I have constant upload errors at a reasonable 19200 baud, I cant say they are off by 20% per day, but they sure as heck are not spec

but hey when you buy the cheapest garbage from china your often lucky if it works at all, luckily I got them for free so I didnt waste money on them.

Osgeld:
if it makes you guys feel better, I got a hold of some SF resonators and OMG they are crap, I have constant upload errors at a reasonable 19200 baud, I cant say they are off by 20% per day, but they sure as heck are not spec

but hey when you buy the cheapest garbage from china your often lucky if it works at all, luckily I got them for free so I didnt waste money on them.

It may be that they are crap, but are you sure they are not 16384MHz 16**.**384MHz resonators rather than 16MHz?

16384MHz

16384kHz, surely?

Yes, I missed out the decimal point.

Still less than 3% though.