Arduino Forum

Topics => Science and Measurement => Topic started by: marnaw on Jun 17, 2011, 09:05 am

Title: Frequency Counter Library
Post by: marnaw on Jun 17, 2011, 09:05 am
i like to continue the thread from the old forum here

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1224777046 (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1224777046)

martin
Title: Re: Frequency Counter Library
Post by: robtillaart on Jun 17, 2011, 09:42 am
for the newbies, can you give a short description &  current state ?
TIA,
Rob
Title: Re: Frequency Counter Library
Post by: dougm on Feb 29, 2012, 12:06 am
I modified the cpp file to work with the mega2560.  It was pretty easy.  Uses pin 47 same as the 1280.  It works but sadly it does not play nice with the servo module (presumably they both use the same timer).

Code: [Select]

/*
 FreqCounter.h -
 Using Counter1 for counting Frequency on T1 / PD5 / digitalPin 5
 Uses Counter5 on the Mega digitalPin 47

 Using Timer2 for Gatetime generation

 Martin Nawrath KHM LAB3
 Kunsthochschule für Medien Köln
 Academy of Media Arts
 http://www.khm.de
 http://interface.khm.de/index.php/labor/experimente/

 History:
   Dec/08 - V0.0
   May/20  modified by mem to support Mega usting T5 /PL2 on digitalPin 47


 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/



#include <FreqCounter.h>


unsigned long FreqCounter::f_freq;

volatile unsigned char FreqCounter::f_ready;
volatile unsigned char FreqCounter::f_mlt;
volatile unsigned int FreqCounter::f_tics;
volatile unsigned int FreqCounter::f_period;
volatile unsigned int FreqCounter::f_comp;

// 16 bit timer defines added by mem to enable redifining the timer used
#if defined(__AVR_ATmega2560__)
#define TCCRnA TCCR5A
#define TCCRnB TCCR5B
#define TCNTn  TCNT5
#define TIFRn  TIFR5
#define TOVn   TOV5
#elif defined(__AVR_ATmega1280__)
#define TCCRnA TCCR5A
#define TCCRnB TCCR5B
#define TCNTn  TCNT5
#define TIFRn  TIFR5
#define TOVn   TOV5
#elif defined (__AVR_ATmega168__)
#define TCCRnA TCCR1A
#define TCCRnB TCCR1B
#define TCNTn  TCNT1
#define TIFRn  TIFR1
#define TOVn   TOV1
#endif
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void FreqCounter::start(int ms) {

 f_period=ms/2;
 if (f_comp ==0) f_comp=1;

// hardware counter setup ( refer atmega168.pdf chapter 16-bit counter1)
 TCCRnA=0;     // reset timer/countern control register A
 TCCRnB=0;  // reset timer/countern control register A
 TCNTn=0;     // counter value = 0
 // set timer/counter1 hardware as counter , counts events on pin Tn ( arduino pin 5 on 168,47 on Mega )
 // normal mode, wgm10 .. wgm13 = 0
 sbi (TCCRnB ,CS10); // External clock source on Tn pin. Clock on rising edge.
 sbi (TCCRnB ,CS11);
 sbi (TCCRnB ,CS12);


 // timer2 setup / is used for frequency measurement gatetime generation
 // timer 2 presaler set to 256 / timer 2 clock = 16Mhz / 256 = 62500 Hz
 TCCR2A=0;
 TCCR2B=0;
 cbi (TCCR2B ,CS20);
 sbi (TCCR2B ,CS21);
 sbi (TCCR2B ,CS22);

 //set timer2 to CTC Mode
 cbi (TCCR2A ,WGM20);
 sbi (TCCR2A ,WGM21);
 cbi (TCCR2B ,WGM22);
 OCR2A = 124;


 f_ready=0;    // reset period measure flag
 f_tics=0;     // reset interrupt counter
 sbi (GTCCR,PSRASY); // reset presacler counting
 TCNT2=0; // timer2=0
 TCNTn=0; // Countern = 0

 cbi (TIMSK0,TOIE0); // disable Timer0  //disable  millis and delay
 sbi (TIMSK2,OCIE2A); // enable Timer2 Interrupt

 TCCRnB = TCCRnB | 7; //  Counter Clock source = pin Tn , start counting now

}



//******************************************************************
//  Timer2 Interrupt Service is invoked by hardware Timer2 every 2ms = 500 Hz
//  16Mhz / 256 / 125 = 500 Hz
//  here the gatetime generation for freq. measurement takes place:

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
   TCCRnB = TCCRnB & ~7;   // Gate Off  / Counter Tn stopped
   cbi (TIMSK2,OCIE2A);    // disable Timer2 Interrupt
   sbi (TIMSK0,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 += TCNTn; // add countern value
   FreqCounter::f_mlt=0;

 }
 FreqCounter::f_tics++; // count number of interrupt events
 if (TIFRn & 1) {    // if Timer/Counter n overflow flag
   FreqCounter::f_mlt++;   // count number of Countern overflows
   sbi(TIFRn,TOVn);  // clear Timer/Counter n overflow flag
 }
 // PORTB = PORTB ^ 32;  // int activity test
}


Title: Re: Frequency Counter Library
Post by: smeezekitty on Feb 29, 2012, 03:44 am
replace the < and > with [ and ] to make the code tags work.
Title: Re: Frequency Counter Library
Post by: dougm on Feb 29, 2012, 05:23 am
Thanks for the tip - I went back and edited.  I find it ironic that there are 35 buttons to put different smileys in the message but not one button to put code in the message.

DougM
Title: Re: Frequency Counter Library
Post by: smeezekitty on Feb 29, 2012, 07:04 am

Thanks for the tip - I went back and edited.  I find it ironic that there are 35 buttons to put different smileys in the message but not one button to put code in the message.

DougM


Actually there is one (it looks like a '#') but once you get the hang of it, it is easier just to type code tags.
I might check out the code alittle later if I have time, it looks interesting.
Title: Re: Frequency Counter Library
Post by: kurtommy on Mar 23, 2012, 12:18 am
There is a workoround for use with servo library?
Title: Re: Frequency Counter Library
Post by: keithspg on Jul 31, 2012, 03:55 pm
A bit confused. I grabbed the 'latest' version which appears to be V1.2. Will it work with a 2560, or do I need to use the cpp that Doug contributed above?
Title: Re: Frequency Counter Library
Post by: Far-seeker on Jul 31, 2012, 04:52 pm

There is a workoround for use with servo library?


I'm by far not the most accomplished low-level embedded programmer on these forums, but here's my take.  It's unlikely for the UNO, as the Frequency Counter Library relies heavily on Timer1 and Timer2.  For the Mega boards, it could be possible to use the Servo Library with pins in the banks associated with Timer3 and Timer4 (i.e. the timers not used by the Frequency Counter Library).  Even so, it may still require some changes to one or both libraries.  However, I don't have a Mega board available to experiment with at this time.
Title: Re: Frequency Counter Library
Post by: michael_kaeppler on Aug 25, 2012, 10:47 pm
Hi all,
I'd like to ask the question why it is necessary to disable Timer0 before starting the counting process?

- Michael
Title: Re: Frequency Counter Library
Post by: pito on Aug 26, 2012, 07:01 pm
..for advanced users :)
http://arduino.cc/forum/index.php/topic,120220.0.html
Title: Re: Frequency Counter Library
Post by: brainbooster on Oct 19, 2012, 10:01 am
hi,
do you think it's possible to modify the lib in order to be able to read also the duty cycle?
we could use two interrupts , one for the rising edge and one for the fallig so at the end of the measure we could count both events and then do the proper calculations?
Title: Re: Frequency Counter Library
Post by: retrolefty on Oct 19, 2012, 04:22 pm

Hi all,
I'd like to ask the question why it is necessary to disable Timer0 before starting the counting process?

- Michael


Most likely because the free running timer0 interrupts used by the arduino start-up code to support the delay() and millis() and micros() function would add a element of variable latency to responding to the timer interrupt used by the frequency counter function.
Title: Re: Frequency Counter Library
Post by: AaronTroeger on Oct 23, 2012, 02:04 am
Hi, I'm trying to use Arduino Uno with 2 flow sensors.
They pulse at 3300 per litre. I have them hooked up to pins 4 and 5 on my arduino.
My question is can I use FreqCounter to read each one separately and over a 1 second period?
I have looked through the code and I can't see anywhere to allocate the pins I want it to read..
Title: Re: Frequency Counter Library
Post by: AaronTroeger on Oct 23, 2012, 02:31 am
Quote
Hi, I'm trying to use Arduino Uno with 2 flow sensors.
They pulse at 3300 per litre. I have them hooked up to pins 4 and 5 on my arduino.
My question is can I use FreqCounter to read each one separately and over a 1 second period?
I have looked through the code and I can't see anywhere to allocate the pins I want it to read..


I've had a quite look through the C++ coding. If I change every occurance of T1 with the relevant T number for pin4 or 6?
If anyone knows where i can find those T numbers that would be awesome :)
Title: Re: Frequency Counter Library
Post by: idkwat2namme on Nov 15, 2012, 05:36 am
I am new to the site, but I have been programming micros and Arduino for a little time now. I like the code and it works great. I am using it with a variable reluctance sensor and some support circuitry. I wanted to use you code and take the frequency value and output an analog signal in a ratio of the frequency. For example I take the frq from the example and ledBrightness=map(frq,0,fastestFrequency,0,255) but i cannot seem to get a signal out with the analogWrite() command. Does this library mess with the timer that controls the PWM timing of the analogWrite() command?
Title: Re: Frequency Counter Library
Post by: matinzk on Dec 01, 2012, 06:17 pm
Been using the Frequency Measurement Library, it's great. Been using it to measure the speed and RPM on my car. Is there a way of measuring 0 frequency to show 0 speed or 0 RPM at all?

Thanks.
Title: Re: Frequency Counter Library
Post by: idkwat2namme on Dec 01, 2012, 10:44 pm

Been using the Frequency Measurement Library, it's great. Been using it to measure the speed and RPM on my car. Is there a way of measuring 0 frequency to show 0 speed or 0 RPM at all?

Thanks.


Just as a heads up, if you are getting your signal from a hall effect sensor you should be able to read zero speed, but from what I have been looking up, most speed sensors are a much cheaper variable reluctance sensor. As I understand it, variable reluctance (VR) sensors do not do well at slow speeds. This code and my VR sensor off of a Borg-Warner T5, for a S-10, cannot go down to 0 rpm. I can only get to 10s or rpm. Hall effect sensor can take true zero speed measurements. Good luck.
Title: Re: Frequency Counter Library
Post by: matinzk on Dec 01, 2012, 11:01 pm
I am using this:
http://interface.khm.de/index.php/lab/experiments/frequency-measurement-library/

Are we talking about the same library? Is the above library in the link able to detect zero RPM and speed?

This is the hall effect sensor we use:  http://www.digital-speedos.co.uk/hall-effect-speed-sensor-for-drift-gauges-non-magnetic-382-p.asp
Title: Re: Frequency Counter Library
Post by: smeezekitty on Dec 02, 2012, 07:35 am
Have you considered using a light based counter? Shine an IR light at whatever is spinning and fix piece of something shiny to it. Then point an IR detector at it which should detect rotation.
Title: Re: Frequency Counter Library
Post by: matinzk on Dec 02, 2012, 11:21 am
How can I do this with a car? Especially the engine rpm?
Title: Re: Frequency Counter Library
Post by: smeezekitty on Dec 07, 2012, 05:45 am

How can I do this with a car? Especially the engine rpm?

Maybe you can fix something shiny or use shiny paint on one of the main belts?
Title: Re: Frequency Counter Library
Post by: Constantin on Dec 10, 2012, 12:09 am
Please do not paint belts. The paint may damage the belt (thanks to the enclosed / entrained solvents) and lead to premature cracking. Not only are modern belts very expensive to replace, losing one will usually leave you stranded. Not the best way to impress the missus.

Instead use a hall-effect or optical rig on a sprocket or similar device that does not need physical modification.
Title: Re: Frequency Counter Library
Post by: smeezekitty on Dec 12, 2012, 02:11 am

The paint may damage the belt (thanks to the enclosed / entrained solvents) and lead to premature cracking.

Honestly this is not my place to expertise but it would seem there is certain types of paints that would not be a problem.
Quote

Not only are modern belts very expensive to replace, losing one will usually leave you stranded. Not the best way to impress the missus.

Last time I looked, the belts were not all that expensive. But losing one can indeed leave you stranded but alas this is a risk with any type of engine modification.
Title: Re: Frequency Counter Library
Post by: Constantin on Dec 12, 2012, 04:09 am
SmeezeKitty, do as you wish.

All I can tell you is that I had to replace every rubber hose on a diesel engine because some lugnut sprayed them with the same 'Perkins blue' as the rest of the engine. And to do that, we got to lift the engine out of the boat, drain it of all fluids, etc. Not the fastest fix.

Every hose had cracked thanks to this painting treatment. Given how important belts are, I wouldn't mess with them and pick up the desired signal elsewhere.
Title: Re: Frequency Counter Library
Post by: boriskourt on Feb 04, 2013, 12:19 am
I got this to work well on one sensor, using my Arduino UNO.

But I have not been able to get it to work at all on a Leonardo. [ Serial doesn't even print the 'Frequency Library' line at the start] Have there been major changes to serial for Leonardo?

Another question is, how would I be able to expand this to multiple sensors without using multiple Arduinos?
Title: Re: Frequency Counter Library
Post by: iw4blg on Aug 27, 2013, 10:01 pm
Hello to everybody, first of all I'm not an expert altought I have succeed so far with some small Arduino based project.
I'm now trying to develop a radioastronomic receiver (radiometer) controlled by Arduino.
Now the topic:

- I have an Arduino Uno rev.2 with an Ethernet shield with microSD slot (both not yet used, but useful later on)
- In order to control the receiver I have to program 2 different PWM on 2 different pins
- for what I read on the web pages, I can use the instruction analog.write(pin,pwm) on the pins 3,5,6,9,10,11 if not already used by other devices
- the pin 5 (T1) is used to read the OL frequency of the receiver by means of the library FreqCounter.h herewith discussed..
- pin 3 seems to be used by the Eth shield as well as the pins 0,1,2,4,10,14,15
- thus, "fre to be used" for my purpose, remain the pins 6,9,11

Unfortunately only the output on the pin 6 works. Pins 9 and 11 always are at low level, no PWM, even with no shield on top of the Arduino Uno.
The board works fine is I do not call the frequency reading routine.
What I'm doing wrong? Waht shall I do to fix the trouble?
On the following a draft of the cose I'm using. Please note it's a very early draft of what I would do, so several variables are defined but not used yet.

Many thanks to all for the help!
Pierluigi
Quote

#include <FreqCounter.h>

// OL input on digital pin #5

const short pwm1=9; // pin 9 is 8 MSB PWM
const short pwm2=6; // pin 6 is 8 LSB PWM

long int frq; //frequency read
long int IF=10700000; // first IF of the Rx
const short prescaler=8; // scale factor of the ext. prescaler
const long int fastro1=25610000; // astro1 = 1st frequency
const long int fastro2=13385000; // astro2 = 2nd frequency
long int OLnow; // current OL frequency
long int RXnow; // current RX frequency
long int errore=0; // frequency error

int pwmh; // 8 MSB of PWM
int pwml; // 8 LSB of PWM

float Vastro1=0.2035; // VCO nominal input for fastro1
// float Vastro2=3; // VCO nominale per rx frequenza fastro2

int bitbase1=Vastro1*65535/5; // total PWM bits (res.16) of feed forward VCO a freq. astro1
// int bitbase2=Vastro2*65535/5; // bit di PWM totali (risoluzione 16) del feed forward tensione VCO a freq. astro1

void setup() {
  Serial.begin(9600);                    // connect to the serial port
  Serial.println("Frequency Counter");
}

void loop() {

  FreqCounter::f_comp= 5;             // Set compensation
  FreqCounter::start(1000);           // Start counting with gatetime of 100ms
  while (FreqCounter::f_ready == 0)   // wait until counter ready

    frq=FreqCounter::f_freq;          // read result
  OLnow= frq*prescaler;  // OL frequency calculation
  RXnow= OLnow-IF;  // RX frequency from IF and OL
  errore= RXnow-fastro1; // tuning freq. errorcalcolo errore di sintonia

  pwmh= bitbase1/256;
  pwml= bitbase1-256*pwmh;

analogWrite(pwm1, pwmh);
analogWrite(pwm2, pwml);

  Serial.print("bitbase1= ");
  Serial.print(bitbase1);
  Serial.print("  pwmh= ");
  Serial.print(pwmh);
  Serial.print("  pwml ");
  Serial.print(pwml);
  Serial.print("  frq= ");
  Serial.print(frq);
  Serial.print("  OLnow= ");
  Serial.print(OLnow);
  Serial.print("  RXnow= ");
  Serial.print(RXnow);
  Serial.print("  Errore= ");
  Serial.println(errore);
  delay(20);
}










Title: Re: Frequency Counter Library
Post by: dc42 on Sep 18, 2013, 03:27 pm
How about a variation on the frequency counter lib that takes its input from the analog comparator? This would avoid the need for a preamplifier. You wouldn't be able to count the input directly in counter 2 because AFAIK it can't be clocked from the analog comparator output. However, you could use the analog comparator interrupt to count pulses, and use timer 1 as before to define the gate time.
Title: Re: Frequency Counter Library
Post by: Stoni on Oct 17, 2013, 12:32 pm
Hey,
first of all, thanks for the great library!

I have a small issue with my LEDs and this library. They are working if I give them the value "HIGH" or "255". But however they are not working with a lower value. I have tested the leds in an other sketch. So they are correctly wired and working fine, also the arduino. It seems to be a problem with the "FreqCounter::start(100);", if I remove it, the lower values are working, but of course the frequency counter not...

has someone an idea? thanks in advance!
Title: Re: Frequency Counter Library
Post by: dc42 on Oct 17, 2013, 01:28 pm
Assuming you mean the frequency counter library at http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/ (http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/), it uses timers 1 and 2, and disables timer 0 during the gate time. This means that none of the PWM pins on a Uno will work while you are measuring a frequency.

If the frequency you want to measure is less than about 10kHz, there are other ways of measuring it that take over only one timer, or even no timers at all.
Title: Re: Frequency Counter Library
Post by: Stoni on Oct 17, 2013, 03:03 pm
Sorry, I forgot to mention it ... you are right, I am using this library:  http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/ (http://interface.khm.de/index.php/lab/experiments/arduino-frequency-counter-library/). And I am using a Arduino Duemilanove.

The frequency I'd like to measure are under 10kHz. Do you have an example code in which one or more timers are disabled? I tried to look for an other library, but all of them are using the 3 timers ... so I would be really glad if you can help me out!
thanks in advance.
Title: Re: Frequency Counter Library
Post by: dc42 on Oct 17, 2013, 03:20 pm
1. What will be the approximate frequency, and how accurately do you need to measure it?

2. Will the input be a 5V square wave, or would you like to use the built-in analog comparator to allow much smaller input signals?
Title: Re: Frequency Counter Library
Post by: Stoni on Oct 17, 2013, 03:27 pm
The frequency will be between 85 and 255Hz.
I am using a pulse Generator which gives sqare waves with a maximum of 5V.
Title: Re: Frequency Counter Library
Post by: robtillaart on Oct 17, 2013, 07:30 pm
Code: [Select]
The frequency will be between 85 and 255Hz.
I am using a pulse Generator which gives sqare waves with a maximum of 5V.

then using an interrupt might be the easiest way - check attachInterrupt example
Title: Re: Frequency Counter Library
Post by: dc42 on Oct 18, 2013, 12:03 am
Try this:

Code: [Select]

// 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 == 0)
  {
    firstPulseTime = now;
  }
  else
  {
    lastPulseTime = now;
  }
  ++numPulses;
}

void setup()
{
  Serial.begin(19200);
}

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
unsigned int 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 < 2) ? 0 : (1000000UL * (numPulses - 1))/(lastPulseTime - firstPulseTime);
}

void loop()
{
  unsigned int freq = readFrequency(1000);
  Serial.println(freq);
  delay(1000);
}
Title: Re: Frequency Counter Library
Post by: dc42 on Oct 18, 2013, 10:50 am
Here is an improved version of the frequency counter sketch. There were a couple of problems with the previous version:

- when you attach the interrupt, you can get an immediate interrupt if this input is already high. This resulted in some jitter in the frequency reading. So I now ignore the first interrupt.

- if the pulse count (i.e. frequency multiplied by the sample time in seconds) was greater than about 4000 then the calculation would overflow. So I have changed it to use floating point calculation instead. This also give a more precise result when the number of cycles counted is low.

Code: [Select]

// 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);
}
Title: Re: Frequency Counter Library
Post by: robtillaart on Oct 18, 2013, 10:56 am
Very good sample DC42,
another argument to use float division is that integer division truncates.

(you just beat me :)
Title: Re: Frequency Counter Library
Post by: Stoni on Oct 18, 2013, 11:00 am
Oh great! Thanks alot!!
This Frequency counter works really really good for me! Now I can move on  :) ...
Title: Re: Frequency Counter Library
Post by: dc42 on Oct 18, 2013, 11:36 am
One thing I found while testing this is that the PWM frequency on pin 3 is not 488.28Hz as documented at http://playground.arduino.cc/Main/TimerPWMCheatsheet (http://playground.arduino.cc/Main/TimerPWMCheatsheet), it is in fact 490.20Hz. This makes sense, since timers 1 and 2 on the Uno are configured in phase-correct PWM mode, in which the timer counts from 0 to 255 and then back again, giving 510 steps not 512. The PWM frequency on pin 5 (controlled by timer 0 in fast PWM mode) is 976.57Hz as documented.
Title: Re: Frequency Counter Library
Post by: venu5056 on Oct 27, 2013, 10:27 am
i have a small question for u..that is it possible to measure the freq of the sine wave using arduino...
Title: Re: Frequency Counter Library
Post by: dc42 on Oct 27, 2013, 12:19 pm
To measure the frequency of a sine wave, you can either convert it to something resembling a square wave using additional hardware, or you can use the built-in analog comparator. I have found that the analog comparator is extremely sensitive and you need good wiring layout to avoid getting spurious counts due to noise.
Title: Re: Frequency Counter Library
Post by: dariq88 on Dec 17, 2013, 09:39 pm
hello!
I tried to modify the library freqcounter for arduino leonardo, but does not start, can you give me a hand to find errors?
Thank

Ps sorry for my English

Code: [Select]

#include <FreqCounter.h>

unsigned long FreqCounter::f_freq;

volatile unsigned char FreqCounter::f_ready;
volatile unsigned char FreqCounter::f_mlt;
volatile unsigned int FreqCounter::f_tics;
volatile unsigned int FreqCounter::f_period;
volatile unsigned int FreqCounter::f_comp;

void FreqCounter::start(int ms) {

#if defined (__AVR_ATmega32U4__)//(__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || (__AVR_ATmega1280__)


   TIMSK0 &=~(1<<TOIE0);       // disable Timer0  //disable  millis and delay
   delayMicroseconds(50);      // wait if any ints are pending
   
   f_period=ms;
 
 
   if (f_comp ==0) f_comp=1;  // 0 is not allowed in del us

   // hardware counter setup ( refer atmega32u4)
   TCCR1A=0;                  // reset timer/counter1 control register A
   TCCR1B=0;                 // reset timer/counter1 control register A
   TCNT1=0;             // counter value = 0
TCNT3=0;
   // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino pin 12)
   // normal mode, wgm10 .. wgm13 = 0
   
   TCCR1B |=  (1<<CS10) ;//CLOCK ESTERNO su fronte di salita
   TCCR1B |=  (1<<CS11) ;
   TCCR1B |=  (1<<CS12) ;
   
   // timer3 setup / usato per la generazione del tempo di lettura
   TCCR3A=0;
   TCCR3B=0;
   
   // timer3 presaler set to 64 / timer3 clock = 16Mhz / 64 = 250.000 Hz
   TCCR3B &= ~(1<<CS30) ;
   TCCR3B |=  (1<<CS31) ;
   TCCR3B |=  (1<<CS32) ;

   //setta il timer3 to CTC(Clear Timer on Compare)  Mode with OCR3A is top counter value (arrivato a OCR3A si resetta)
   TCCR3A &= ~(1<<WGM30) ;
   TCCR3A &= ~(1<<WGM31) ;
   TCCR3A |=  (1<<WGM32) ;
TCCR3A &= ~(1<<WGM33) ;
   OCR3A = 249;                // CTC divider by 250
 
   f_ready=0;                  // reset period measure flag
   f_tics=0;                   // reset interrupt counter
   GTCCR = (1<<PSRASY);        // reset presacler counting (perchè resettarlo?)
   TCNT3=0;                    // timer3=0
   TCNT1=0;                    // Counter1 = 0
   
   TIMSK3 |=(1<<OCIE3A);       // enable Timer3 Interrupt (interrupt di Timer/Counter3 Compare Match A)
   
                               // External clock source on T1 pin. Clock on rising edge.
   TCCR1B |= (1<<CS12) | (1<<CS11) | (1<<CS10);        //   start counting now    
   #endif
}
//******************************************************************
//  Timer3 Interrupt Service is invoked by hardware Timer3 every 1ms = 1000 Hz
//  16Mhz/64/250 = 1000 Hz
//  here the gatetime generation for freq. measurement takes place:
//

ISR(TIMER3_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
   TIMSK3 &= ~(1<<OCIE3A);     // disable Timer3 Interrupt(timer del gate)
   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
}
Title: Re: Frequency Counter Library
Post by: dariq88 on Jan 03, 2014, 05:32 pm
Now the library also works for leonardo
Code: [Select]
#include "FreqCounter.h"

volatile unsigned long FreqCounter::f_freq;

volatile unsigned char FreqCounter::f_ready;
volatile unsigned char FreqCounter::f_mlt;
volatile unsigned int FreqCounter::f_tics;
volatile unsigned int FreqCounter::f_period;
volatile unsigned int FreqCounter::f_comp;

void FreqCounter::start(int ms) {

#if defined (__AVR_ATmega32U4__)

    f_period=ms/2;
    f_ready=0;                  // reset period measure flag
    f_tics=0;                   // reset interrupt counter
 
 
    if (f_comp ==0) f_comp=1;  // 0 is not allowed in del us

    // hardware counter setup ( refer atmega32u4)
    TCCR1A=0;                  // reset timer/counter1 control register A
    TCCR1B=0;                 // reset timer/counter1 control register A
    TCNT1=0;               // counter value = 0

    // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino leonardo pin 12)
    // normal mode, wgm10 .. wgm13 = 0
   
    TCCR1B |=  (1<<CS10) ;//CLOCK ESTERNO su fronte di salita
    TCCR1B |=  (1<<CS11) ;
    TCCR1B |=  (1<<CS12) ;
   
    // timer0 setup / usato per la generazione del tempo di lettura
    TCCR0A=0;
    TCCR0B=0;
   
    // timer3 presaler set to 256 / timer3 clock = 16Mhz / 256 = 62.500 Hz
    TCCR0B = (1<<CS02);

    //setta il timer0 to CTC(Clear Timer on Compare)  Mode with OCR3A is top counter value (arrivato a OCR3A si resetta)
    TCCR0A = (1<<WGM01);  // CTC mode, normal (no Output compare)
    GTCCR |= (1<<PSRASY);  // reset prescaler (undocumented bit in mega32u4?)
    TCCR0B = (1<<CS02);  // timer0 on clk/256 == 16MHZ / 256 = 62500hz..
    OCR0A = 124;  // 125 counts of 62500 Hz before an output compare interrupt...

    TCNT1 = 0;
    TCNT0 = 0;

    TIMSK0 = (1<<OCIE0A);
    #endif

}
//******************************************************************
//  Timer3 Interrupt Service is invoked by hardware Timer3 every 1ms = 1000 Hz
//  16Mhz/256/124 = 500 Hz (corretto con il dimezzamento del period)
//  here the gatetime generation for freq. measurement takes place:
//

ISR(TIMER0_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
    TIMSK0 &= ~(1<<OCIE0A);    // disable Timer3 Interrupt(timer del gate)
    //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
    }
   
}
Title: Re: Frequency Counter Library
Post by: robtillaart on Jan 03, 2014, 06:52 pm
Thanks for fixing Leonardo support,

TCCR1B=0;                    // reset timer/counter1 control register A

mismatch between code and comment :)

Title: Re: Frequency Counter Library
Post by: dariq88 on Jan 03, 2014, 07:59 pm
Ops,probably there are others mismatch, sorry :smiley-yell:
Title: Re: Frequency Counter Library
Post by: RuRu on Feb 02, 2014, 05:20 pm
I use the frequency library on both Mega ADK ( modified library)  and Nano board.
When i measure a precise 1.000.000 Hz signal I get 1.000.169 on the display.
I try to correct this with f_comp but it seems that i can only increase the displayed reading.
How can I decrease the reading to 1.000.000 ??

Thanks for a nice frequency library. Very usefull.
Title: Re: Frequency Counter Library
Post by: Palliser on Feb 06, 2014, 11:55 pm
Hello dc42.

I just tested your improved version of a frequency counter sketch (Reply#35).
http://forum.arduino.cc/index.php?PHPSESSID=25artcic6a44jl71kf4a1kevo7&topic=64219.30 (http://forum.arduino.cc/index.php?PHPSESSID=25artcic6a44jl71kf4a1kevo7&topic=64219.30) .
It works great!. Is is possible to modify it to read frequencies between 1Hz to 3Hz. So far, I can measure with your code frequencies over 2.99Hz.

Thank you.
Palliser
Title: Re: Frequency Counter Library
Post by: sonacx on Mar 09, 2014, 10:33 pm
Can I detect a guitare sound frequency with it?
Title: Re: Frequency Counter Library
Post by: Aruen on Mar 11, 2014, 06:16 pm
Can anyone help me?

I have a bipolar signal from 40mVp to 4Vp (it has 2Kohm impedance too as it comes from an inductance). I want to measure his frecuency. I tried all configurations possible withouth succesful.

My first approach was plug into V+ and V- in an operational with open loop (so i have an square output and a single edge detector with a timer will measure). The output is not consistent due to the small voltage of the signal i guess.

I tried a transistor with the signal attached to the base and collector so it enables. It does not work either. The solution with the biestable is not possible due to the small Voltage of the signal when low frecuencies.


Thanks in advance.
Title: One decimal place missing :(
Post by: mbruck on Jun 07, 2014, 01:38 am
Hi!

I'm trying to measure frequency, and display always return on decimal place less. It should show 26640, but show only 2664. I also tryed to increase/decrease frequency, but same error occur.

I'm using FreqCounter library.  

This is the code:

Code: [Select]
#include <FreqCounter.h>


unsigned long frq;
int cnt;
int pinLed=13;

void setup() {
  pinMode(pinLed, OUTPUT);

  Serial.begin(115200);        // connect to the serial port

  Serial.println("Frequency Counter");
}


void loop() {

  // wait if any serial is going on
  FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(100);  // 100 ms Gate Time

  while (FreqCounter::f_ready == 0)

  frq=FreqCounter::f_freq;
  Serial.print(cnt++);
  Serial.print("  Freq: ");
  Serial.println(frq);
  delay(20);
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led

}


Please help !

BR !

Mladen
Title: Re: Frequency Counter Library
Post by: robtillaart on Jun 07, 2014, 08:31 am

while (FreqCounter::f_ready == 0)

is this really what you meant  ?
or is the  ;   missing

while (FreqCounter::f_ready == 0) ;

the difference is effectively a different loop

while (FreqCounter::f_ready == 0)
{
   frq=FreqCounter::f_freq;
}

or

while (FreqCounter::f_ready == 0)  {}
frq=FreqCounter::f_freq;
Title: Re: Frequency Counter Library
Post by: mbruck on Jun 07, 2014, 11:53 am
Hmm...

I didn't notice missing ; since compiled without error.  But I have found yet another post with similar problem. I'll try your both proposal.   Thank you.
Title: Re: Frequency Counter Library
Post by: impackrat9 on Jul 23, 2014, 09:05 pm

There is a workoround for use with servo library?


I have not yet tried this code yet, so if it doesn't work I am sorry!  When I thought of a workaround, I was thinking external.  I found the liked below chip on adafruit that takes an I2C signal and can create PWM without using the AtMel's PWM.  As long as the communications clock is not disabled or messed up, something like this might work for you. 

http://www.adafruit.com/product/815
Title: Re: Frequency Counter Library
Post by: roscodemars on Dec 04, 2014, 11:37 am
Hi,

I am trying to make that library work with the leonardo / Micro but can't figure it out. I replaced the code below in the FreqCounter.cpp found here : http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/

Does anybody actually ever sucessed to measure frequency using TIMER 3 on a Leonardo?




Now the library also works for leonardo
Code: [Select]
#include "FreqCounter.h"

volatile unsigned long FreqCounter::f_freq;

volatile unsigned char FreqCounter::f_ready;
volatile unsigned char FreqCounter::f_mlt;
volatile unsigned int FreqCounter::f_tics;
volatile unsigned int FreqCounter::f_period;
volatile unsigned int FreqCounter::f_comp;

void FreqCounter::start(int ms) {

#if defined (__AVR_ATmega32U4__)

    f_period=ms/2;
    f_ready=0;                  // reset period measure flag
    f_tics=0;                   // reset interrupt counter
 
 
    if (f_comp ==0) f_comp=1;  // 0 is not allowed in del us

    // hardware counter setup ( refer atmega32u4)
    TCCR1A=0;                  // reset timer/counter1 control register A
    TCCR1B=0;                 // reset timer/counter1 control register A
    TCNT1=0;               // counter value = 0

    // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino leonardo pin 12)
    // normal mode, wgm10 .. wgm13 = 0
   
    TCCR1B |=  (1<<CS10) ;//CLOCK ESTERNO su fronte di salita
    TCCR1B |=  (1<<CS11) ;
    TCCR1B |=  (1<<CS12) ;
   
    // timer0 setup / usato per la generazione del tempo di lettura
    TCCR0A=0;
    TCCR0B=0;
   
    // timer3 presaler set to 256 / timer3 clock = 16Mhz / 256 = 62.500 Hz
    TCCR0B = (1<<CS02);

    //setta il timer0 to CTC(Clear Timer on Compare)  Mode with OCR3A is top counter value (arrivato a OCR3A si resetta)
    TCCR0A = (1<<WGM01);  // CTC mode, normal (no Output compare)
    GTCCR |= (1<<PSRASY);  // reset prescaler (undocumented bit in mega32u4?)
    TCCR0B = (1<<CS02);  // timer0 on clk/256 == 16MHZ / 256 = 62500hz..
    OCR0A = 124;  // 125 counts of 62500 Hz before an output compare interrupt...

    TCNT1 = 0;
    TCNT0 = 0;

    TIMSK0 = (1<<OCIE0A);
    #endif

}
//******************************************************************
//  Timer3 Interrupt Service is invoked by hardware Timer3 every 1ms = 1000 Hz
//  16Mhz/256/124 = 500 Hz (corretto con il dimezzamento del period)
//  here the gatetime generation for freq. measurement takes place:
//

ISR(TIMER0_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
    TIMSK0 &= ~(1<<OCIE0A);    // disable Timer3 Interrupt(timer del gate)
    //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
    }
   
}

Title: Re: Frequency Counter Library
Post by: YellowGTM on Dec 31, 2014, 04:59 pm
I'm also having trouble with the Frequency Counter examples, and have tried most of the suggestions within
this thread (and others).  The #if and #endif lines were commented out within the Frequency.cpp file, however
the problem still exists.

The error message that is displayed when trying to upload the code is,  "redefinition of 'long unsigned int frq' "

I've attached a screen shot of the entire log of errors which also shows the code version that I'm using. 
The error might be caused by the board which is the Dcduino Mega 2560.

I do have an authentic Arduino Mega 2560 at home, which I'll try this evening (not sure of the chipset at the moment)

Is this message consistent with the incorrect Arduino board/chipset, or outdated .CPP file?  Otherwise, I don't see any
problem with the code?

Code: [Select]

// Frequency Counter Lib example

/*
  Martin Nawrath KHM LAB3
  Kunsthochschule f¸r Medien Kˆln
  Academy of Media Arts
  http://www.khm.de
  http://interface.khm.de/index.php/labor/experimente/
 */
