Skip to main content
Added program output.
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

You can time reasonably long intervals using Timer 2 (on the Atmega328) as described in my page about timers.

The example there is this:

void startTimer1 () { // reset Timer 1 TCCR1A = 0; TCCR1B = 0; // zero it TCNT1 = 0; TIFR1 |= bit (TOV1); // clear overflow flag // start Timer 1 TCCR1B = bit (CS10) | bit (CS12); // prescaler of 1024 } // end of startTimer1 unsigned long getTimer1Reading () { unsigned long elapsed = TCNT1; if (TIFR1 & bit (TOV1)) elapsed += 65536; return elapsed; } // end of getTimer1Reading void setup () { Serial.begin (115200); Serial.println (); } // end of setup void loop () { Serial.println ("Starting ..."); Serial.flush (); startTimer1 (); delay (7560); float secs = (1.0 / F_CPU * 1024) * getTimer1Reading (); Serial.print ("Time taken = "); Serial.print (secs); Serial.println (" seconds."); } // end of loop 

The code belowabove uses Timer 1 to time an interval up to 8.388 seconds. It users a prescaler of 1024, which means each "count" of timer 1 is 1/16e6 * 1024 of a second (0.000064 seconds, or 64 µs). Since it can count up to 65536 we can time 0.000064 * 65536 = 4.194304 seconds. Then the timer overflows, but we can test the "overflow flag" and know the overflow occurred. That lets us time up to 8.388608 seconds before we miss the fact that there was a second overflow.

This code works even if interrupts are off, because the timing is done by the hardware timer.

Output on my Uno:

Starting ... Time taken = 7.56 seconds. 

You can time reasonably long intervals using Timer 2 (on the Atmega328) as described in my page about timers.

The example there is this:

void startTimer1 () { // reset Timer 1 TCCR1A = 0; TCCR1B = 0; // zero it TCNT1 = 0; TIFR1 |= bit (TOV1); // clear overflow flag // start Timer 1 TCCR1B = bit (CS10) | bit (CS12); // prescaler of 1024 } // end of startTimer1 unsigned long getTimer1Reading () { unsigned long elapsed = TCNT1; if (TIFR1 & bit (TOV1)) elapsed += 65536; return elapsed; } // end of getTimer1Reading void setup () { Serial.begin (115200); Serial.println (); } // end of setup void loop () { Serial.println ("Starting ..."); Serial.flush (); startTimer1 (); delay (7560); float secs = (1.0 / F_CPU * 1024) * getTimer1Reading (); Serial.print ("Time taken = "); Serial.print (secs); Serial.println (" seconds."); } // end of loop 

The code below uses Timer 1 to time an interval up to 8.388 seconds. It users a prescaler of 1024, which means each "count" of timer 1 is 1/16e6 * 1024 of a second (0.000064 seconds, or 64 µs). Since it can count up to 65536 we can time 0.000064 * 65536 = 4.194304 seconds. Then the timer overflows, but we can test the "overflow flag" and know the overflow occurred. That lets us time up to 8.388608 seconds before we miss the fact that there was a second overflow.

This code works even if interrupts are off, because the timing is done by the hardware timer.

You can time reasonably long intervals using Timer 2 (on the Atmega328) as described in my page about timers.

The example there is this:

void startTimer1 () { // reset Timer 1 TCCR1A = 0; TCCR1B = 0; // zero it TCNT1 = 0; TIFR1 |= bit (TOV1); // clear overflow flag // start Timer 1 TCCR1B = bit (CS10) | bit (CS12); // prescaler of 1024 } // end of startTimer1 unsigned long getTimer1Reading () { unsigned long elapsed = TCNT1; if (TIFR1 & bit (TOV1)) elapsed += 65536; return elapsed; } // end of getTimer1Reading void setup () { Serial.begin (115200); Serial.println (); } // end of setup void loop () { Serial.println ("Starting ..."); Serial.flush (); startTimer1 (); delay (7560); float secs = (1.0 / F_CPU * 1024) * getTimer1Reading (); Serial.print ("Time taken = "); Serial.print (secs); Serial.println (" seconds."); } // end of loop 

The code above uses Timer 1 to time an interval up to 8.388 seconds. It users a prescaler of 1024, which means each "count" of timer 1 is 1/16e6 * 1024 of a second (0.000064 seconds, or 64 µs). Since it can count up to 65536 we can time 0.000064 * 65536 = 4.194304 seconds. Then the timer overflows, but we can test the "overflow flag" and know the overflow occurred. That lets us time up to 8.388608 seconds before we miss the fact that there was a second overflow.

This code works even if interrupts are off, because the timing is done by the hardware timer.

Output on my Uno:

Starting ... Time taken = 7.56 seconds. 
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

You can time reasonably long intervals using Timer 2 (on the Atmega328) as described in my page about timers.

The example there is this:

void startTimer1 () { // reset Timer 1 TCCR1A = 0; TCCR1B = 0; // zero it TCNT1 = 0; TIFR1 |= bit (TOV1); // clear overflow flag // start Timer 1 TCCR1B = bit (CS10) | bit (CS12); // prescaler of 1024 } // end of startTimer1 unsigned long getTimer1Reading () { unsigned long elapsed = TCNT1; if (TIFR1 & bit (TOV1)) elapsed += 65536; return elapsed; } // end of getTimer1Reading void setup () { Serial.begin (115200); Serial.println (); } // end of setup void loop () { Serial.println ("Starting ..."); Serial.flush (); startTimer1 (); delay (7560); float secs = (1.0 / F_CPU * 1024) * getTimer1Reading (); Serial.print ("Time taken = "); Serial.print (secs); Serial.println (" seconds."); } // end of loop 

The code below uses Timer 1 to time an interval up to 8.388 seconds. It users a prescaler of 1024, which means each "count" of timer 1 is 1/16e6 * 1024 of a second (0.000064 seconds, or 64 µs). Since it can count up to 65536 we can time 0.000064 * 65536 = 4.194304 seconds. Then the timer overflows, but we can test the "overflow flag" and know the overflow occurred. That lets us time up to 8.388608 seconds before we miss the fact that there was a second overflow.

This code works even if interrupts are off, because the timing is done by the hardware timer.