I am making a clock on an Arduino Mega using interrupts to facilitate time-keeping. The following is my timer breakdown:

  • Timer0: Used for my calls to millis() which allows me to determine when a second has passed.
  • Timer1: Used to interrupt at 8000Hz and play a sound sample on the fast PWM pin.
  • Timer2: Used for fast PWM in order to approximate sound.

My time seems to be accurate for roughly 15-25 minutes and then it starts to lag behind the phone time I am using as a comparison. I am wondering if this is bound to happen using interrupts to keep track of time, or if there is something I am doing in my ISR that might be slowing things down. My ISR looks like the following:

  // re-enable global interrupts so that other ISRs can execute (millis can keep incrementing)
  // As per: https://forum.arduino.cc/index.php/topic,46133.0.html#4

  test_time = millis();
  if (test_time - start_time >= 1000) {
    start_time = test_time;
    // ... play some audio

Setting up Timer1 is done as follows where SAMPLE_RATE = 8000:

void  init_timer(void) {
  noInterrupts (); //  Disable  all  interrupts

  //  Clear  Timer1  register  configuration
  TCCR1A = 0;
  TCCR1B = 0;

  //  Configure  Timer1  for  CTC  mode (WGM = 0b0100)
  bitSet(TCCR1B , WGM12);

  //  Disable  prescaler
  bitSet(TCCR1B , CS10);

  // Set  timer  period , which is  defined  as the  number  of
  // CPU  clock  cycles  (1/16 MHz) between  interrupts  - 1
  OCR1A = (F_CPU / SAMPLE_RATE) - 1;

  //  Enable  timer  interrupts  when  timer  count  reaches  value in  OCR1A
  bitSet(TIMSK1 , OCIE1A);

  //  Enable  interrupts
  interrupts ();
  • What drift are you experienceing? It might just be the inaccuracy of the crystal and not the interrupts counting wrong. – Maximilian Gerhardt Nov 23 '19 at 20:09
  • I have just been eyeballing the drift. After about 30 minutes I notice that it has lagged ~1 second. – peachykeen Nov 23 '19 at 20:12
  • Hm over ~-550ppm drift is pretty bad, crystal oscilators I've looked at have about +/-100ppm. Have you done a negative test, like doing just a minimal sketch without your ISRs which prints millis() and tracking the drift? Also would an external RTC (like DS3231) be an option? – Maximilian Gerhardt Nov 23 '19 at 20:25
  • 3
    @MaximilianGerhardt: The Mega is not clocked off a crystal: it uses a ceramic resonator instead. 555 ppm is consistent with the accuracy you can expect from a ceramic resonator. C.f. jorisvr.nl/article/arduino-frequency – Edgar Bonet Nov 23 '19 at 21:45
  • 1
    The resonator accuracy can be as bad as 0.1% ( 1000 ppm ) but should be rather consistent with stable temperatures. If you increment odd seconds every 999 ms, and even seconds every 1000 ms, you should be fine currently :) Your error will be less by one magnitude (factor 10) ( A second off per ~4 hours). But there are more accurate external time signals (RTC, NTP). BTW: Long term accuracy is great for the power grid frequency, and available everywhere, – DataFiddler Nov 23 '19 at 23:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.