#include <FreqCounter.h>


unsigned long frq;
int cnt;
int pinLed=13;

void setup() {
  pinMode(pinLed, OUTPUT);

  Serial.begin(115200);        // connect to the serial port

  Serial.println("Frequency Counter");

}



void loop() {

  // wait if any serial is going on
  FreqCounter::f_comp=10;   // Cal Value / Calibrate with professional Freq Counter
  FreqCounter::start(100);  // 100 ms Gate Time

  while (FreqCounter::f_ready == 0)

  frq=FreqCounter::f_freq;
  Serial.print(cnt++);
  Serial.print("  Freq: ");
  Serial.println(frq);
  delay(20);
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led


Title: Re: Frequency Counter Library
Post by: YellowGTM on Jan 01, 2015, 04:48 pm
I was able to successfully measure frequency using the following code on the Dcduino.  I would
expect this to work on the Mega as well.

Code: [Select]
#include <FreqMeasure.h>

double sum=0;
int count=0;
float frequency;

void setup()
{
  Serial.begin(57600);
  FreqMeasure.begin();
}


void loop()
{
  if (FreqMeasure.available())
    {

    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
   
    if (count > 30) {
      float frequency= FreqMeasure.countToFrequency(sum / count);
      Serial.println(frequency);
      sum = 0;
      count = 0;
      delay(100);
    }
  }
}
Title: Re: Frequency Counter Library
Post by: wookie1 on Jan 01, 2015, 05:58 pm
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.
Title: Re: Frequency Counter Library
Post by: woodstock on Feb 11, 2015, 10:12 am
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  :'(

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

Thanks!
Title: Re: Frequency Counter Library
Post by: polymorph on Feb 11, 2015, 04:28 pm
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?
Title: Re: Frequency Counter Library
Post by: woodstock on Feb 12, 2015, 09:30 am
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?

Code: [Select]

// 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.
Title: Re: Frequency Counter Library
Post by: Picoteando on Feb 16, 2015, 02:28 pm
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:

Code: [Select]

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!
Title: Re: Frequency Counter Library
Post by: d866 on Mar 20, 2015, 03:30 pm
Here is an improved version of the frequency counter sketch. There were a couple of problems with the previous version:

Code: [Select]

// 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!
Title: Re: Frequency Counter Library
Post by: DevilMoo on Apr 02, 2015, 06:59 pm
Hello!
Is there any method to make the frequency be a "double"?
Thanks!
Title: Re: Frequency Counter Library
Post by: CrossRoads on Apr 02, 2015, 08:02 pm
double, or long/unsigned long, instead of a float?
Title: Re: Frequency Counter Library
Post by: robtillaart on Apr 03, 2015, 03:00 pm
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,
Title: Re: Frequency Counter Library
Post by: HBO88 on Apr 09, 2015, 08:19 pm
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);
}
Title: Re: Frequency Counter Library
Post by: robtillaart on Apr 10, 2015, 09:52 pm
Check the - blink without delay - example sketch. It shows how to write delay less
Title: Re: Frequency Counter Library
Post by: HBO88 on Apr 11, 2015, 09:50 am
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.

