Arduino frequency counter facts
Here is a frequency counter for the Arduino which measure the period and pulse width, it was needed for a pedelec legalisation device and a scale interface. Look for the latest version here:
-
The period is measured instead of the frequency; this is done to save program space. The frequency can be calculated with 1/period; however this will include the float library which takes a lot of memory. Thus the frequency calculation is left out of the library code. - These values are available: frequency, period, pulseWidth, pulseWidthLow, elapsedTime and level.
- The frequency counter can be used in two ways:
With an interrupt triggered by the input signal.
Polled regularly with the poll() instruction in a loop. - Take a debounce time of about 10ms if the frequency comes from a mechanically switch.
- The measurement can be done in milli seconds or micro seconds.
Frequency counter example
#include <Streaming.h>
#include <FreqPeriodCounter.h>
const byte freqPin = 3;
#define debounceTime_ms 10
FreqPeriodCounter freqPeriodCounter(freqPin, millis, debounceTime_ms);
void setup(void)
{ Serial.begin(9600);
}
void loop(void)
{ freqPeriodCounter.poll();
Serial << freqPeriodCounter.period << endl;
}
Frequency counter library
/* FreqPeriodCounter
* Version 25-11-2011
* Copyright (C) 2011 Albert van Dalen http://www.avdweb.nl
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses.
<------------- period ------------>
pulseWidth
_____________ ______________
|| || || ||
|| || pulseWidthLow || ||
______________|| ||__________________|| ||______________
periodCount 0 1
transientTime ^ ^ ^ ^
level 1 0 1 0
debounceTime <--> <--> <--> <-->
<- elapsedTime ->
*/
#include "FreqPeriodCounter.h"
// debounceTime in msec if msec_usecNot=1 else in usec
FreqPeriodCounter::FreqPeriodCounter(byte pin, bool msec_usecNot, unsigned debounceTime):
time(0), transientTime(0), elapsedTime(0), pulseWidth(0), pulseWidthLow(0), period(0), periodCount(0), level(0), lastLevel(0),
pin(pin), msec_usecNot(msec_usecNot), debounceTime (debounceTime)
{
}
bool FreqPeriodCounter::poll()
{ if(msec_usecNot) time = millis();
else time = micros();
elapsedTime = time - transientTime;
level = digitalRead(pin);
if((level != lastLevel) & (elapsedTime > debounceTime))
{ lastLevel = level;
transientTime = time;
if(level == HIGH)
{ pulseWidthLow = elapsedTime;
period = pulseWidth + pulseWidthLow;
if(periodCount++ > 1)
{ periodCount = 0;
return true; // return true if a complete period is measured
}
}
else pulseWidth = elapsedTime;
}
return false;
}
unsigned int FreqPeriodCounter::hertz()
{ if (timeFunctionPtr == micros) return 1000000/period;
else return 1000/period;
}
#ifndef FREQPERIODCOUNTER_H
#define FREQPERIODCOUNTER_H
/* FreqPeriodCounter
* Version 25-11-2011
* Copyright (C) 2011 Albert van Dalen http://www.avdweb.nl
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* This program 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 General Public License for more details.
* You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses.
*/
#include <WProgram.h>
class FreqPeriodCounter
{
public:
FreqPeriodCounter(byte pin, bool msec_usecNot, unsigned debounceTime);
bool poll();
unsigned long period, pulseWidth, pulseWidthLow, elapsedTime;
bool level;
protected:
unsigned long time, transientTime;
unsigned debounceTime;
byte periodCount, pin;
bool lastLevel, msec_usecNot;
};
#endif