Frequency Counter Library

I also am trying to use the library on a Blend Micro (Leonardo + Bluetooth LE chip), and no luck. I double-checked the pin assignments to connect the signal to Counter1, but it never counts any pulses. It works great on a Pro Trinket.

Hi,

please, someone can use the Frequecy Counter Library with Arduino Leonardo (ATmega32u4)?? I read some threads but nobody have been able to use it :cry:

I need to measure the frequency that comes from an external circuit.

Thanks!

I think you should start a new thread specific to your application. What frequency range? What is the signal like, is it low voltage AC, a DC squarewave, 0-12V?

I need to measure a signal with a frequency in the order of 500KHz-600KHz. The amplitude is about 1V, but about this point I can add a level shifter.

Currently, I am using a code below for the Yun (by Nick Gammon) but I cannot measure signal with frequency above 250KHz. How can I extend the range?

// Frequency timer using input capture unit
// Author: Nick Gammon
// Date: 31 August 2013

// Input: Pin D4 on YUN Bill Gilbert 20141015_13:44 Works

#include "Bridge.h"
#include "Console.h"

volatile boolean first;
volatile boolean triggered;
volatile unsigned long overflowCount;
volatile unsigned long startTime;
volatile unsigned long finishTime;

// timer overflows (every 65536 counts)
ISR (TIMER1_OVF_vect) 
{
  overflowCount++;
}  // end of TIMER1_OVF_vect

ISR (TIMER1_CAPT_vect)
  {
  // grab counter value before it changes any more
  unsigned int timer1CounterValue;
  timer1CounterValue = ICR1;  // see datasheet, page 117 (accessing 16-bit registers)
  unsigned long overflowCopy = overflowCount;
  
  // if just missed an overflow
  if ((TIFR1 & bit (TOV1)) && timer1CounterValue < 0x7FFF)
    overflowCopy++;
  
  // wait until we noticed last one
  if (triggered)
    return;

  if (first)
    {
    startTime = (overflowCopy << 16) + timer1CounterValue;
    first = false;
    return;  
    }
    
  finishTime = (overflowCopy << 16) + timer1CounterValue;
  triggered = true;
  TIMSK1 = 0;    // no more interrupts for now
  }  // end of TIMER1_CAPT_vect
  
void prepareForInterrupts ()
  {
  noInterrupts ();  // protected code
  first = true;
  triggered = false;  // re-arm for next time
  // reset Timer 1
  TCCR1A = 0;
  TCCR1B = 0;
  
  TIFR1 = bit (ICF1) | bit (TOV1);  // clear flags so we don't get a bogus interrupt
  TCNT1 = 0;          // Counter to zero
  overflowCount = 0;  // Therefore no overflows yet
  
  // Timer 1 - counts clock pulses
  TIMSK1 = bit (TOIE1) | bit (ICIE1);   // interrupt on Timer 1 overflow and input capture
  // start Timer 1, no prescaler
  TCCR1B =  bit (CS10) | bit (ICES1);  // plus Input Capture Edge Select (rising on D8)
  interrupts ();
  }  // end of prepareForInterrupts
  

void setup () 
  {
      // initialize serial communication:
  Bridge.begin();
  Console.begin(); 

  pinMode(5,INPUT); 
 
  while (!Console){
    ; // wait for Console port to connect.
  }
  Console.println("You're connected to the Console!!!!");
   delay(1000); 
  
  Console.begin();       
  Console.println("Frequency Counter");
  // set up for interrupts
  prepareForInterrupts ();   
  } // end of setup

void loop () 
  {
  
  // wait till we have a reading
  if (!triggered)
    return;
 
  // period is elapsed time
  unsigned long elapsedTime = finishTime - startTime;
  // frequency is inverse of period, adjusted for clock period
  float freq = F_CPU / float (elapsedTime);  // each tick is 62.5 nS at 16 MHz
  
  Console.print ("Took: ");
  Console.print (elapsedTime);
  Console.print (" counts. ");

  Console.print ("Frequency: ");
  Console.print (freq);
  Console.println (" Hz. ");

  // so we can read it  
  delay (1);

  prepareForInterrupts ();   
}   // end of loop}