Code: [Select]
// 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);


}
Title: Re: Frequency Counter Library
Post by: HBO88 on Apr 11, 2015, 03:59 pm
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:

Code: [Select]
// 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);

}
Title: Re: Frequency Counter Library
Post by: Chrislid on May 13, 2015, 05:04 pm
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,
Title: Re: Frequency Counter Library
Post by: full_throttle on May 14, 2015, 04:22 pm
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
Title: Re: Frequency Counter Library
Post by: polymorph on May 19, 2015, 06:06 pm
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.
Title: Re: Frequency Counter Library
Post by: tk5ep on Jun 05, 2015, 06:18 pm
@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 ?
Title: Re: Frequency Counter Library
Post by: idans on Oct 27, 2015, 02:27 pm
hi i wish to use freqcounter lib with pwm output, is it possible to use pwm when waiting to interrupt on timer2?
Title: Re: Frequency Counter Library
Post by: barryx on Dec 07, 2015, 06:15 am
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.
Title: Re: Frequency Counter Library
Post by: Yuliia_Sych on Jan 26, 2016, 12:39 am
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)
Title: Re: Frequency Counter Library
Post by: Muhammad_Adil_42 on Mar 04, 2016, 03:52 pm
In the FrequencyCounter::start() function use 1000 instead of 100 if you want to get the exact frequency in Hz. because when you write 100 in start function, it takes it in ms in library running at the back end and will calculate frequency for 100ms which obviously will be 1/10th of original frequency in Hz. Similarly using 10 in the start function will give you the frequency 1/100th of the original frequency in Hz. Hopefully you understands it now.   
Title: Re: Frequency Counter Library
Post by: futurebird on Apr 28, 2016, 01:56 am
I just wanted to thank the developer for this library. It was very useful on the project I created today. I hacked a digital anemometer which produced a pulsing signal, then used it to create a formula to translate the signal into windspeed in km/h.

