I think TXCO was the term I needed to feed Google. This helped But by now I think I will opt for one of the used time normals. Just for the sake of a real overkill
With regard of how to figure out 203 ppm deviation without a scope:
Step 1: figure out that it actually drifts at all. I used this with the help of a quick an dirty program like this.
#include <WProgram.h>
volatile uint32_t latency = 0;
void delay_micros(uint32_t us) {
// overhead of the function call delays > 1us
if (--us == 0)
return;
// the following loop takes a 1/2 microsecond (8 cycles)
// execute it 2 times for each microsecond requested.
us <<= 1;
// account for the time taken in the preceeding commands.
us -= 1;
__asm__ __volatile__ (
"1: nop" "\n\t" // 1 cylce
" nop" "\n\t" // 1 cylce
" subi %A[micros],1" "\n\t" // subtract immediate, 1 cycle
" sbci %B[micros],0" "\n\t" // subtract with carry, 1 cycle
" sbci %C[micros],0" "\n\t" // subtract with carry, 1 cycle
" sbci %D[micros],0" "\n\t" // subtract with carry, 1 cycle
" brne 1b" "\n\t" // 2 cycles (1 in the last pass)
:
: [micros] "a" (us) // constraint: simple upper register
);
}
int main() {
// pin 7 = portd 7 --> this will be our input
// pin 6 = portd 6 --> this will be our output
// we will set PIN 6 to low and wait till we see a high a PIN 7
// the time in between is measured in lateancy
const uint8_t in_mask = 0xff;
pinMode(6,OUTPUT);
digitalWrite(6, HIGH);
pinMode(7,INPUT);
digitalWrite(7, HIGH);
Serial.begin(115200);
Serial.println("countdown");
for (int i = 2; i > 0; --i) {
Serial.println(i,DEC);
delay_micros(1000000);
}
Serial.println("go");
// capture 1024 at 1 byte each 3 seconds
// trigger if any of the bits in mask changes
uint8_t tmp; // dummy for temporary register
__asm__ __volatile__ (
"push r24" "\n\t"
"push r25" "\n\t"
"push r26" "\n\t"
"push r27" "\n\t"
"eor r24,r24" "\n\t"
"eor r25,r25" "\n\t"
"eor r26,r26" "\n\t"
"eor r27,r27" "\n\t"
"cli" "\n\t"
"cbi %[out_port], %[out_pin]" "\n\t"
"1: adiw r24, 1" "\n\t" // 2 cycles
"adc r26, __zero_reg__" "\n\t" // 1 cycle
"adc r27, __zero_reg__" "\n\t" // 1 cycle
"nop" "\n\t" // 1 cycle
"sbis %[in_port], %[in_pin]" "\n\t" // 1 cycle for not branching, 2 cycles for branching
"rjmp 1b" "\n\t" // 2 cycles
"sei" "\n\t"
"sts latency, r24" "\n\t"
"sts latency+1, r25" "\n\t"
"sts latency+2, r26" "\n\t"
"sts latency+3, r27" "\n\t"
"pop r27" "\n\t"
"pop r26" "\n\t"
"pop r25" "\n\t"
"pop r24" "\n\t"
:
: [out_port] "M" (_SFR_IO_ADDR (PORTD)),
[out_pin] "M" (6),
[in_port] "M" (_SFR_IO_ADDR (PIND)),
[in_pin] "M" (7)
);
Serial.print("Microseconds: ");
Serial.print(latency/2,DEC);
Serial.print('.');
Serial.println(5*(latency%2),DEC);
Serial.println();
for (;;) {}
}
It's actuall two of them each running on different boards. If I switch them I see that they deviate a lot. And since all interrupts are off this is most probably crystal drift. And by then I know that this is a relative error of 203 ppm.
Step 2: figure out which one in the culprit (or both):
Create a loop that runs for 100 000 seconds and then blinks
(actually I have already a clock application, but this describes the idea). So I run this for 100 000 seconds beside a DCF77 clock. Those are cheap. 203 ppm means that I can see 20 seconds deviation after a little more than a day.
Now how could I get it precise?
Step 3: either increase the time or increase the time resolution of reading. --> use a digital camera to make a video of the start and the end of the period and use the computer as a time lense.
Result: I can measure ~1ppm in a little more than one day
What project has such requirements: my "beginner project" for learning the arduino is kind of a killer "stopwatch". Once it is finished I will exhibit and describe what I did. Until then I consider it bad practice to go into details of the unlaid egg. I confess that what I am doing is most probably the definite timing overkill. But who cares, it's my time (and my timer )
Current estimate: >7000 lines of code (in 5 months) so far, maybe 5000-10000 and 6 months more till completion of the software part. Hopefully everything finished till end of 2010. I think for a spare time project my speed is quite OK so far.
The bigger obstacles will be the hardware part and a proper enclosure. But I am determined to get a "professional" result.
The anyoing part right now is: I have 4 boards. The freeduino and arduino do not drift that much. But my hacked and heavily modified board that has to carry the application is the one that drifts. So this is really annoying