If you want, I start with a new thread.

Hi guys,

This is my first post and actually this is my first project with Arduino. I am trying to understand how that library works and there are some things that I do not understand inside the ISR:

ISR(TIMER2_COMPA_vect) 
{
  // multiple 2ms = gate time = 100 ms
  if (FreqCounter::f_tics >= FreqCounter::f_period) 
  {         	
      // end of gate time, measurement ready
      // GateCalibration Value, set to zero error with reference frequency counter
      //  delayMicroseconds(FreqCounter::f_comp); // 0.01=1/ 0.1=12 / 1=120 sec 
      delayMicroseconds(FreqCounter::f_comp);
      TCCR1B = TCCR1B & ~7;   		    // Gate Off  / Counter T1 stopped 
      TIMSK2 &= ~(1<<OCIE2A);    	    // disable Timer2 Interrupt
      TIMSK0 |=(1<<TOIE0);     		    // enable Timer0 again // millis and delay
      FreqCounter::f_ready=1;               // set global flag for end count period
      
      // calculate now frequeny value
      FreqCounter::f_freq=0x10000 * FreqCounter::f_mlt;  // mult #overflows by 65636
      FreqCounter::f_freq += TCNT1;      	// add counter1 value
      FreqCounter::f_mlt=0;    
    }
    FreqCounter::f_tics++;            	  // count number of interrupt events
    if (TIFR1 & 1)                        // if Timer/Counter 1 overflow flag
    {          			
      FreqCounter::f_mlt++;               // count number of Counter1 overflows
      TIFR1 =(1<<TOV1);        		  // clear Timer/Counter 1 overflow flag
    }
    // PORTB = PORTB ^ 32;  		  // int activity test
}

1.- Timer2 interrupt is disabled but it is never enabled again. Is it automatically enabled after the ISR?
2.- Counter T1 is stopped.. what makes it run again? The input signal?
3.- What does "delayMicroseconds(FreqCounter::f_comp);" do? I mean, why do we need that delay and why is f_comp set to 1? Shall I change that value depending on the application?
4.- Why is timer0 enabled every time that the frequency is measured?

Thanks so much!

dc42:
Here is an improved version of the frequency counter sketch. There were a couple of problems with the previous version:

// Frequency counter sketch, for measuring frequencies low enough to execute an interrupt for each cycle

// Connect the frequency source to the INT0 pin (digital pin 2 on an Arduino Uno)

volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile unsigned long numPulses;

void isr()
{
  unsigned long now = micros();
  if (numPulses == 1)
  {
    firstPulseTime = now;
  }
  else
  {
    lastPulseTime = now;
  }
  ++numPulses;
}

void setup()
{
  Serial.begin(19200);    // this is here so that we can print the result
  pinMode(3, OUTPUT);    // put a PWM signal on pin 3, then we can connect pin 3 to pin 2 to test the counter
  analogWrite(3, 128);
}

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
float readFrequency(unsigned int sampleTime)
{
  numPulses = 0;                      // prime the system to start a new reading
  attachInterrupt(0, isr, RISING);    // enable the interrupt
  delay(sampleTime);
  detachInterrupt(0);
  return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime);
}

void loop()
{
  float freq = readFrequency(1000);
  Serial.println(freq);
  delay(1000);
}

Sorry for dragging up an old thread but what is the value of the variable sampleTime in this sketch, is it 0 or is there a standard value for this? I'm slightly confused! I realize I could run the sketch and print the value to the serial port but I don't have access to my Arduino for a week and it's bugging me!

Hello!
Is there any method to make the frequency be a "double"?
Thanks!

double, or long/unsigned long, instead of a float?

DevilMoo:
Hello!
Is there any method to make the frequency be a "double"?
Thanks!

On an AVR [UNO/MEGA] a double equals a float (32 bit IEEE754 float),
other platforms like ARM based DUE might have 64bit double,

Hello guys,

I have a small question about the frequency counter sketch, from the example of DC42.
Here is "delay(sampleTime)" used.
I dont want to use delay.