I started to try to write something like this myself thank god I found this!

Title: Re: Frequency Counter Library
Post by: gawnieg on Jul 28, 2016, 12:41 pm
Hello All

I am trying to use dc42's code to measure a low frequency speed from the flywheel of an internal combustion engine. The signal of interest is a 5V square wave in the order of 30 to 40Hz. However, using dc40's code there are rogue high values (50 to 60Hz) appearing which is completely throwing my speed control system.

I am using a servo motor to control the throttle angle based on speed to keep the speed at a setpoint, using a PID library. Would this be throwing the ISR timer? Can the two work together? Where are these rogue values coming from? They appear randomly, with every 20 to 40 seconds of running:



Code: [Select]
#include <PID_v1.h> //include PID library in sketch
#include <Wire.h>
#include <Servo.h>

#define ECU2_RESET 8 //was 3
#define SERVO_PIN 9 //was 5
#define OVERSPEED_PIN 10 //overspeed to master
#define RELAY_PIN 11 //local overspeed relay

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

unsigned long over_speed_setpoint = 50; //define an over speed setpoint (i.e 3000rpm) here in correct units = 3000rpm
 double speed_setpoint = 41 ; // see engine calcs overview for this calc. or onenote To Do sheet. 48000=2500rpm, 50000=2400rpm
