Go Down

### Topic: Frequency counting with internal timers (Read 1 time)previous topic - next topic

#### nickgammon

##### Jan 17, 2012, 03:23 am
Someone mentioned recently about a frequency counting technique using the internal timers on the Atmega328. Try as I might, I couldn't find the post relating to that, although this might have been it:

http://interface.khm.de/index.php/lab/experiments/frequency-measurement-library/

or

http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/

However, I wanted to understand exactly how it all worked, hence, my own attempts at a frequency counter:

http://www.gammon.com.au/forum/?id=11504

This uses Timer 1 to count pulses, and Timer 2 to find exactly 1 mS intervals. So for example, you could count the number of pulses over 1000 mS (one second) to find the frequency in Hz.

The accuracy is pretty good, I am measuring 0.02% error with an input of 5 MHz.
Please post technical questions on the forum, not by personal message. Thanks!

#### bubulindo

#1
##### Jan 17, 2012, 03:29 am
For those frequencies, wouldn't input capture be a good option using only 1 timer?
This... is a hobby.

#### nickgammon

#2
##### Jan 17, 2012, 04:00 am
You mean, with micros() or millis() ? That would certainly be an option too.

It was partly an educational exercise, to demonstrate measuring exact intervals as well as counting stuff.

I think though you would sacrifice some accuracy using the normal micros() or millis() timers. Since you don't have access to the interrupts they generate (which in any case are not exactly at 1 mS intervals) you would have to loop waiting for time to be up, and the overhead of noticing that the time was up, and then stopping the clock and getting a reading, would, I think, introduce an inaccuracy.

Test here:

Code: [Select]
`// these are checked for in the main programvolatile unsigned long timerCounts;// internal to counting routineunsigned long overflowCount;ISR (TIMER1_OVF_vect){  ++overflowCount;               // count number of Counter1 overflows  }  // end of TIMER1_OVF_vectvoid setup () {  Serial.begin(115200);         Serial.println("Frequency Counter");} // end of setupvoid loop () {     // reset Timer 1  TCCR1A = 0;               TCCR1B = 0;                // Timer 1 - counts events on pin D5  TIMSK1 = _BV (TOIE1);   // interrupt on Timer 1 overflow  TCNT1 = 0;      // counters to zero  overflowCount = 0;  // start Timer 1  // External clock source on T1 pin (D5). Clock on rising edge.  TCCR1B =  _BV (CS10) | _BV (CS11) | _BV (CS12);   // time for a second   unsigned long start = micros ();  while (micros () - start < 1000000UL)    { }  unsigned long finish = micros ();     // end of gate time, measurement ready  TCCR1A = 0;    // stop timer 1  TCCR1B = 0;      unsigned int timer1CounterValue;  timer1CounterValue = TCNT1;  // see datasheet, page 117 (accessing 16-bit registers)  TIMSK1 = 0;    // disable Timer1 Interrupt    timerCounts = (overflowCount << 16) + timer1CounterValue;  // each overflow is 65536 more    // adjust counts by counting interval to give frequency in Hz  float frq = (timerCounts *  1000000.0) / (finish - start);  Serial.print ("Frequency: ");  Serial.println ((unsigned long) frq);    // let serial stuff finish  delay(200);}   // end of loop`

That only used one timer, and seemed to work OK, but with perhaps slightly less accuracy (0.2% error).
Please post technical questions on the forum, not by personal message. Thanks!

#3
##### Jan 17, 2012, 08:25 am

Have you seen Paul Stoffregen's library...
http://www.pjrc.com/teensy/td_libs_FreqMeasure.html

#### nickgammon

#4
##### Jan 17, 2012, 08:35 am
Looks like my Google-Fu wasn't as good as it could have been. Thanks for the link.

But still, learning how to do it myself is always useful, because then I can adapt the concepts to other things.
Please post technical questions on the forum, not by personal message. Thanks!

#5
##### Jan 17, 2012, 08:43 am
Looks like my Google-Fu wasn't as good as it could have been.

I doubt that was a problem.  Several months ago I spent about 30 minutes each day for a week collecting information about frequency counting on Arduinos and never found that library.  I stumbled across it by accident looking for some Teensy information.

Quote