Is it possible to make a timing with millis() or something instead of delay for this sketch?
Thanks in advance.

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
float readFrequency(unsigned int sampleTime)
{
numPulses = 0; // prime the system to start a new reading
attachInterrupt(0, isr, RISING); // enable the interrupt
delay(sampleTime);
detachInterrupt(0);
return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime);
}

Check the - blink without delay - example sketch. It shows how to write delay less

Thanks for your reply Rob,
But when i tried it with the millis timer, I get a overflow of the reading??
It is maybe something simple, but i don't see the problem.

// Frequency counter sketch, for measuring frequencies low enough to execute an interrupt for each cycle
// Connect the frequency source to the INT0 pin (digital pin 2 on an Arduino Uno)

volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile unsigned long numPulses;
unsigned long currentMilis;
unsigned long lastMilis = 0;
float Hz;


void isr()
{
  unsigned long now = micros();
  if (numPulses == 1) {
    firstPulseTime = now;
  }
  else {
    lastPulseTime = now;
  }
  ++numPulses;
}


void setup()
{
  Serial.begin(19200);    // this is here so that we can print the result
}




void loop()
{
  currentMilis = millis();
  attachInterrupt(2, isr, RISING);    // enable the interrupt
  
  if (currentMilis - lastMilis > 1000) // instead of using delay(1000)
  {
    detachInterrupt(2);
    lastMilis = currentMilis;
    numPulses = 0;                      // prime the system to start a new reading
    Hz =  (1000000.0 * (float)(numPulses - 2)) / (float)(lastPulseTime - firstPulseTime);
  }
  Serial.println(Hz);


}

I found the problem!
It was not an overflow, but divided with 0.

When my if statement was true, i first set the numPulses to 0, and then calculate my Hz.
numPulses have to be set 0 after my calculation, so it is solved now.

The complete code for a accurate frequency measurement without using delay:

// Frequency counter sketch, for measuring frequencies low enough to execute an interrupt for each cycle
// Connect the frequency source to the INT0 pin (digital pin 2 on an Arduino Uno)

volatile unsigned long firstPulseTime;
volatile unsigned long lastPulseTime;
volatile unsigned long numPulses;
unsigned long currentMilis;
unsigned long lastMilis = 0;
float Hz;



void isr()
{
  unsigned long now = micros();
  if (numPulses == 1) {
    firstPulseTime = now;
  }
  else {
    lastPulseTime = now;
  }
  ++numPulses;
}


void setup()
{
  Serial.begin(19200);    // this is here so that we can print the result
attachInterrupt(2, isr, RISING);    // enable the interrupt
}




void loop()
{
currentMilis = millis();
 attachInterrupt(2, isr, RISING);    // enable the interrupt
  
  if (currentMilis - lastMilis > 1000) // instead of using delay(1000)
  {
   detachInterrupt(2);
   lastMilis = currentMilis;
   Hz =  (1000000.0 * (float)(numPulses - 2)) / (float)(lastPulseTime - firstPulseTime);
  
     numPulses = 0;  
    attachInterrupt(2, isr, RISING);    // enable the interrupt  
}
   Serial.println(Hz);

}

Hello guys !!!

Just a small error in the previous code writted by HBO88...
You mixed up the number of the interruption and the number of PIN !!!!
Be carefull

Correction:
Please replace attachInterrupt(2, isr, RISING); by attachInterrupt(0, isr, RISING);

Otherwise congratulation for the rest!

Chris,

hi , i want ask some question. how about i want measure frequency from function generator by using arduino uno. can i connect direct from function generator to analog pin . thank you

full_throttle, you should start your own thread. You'll get a lot more answers that way.

And place this question in something like Project Guidance, or General Electronics.

@HBO88

I tried your modified version, but it's not working as expected on an UNO.
A have an incoherent value and often "inf" or "ovf"

Any help ?

hi i wish to use freqcounter lib with pwm output, is it possible to use pwm when waiting to interrupt on timer2?

Anyone tried getting the FreqCount running a Zero? I'm looking to measure a input signal that varies from around 100kHz to 80kHz. Been trying to figure all the internal routing of the Zero to make this happen withou any success yet.

Can you please explain me why preamplifier scheme has such view and why there is such transistor and what this scheme do with signal (I've make it in Workbench and the signal from generator just shifts under zero level)