unsigned int sample_time = 100;
unsigned long num_iterations;




/////////////////////PID SETTINGS///////////////////////////////////////
double Kp = 1.0; //was o.008
double Ki = 0.7; // was 0.0022
double Kd=0.0;


////////////////////SERVO SETTINGS//////////////////////////////////////////////////
double throttle_setpoint;    // variable to store the desired throttle angle - WHAT SHOULD THIS BE INITIALISED AT??
int throttle_sig; //whats set to the servo = (90-throttle_setpoint) calculated by map() function
Servo myservo; //initalising servo as servo object

double freq_1=0; //variable for frequency readout


boolean engine_running = false; // this is false until the engine starter motor is engaged

PID myPID(&freq_1, &throttle_setpoint, &speed_setpoint, Kp, Ki, Kd, DIRECT); //PID setup using speed avg //REVERSE




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

void setup()
{

Serial.begin(9600);
Serial.println("Setup Finished");
Serial.print("This  run we have :  ");
Serial.print("Kp = ");
Serial.print(Kp);
Serial.print(" Ki = ");
Serial.print(Ki);
Serial.print(" Kd = ");
Serial.print(Kd);
Serial.print("Sample time = ");
Serial.print(sample_time);
Serial.print("Speed setpoint = ");
Serial.println(speed_setpoint);

pinMode(21, INPUT);     //input for the HES signal
digitalWrite(21,HIGH); // added to prevent floating values???


pinMode(OVERSPEED_PIN, OUTPUT); //pin 4 will be HIGH when engine speed is too high and shutdown is required, LOW when ok to keep running.OVERSPEED PIN
pinMode(RELAY_PIN,OUTPUT); //pin 7 as local overspeed pin

digitalWrite(OVERSPEED_PIN,LOW); //initailly set this to low to say that there is no overspeed on system intialisation
digitalWrite(RELAY_PIN,HIGH); //initailly set this to low to say that there is no overspeed on system intialisation


myservo.attach(SERVO_PIN);//attaching the servo to PIN 9.
myservo.write(8);// setting inital value of 85 to get it started on idle
myPID.SetMode(AUTOMATIC); //this sets the PID algoithm to automatic, i.e. it will compute every loop





}

