I want have millis() or (1ms ticks) precise - therefore I plan to use a 16.384Mhz crystal. Are there any negative implications I have to be aware of?
How is the crystal to be used? Need a little context.
A 16.384MHz crystal instead of the 16.000MHz crystal. Such crystal gives 1.0000ms T0 interrupt (millis). That is important for rtoses, loggers, etc (when used as a tick). Maybe micros would be affected, but that is not so important in practise. Bootloader and boards.txt will be adjusted accordingly.
Uart - will be more precise (closer to 115k2) SPI - no issue PWM - no issue I2C - no issue micros() - ? ..
Sorry, my bad, I read it as kHz, not MHz :blush:
I thought I had read (in the forum) that the millis, or maybe micros, count was adjusted by 1 count every so many cycles to keep the time precise (due to counting 1000 ticks vs 1024), something along those lines.
The crystals are easy to get and cheap, therefore my investigation (the same for 8.192MHz) on possible side-effects.. Why to mess with sw when I can do it in hw :)
technically out of spec for some avr so if a medical or other mission critical application not a good idea. theres virtually zero chance of failure but it becomes an insurance/liability issue upon even unrelated mishap. in that case the 8.192 would be better choice. for hobby i have no problem boosting 16mhz chips to 20mhz or even higher. or running 16mhz at 3v.
personally i think 8mhz/16mhz chosen by original designers and perpetrated by clones was a huge mistake. almost anything else is better from standpoint of serial reliabilty. even internal osc is more accurate if calibrated properly.
john1993: technically out of spec for some avr
How so? For many of the MCUs commonly discussed here, the spec is 10MHz or 20MHz. For example, ATmega328P, 10MHz @ 2.7V, 20MHz @ 4.5V.
for hobby i have no problem boosting 16mhz chips to 20mhz or even higher.
Many are already 20MHz chips.
medical or other mission critical application not a good idea
Hopefully nobody uses arduino for such purposes :)
Arduino? Probably not. AVR, probably so. 8)
If you're going to use your own timer rather than rely on millis, I don't see a down side. That's not a heavily qualified endorsement because I've never tried it, and certainly not run it through compatibility testing with all the common libraries, but from the code perusing I've seen, I can't imagine you'll have any show-stoppers. Certainly worth a shot.
delayMicroseconds() may prove an issue. They use NOP instructions to time that function - at 16MHz, one microsecond is timed by performing 16 instructions giving 16/16MHz = 1us. For your crystal you would have 16/16.384MHz = 0.976us
Well, micros and friends are usually used with one-shot events, where the error does not accumulate. For example a 2.4usec error with a 100usec delay used from time to time somewhere is a smaller issue than a tick based on millis used for logging (for longer periods) or system-tick for rtos task scheduling. For example a data logging for 1 hour period does 45secs difference with 16MHz crystal.
pito: For example a data logging for 1 hour period does 45secs difference with 16MHz crystal.
Only if the crystal is defective or you have a bug in your sketch.
The hardware isn't the issue. I have a precise 1 mS count in a sketch on this page:
After all, if you have a 16 MHz clock and divide by 16000 you get precisely a "tick" every mS. And the timer hardware can do just that (Timer 1).
I should also point out that millis() compensates for the fact that it ticks every 1.024 mS. So it is only cumulative for a small time, then an adjustment is made in the code. So it should be only out by a small fraction at any given point. Also micros() is more accurate, however has a 4 µS resolution. The use of Timer 1 to provide your own exact 1 mS ticks solves both those problems, assuming you don't need the timer for anything else.
If you don't need to use both of the PWM outputs available from timer 0, then you can program timer 0 to divide by 250 instead of 256, and thereby get proper 1ms ticks when using a 16MHz crystal.
Hmmm, I have to double check.. :~ To recap: the experts say the 16MHz/64/256 on timer0 is compensated in long run against 1.024, I can see there is a calculus which probably does it.. (how precise?) However, I ran NilRtos and the NilTimeNow() gave me a ratio 1.0239 against my external time, long run. So it seems NilRtos does not compensate..
pito: (how precise?)
With the Arduino core, exact.
[quote author=Nick Gammon link=topic=182803.msg1354838#msg1354838 date=1376601418] The hardware isn't the issue. I have a precise 1 mS count in a sketch on this page:
After all, if you have a 16 MHz clock and divide by 16000 you get precisely a "tick" every mS. And the timer hardware can do just that (Timer 1). [/quote]
That assumes he can use Timer1.
millis() uses Timer0 - only 8 bits. I'm not sure Timer0 can divide by exactly 16000.
OTOH I'm not sure that millis() will work with 16384, I haven't looked at the source code.
fungus: millis() uses Timer0 - only 8 bits. I'm not sure Timer0 can divide by exactly 16000.
Prescaler of 64, overflow at 250. That gives you 16000000/64/250 = 1000 interrupts per second = 1ms/interrupt