 # Measuring a frequency using ATmega timer & counter

Hello,
I am currently trying to build an LC meter that I want to use to measure the capacity of capacitors or inductance of coils / HF throttles.
For this, my basic idea is to have a resonating circuit with a capacitor and a HF throttle:

Currently, I am using 720 pF and 311 uH which should result in a frequency of ~ 332 kHz.
When measuring with an oscilloscope, the frequency is 337.8 kHz (I don’t know how to export from the oscilloscope) and looks like that:

So everything should be fine. I connected the output of the comparator (LM311) to pin 5 (T1) of an ATmega 168 running at 16 MHz.

Now for the programming part.
My first idea was to use the pulseIn() functionality.
However, because I have an input of 338 kHz which is 2.96 us but pulseIn() only gives full us (return value type long) so it is way too unprecise to use.

So I am currently attempting to measure the frequency by counting the “ticks” in a known gate time.
For this, I set the atmega’s timer 1 to trigger on rising edge, and timer 2 to tick every 4.096 ms:

``````#define LED 8

// Interrupt interval in us
// iinterval = prescale * (ocr2aval + 1) / (F_CPU / 1.0e6);

void setup() {
Serial.begin(9600);
pinMode(LED, OUTPUT);

cli();

// Timer 1 counter mode
TCCR1A = 0;
TCCR1B = (1 << ICES1) | (1 << CS12) | (1 << CS11) | (1 << CS10);
TCCR1C = 0;

// Set Timer 2 CTC mode
// WGM22:0 = 010: CTC Mode
// WGM2 bits 1 and 0 are in TCCR2A,
// WGM2 bit 2 is in TCCR2B
//
TCCR2A = (1 << WGM21);

// Set Timer 2  prescale 1024
//
// CS22:0 = 101: prescale = 1024
// CS2 bits 2:0 are all in TCCR2B
TCCR2B = (1 << CS22) | (0 << CS21) | (1 << CS20);

// Enable Compare-match register A interrupt for timer2
TIMSK2 = (1 << OCIE2A);

// This value determines the interrupt interval
OCR2A = 64-1;

// Enable global interrupts: Ready to run!
sei();

}

volatile uint16_t count = 0;

void loop() {
delay(1000);

Serial.println(count);
// freq [kHz] = ticks [Hz]/1.024 ms
}

// ISR For Timer 2 Compare-match interrupt
ISR(TIMER2_COMPA_vect) {

count = TCNT1;
TCNT1 = 0;

}
``````

But whatever which prescaler I use, I get wrong values for the frequency. Here are my results:

prescaler gate frequency ~ time is ticks is frequency
210 CS with OCR 64-1 I am expecting 337.71 kHz
001 => clock/1 => 250 kHz ~ 0.004 ms got 1 tick
010 => clock/8 => 31.25 kHz ~ 0.032 ms got 10 ticks → 343.75 kHz
011 => clock/64 => 3.91 kHz ~ 0.256 ms got 43 ticks → 167.97 kHz
100 => clock/256 => 977 Hz ~ 1.024 ms got 86 ticks → 83.98 kHz
101 => clock/1024 => 244 Hz ~ 4.096 ms got 155 ticks → 37.84 kHz

The is frequency I calculated using
freq [kHz] = ticks / gate time [ms]

For another test, I connected an LED to pin 8 and switched it every time the ISR is called to test whether I calculated the gate time correctly. This turned out to be true, so the counting part has to have a mistake.

What am I doing wrong here? Can someone give me help on how to use the counter correctly?
Thanks for reading so far & any help in advance.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.