// 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(2, isr, RISING);    // enable the interrupt
 delay(sampleTime);
 detachInterrupt(2);
 return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime); // if the number of pulses is less than 3, then 0, otherwise -


}

void loop()
{
  if(engine_running==true){
    num_iterations++;
  }

 
freq_1 = readFrequency(sample_time);


if(freq_1 > 5 && engine_running == false && freq_1 < 1000){ //if the engine is cranking then the engine_running variable is set to on so the PID controller is activated
  Serial.println("Engine is now running, ECU activated");
  engine_running = true;   
     }



  if(engine_running==true ){ //if closed loop control is need then the master controller will set pin 3 to HIGH AND the engine has started and the servo should be activated
   myPID.Compute();//required for PID to work
   throttle_sig=(int)map(throttle_setpoint, 0, 255, 6, 87);// remapping the PID controller output (0-255), set by the PID setoutput function in the setup to 90 to 0 i.e. 90 degrees throttle_setpoint is actually 0 degrees throttle angle ---23.05.2016 was 0,255,0,90 changed to 87 as was conking on start
   myservo.write(throttle_sig); // this is writing the mapped PID output to the servo
//      Serial.print("The PID OUTPUT is: ");
   Serial.print(throttle_setpoint);
   Serial.print("\t");
//   Serial.print("The servo sig is: ");
   Serial.print(throttle_sig);
   Serial.print("\t");
//   Serial.print("The speed is is: ");
   Serial.print(freq_1);
   Serial.print("\t");
   Serial.print(freq_2);
   Serial.print("\t");
   Serial.println(millis());
  }

  if(freq_1 >= over_speed_setpoint){
  Serial.println(freq_1);
  digitalWrite(OVERSPEED_PIN,HIGH); //sending 5v signal to master to indicate overspeed
  digitalWrite(RELAY_PIN,LOW);     
  Serial.println("OVERSPEED");

 
  }
  else {
  digitalWrite(OVERSPEED_PIN,LOW);//telling master that there is no overspeed present
  digitalWrite(RELAY_PIN,HIGH); //keeping local overspeed relay switched on as there is no issues
  }

}
Title: Re: Frequency Counter Library
Post by: Atmoz22 on Sep 01, 2016, 07:23 pm
Hey,

