Arduino Crystal vs. DS3231 TXCO

crystal

I tested the accuracy of a crystal on one of my Arduino Duemilanove (ATmega168 version) boards. I compared the crystal against a TXCO (ChronoDot). The following graph shows the results.

Arduino Crystal vs. ChronoDot TXCO

Note: I’m not sure about the “3 glitches” present in the data at the 99th, 199th and 291st samples.

After 5 minutes the difference between the arduino timer and the TXCO was 33060 microseconds (us), or 0.033112 seconds. That works out to a 0.397344 second error after one hour. It was averaging a delta of 110.2 per second, or 110.2/16 (MHz) = 6.9 PPM. After 2 minutes of testing, I rested my thumb heavily on the arduino crystal in an attempt to heat it and see if that would have an affect. The data varied by slightly more than 1 PPM.

I’m impressed.

Test Rig: Arduino with ChronoDot connected.

Sample output from arduino program:

#Starting Test
0, 0
1, 112
2, 224
3, 332
4, 444
5, 556
6, 664
7, 776
8, 888
9, 996
10, 1108
11, 1220
12, 1328
...

Arduino Program:

/*
  1 Hz Test
  Copyright 2012, all rights reserved.
  James M. Eli
  1/9/2012

  project parts:
    (1) arduino 16MHz
    (1) ChronoDot RTC (DS3231SN)
    (1) breadboard
    (1) 10 ohm resister (pullup)
    (7) wires

  DS3231SN TXCO RTC (ChronoDot) pin outs:
  CD - Arduino - Port
  SQW - D2  - Port D2 (tied thru 10K resister to VCC)
  GND - GND - Ground
  VCC - VCC - 5V
*/
#include <Wire.h>

//millisecond counter
volatile unsigned long my_timer0_millis;
//ms counters for arduino & TXC0
volatile unsigned long us_t, us_a;
//boolean flag
volatile bool flag;

//this interrupt is called on a TCXO RTC 1Hz SQW
ISR(INT0_vect) {  //PD2 or D2 pin
  unsigned long m;
  uint8_t t;

  //assumptions here: arduino 168/328 running @ 16MHz
  m = my_timer0_millis;
  t = TCNT0;
  if ((TIFR0 & _BV(TOV0)) && (t < 249))
    m++;
  //save current microsecond [us] count
  us_a = ((m*250) + t)*(64/clockCyclesPerMicrosecond());
  //set flag
  flag = true;
}

//timer0 interrupt handler
ISR(TIMER0_COMPA_vect) {
  //incremented every 1ms by arduino timer0
  my_timer0_millis++;
}

//returns current millis count
unsigned long myMillis(void) {
  unsigned long m;
  uint8_t oldSREG;

  oldSREG = SREG;
  cli();
  m = my_timer0_millis;
  SREG = oldSREG;
  return m;
}

void setup(void) {
  //init various
  us_t = 0;
  flag = false;
  //turn off interrupts
  cli();

  //replace arduino timer0 code with our timer
  my_timer0_millis = 0;
  //16Mhz/64 prescale/250 counts = 16000000/64/250 = 1000us (1ms)
  TCCR0A = 0;
  TCCR0A |= (1<<WGM01); //CTC mode, top=OCR0A, TOV0 set@max, update immediate
  TCCR0B = 0;
  TCCR0B |= (1<<CS01) | (1<<CS00); //Fcpu/64
  TIMSK0 |= (1<<OCIE0A); //enable CTC A interrupt
  OCR0A = 249; //249 results in a 250 count rollover
  TCNT0 = 0;

  //setup digital #2 external interrupt
  EICRA |= (1<<ISC00) | (1<<ISC01);  
  EIMSK |= (1<<INT0);

  //enable interrupts
  sei();

  //init wire & serial
  Wire.begin();
  Serial.begin(9600);
  //setup square wavew at choice of 0=1Hz/8=1024Hz/16=4096Hz/24=8192Hz
  Wire.beginTransmission(104);
  //select control register
  Wire.send(0x0e);
  //set square wave @ 1 Hz
  Wire.send(0);
  Wire.endTransmission();
}

void loop(void) {
  Serial.println("# Starting Test");

  while(1) {  //endless loop
    if (flag) {
      if (us_t == 0)
        us_t = us_a;
      else
        us_t += 1000000;
      Serial.print(us_t/1000000);
      Serial.print(", ");
      Serial.println(us_a - us_t);
      flag = false;
    } //if
  }   //while

}     //loop
Advertisements

About Jim Eli

µC experimenter
This entry was posted in Uncategorized and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s