I have to measure the netfrequenzy and i need a resolution of milli hertz 50.xxx Hz, is it possible to change the counter resolution that he will measure milli Hertz?
Title: Re: Frequency Counter Library
Post by: Freezin on Oct 05, 2016, 11:57 pm
Post 42 has a modified library for the Leonardo. As I go through the code it says it will measure the frequency on pin 12 of the Leonardo. Is there any way to change it so the input frequency can be on D5 or D11?

// hardware counter setup ( refer atmega32u4)
    TCCR1A=0;                  // reset timer/counter1 control register A
    TCCR1B=0;                    // reset timer/counter1 control register A
    TCNT1=0;                    // counter value = 0
   
    // set timer/counter1 hardware as counter , counts events on pin T1 ( arduino leonardo pin 12)
    // normal mode, wgm10 .. wgm13 = 0
   
    TCCR1B |=  (1<<CS10) ;//CLOCK ESTERNO su fronte di salita
    TCCR1B |=  (1<<CS11) ;
    TCCR1B |=  (1<<CS12) ;
Title: Why doesn't FreqCount library support tone()
Post by: anilpandeya12 on Jan 08, 2017, 08:57 am
#include <FreqCount.h>

void setup() {
  Serial.begin(57600);
  FreqCount.begin(1000);
}

void loop() {
  tone(9,3100);    //Error in compiling when added this line in arduino Uno
  if (FreqCount.available()) {
    unsigned long count = FreqCount.read();
    Serial.println(count);
  }
}
Title: Re: Frequency Counter Library
Post by: loic_38 on Jan 10, 2017, 11:48 am
Hi All !

Since the 1.8.0 update, the fequency counter using interrupt doesn't work..
I have an Arduino.org M0 Board. Do you have the same problem with other boards ?


Code: [Select]
void isr()
{
 unsigned long now = micros();
 if (numPulses == 1)
 {
   firstPulseTime = now;
 }
 else
 {
   lastPulseTime = now;
 }
 ++numPulses;

float readFrequency(unsigned int sampleTime)
{
 numPulses = 0;                      // prime the system to start a new reading
 attachInterrupt(2, isr, RISING);    // enable the interrupt
 delay(sampleTime);
 detachInterrupt(2);
 return (numPulses < 3) ? 0 : (1000000.0 * (float)(numPulses - 2))/(float)(lastPulseTime - firstPulseTime); // if the number of pulses is less than 3, then 0, otherwise -

}
Title: Re: Frequency Counter Library
Post by: Luis_Barragan on Jan 10, 2019, 12:12 am
hola que tal...

estoy empezando un proyecto, modificando el contador de frecuencias, pero no tengo idea de como empezar.

les explico lo que quiero a ver si alguien me ayuda....

quiero contar la frecuencia de una señal analoga, guardadrla en una variable (x) y dividirla para dos  (x/2)

y reproducir el valor de la variable divida en forma de pulsos digitales


en otras palabras por cada dos pulsos analogicos se emita un pulso digital
Title: Re: Frequency Counter Library
Post by: ShantelJean on Apr 06, 2019, 02:18 am
Try this:

Code: [Select]

// 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 == 0)
  {
    firstPulseTime = now;


  }
  else
  {
    lastPulseTime = now;
  }
  ++numPulses;
}

void setup()
{
  Serial.begin(19200);
}

// Measure the frequency over the specified sample time in milliseconds, returning the frequency in Hz
unsigned int 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 < 2) ? 0 : (1000000UL * (numPulses - 1))/(lastPulseTime - firstPulseTime);
}

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

hie dc42 how can i use this code wch incoporates interrupts to measure frequency from an astable  555 timer circuit of of up to 100khz.
Title: Re: Frequency Counter Library
Post by: jb1055 on May 20, 2019, 03:22 pm
Hello,
I would like to measure a frequenze from 150kHZ with my Arduino Mega2560.
Do I Need a Spezial <FreqCounter.h> for the Adruino Mega?
I copied the Sketch from #2 but i get a lot of Errors. I quess i have the <FreqCounter.h> for the Arduino Uno
Thank you for helping.