Frequency / period counter

Thanks for sharing,

What is the range it can measure?
What is its accuracy? (can be improved by counting multiple periods of course)

Hi
The lowest time with polling is about 40us -> 25kHz. The longest time is 50 days....

why is not all of the required code included?

maybe it's just because I'm new, but I frequently find that many "included" libraries that I simply don't have.

"WProgram.h" is referenced but not included in this one, for example, and "streaming.h"

When I search for Streaming.h I find several, but they then each include some other library that I don't have (LOG.h, or whatever...)

at some point I guess my libraries will include so much random stuff that I'll have better luck with downloaded sketches?

Hi
See for the libraries here:

Wprogram.h is included in Arduino by default.

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.

One can calculate the frequency also by doing integer math. If one expresses the time in micros then the frequency is:

...
period = micros() - start;
long freq = 1000000L/period;
Serial.print("freq: ");
Serial.println(freq);
...

if one wants to add 3 decimals (1 and 2 decimal are similar)

...
period = micros() - start;
long freq = 10000000000L/period;  // note the extra 000
Serial.print("freq: ");
Serial.print(freq/1000);
Serial.print('.');
Serial.print(freq%1000);
...

Wprogram.h is included in Arduino by default.

With versions 0023 and earlier, that is. With 1.0, that file was renamed to Arduino.h. The conditional/unconditional inclusion is how you can tell if a library is compatible with 1.0. Conditional is; unconditional is not.

avandalen:
Hi
See for the libraries here:
http://www.avdweb.nl/arduino/troubleshooting.html#h0-1-1-1-frequently-used-libraries

Wprogram.h is included in Arduino by default.

Thanks!

I've been able to get some data logged, and something odd is emerging. with a fairly large sample size (hundreds of data) there seem to be some discrete "favorite" values. Out of 1000 or so measurements, there are only about 8 discrete values, and they reach out to 5 digits behind the decimal point. weird, huh!?

I'm measuring the frequency of the AC electricity, so the measurement is around 60Hz. I have a real time monitor set up on a Digital multimeter, and also have historical data, so I know sort of how the frequency behaves (and it's not by jumping from one discrete value to another). a favorite seems to be 60.024 (about 20% of all values are 60.024HZ , lol).

When plotted in excel it seems to have a distinct upper and lower bound (say 59.953 to 60.0421), and in between it leaps around almost at random

is there something I can adjust to make it more granular of a measurement?

and something odd is emerging.

pictures?

not sure how to post a graph...

here's a small excerpt of the data. In its repetitiveness of the smae values over and over it is very representative of the whole dataset.

59.9952
60.0096
60.0096
60.024
60.0096
60.024
59.9952
60.024
59.9808
60.0096
59.9952
60.024
60.0096
59.9377
59.9664
60.0528
60.0096
59.9233
60.0096
59.9952
59.9952
59.9952
59.9808
59.9952
59.9952
60.0096
59.9952
60.024
60.0096
60.024
59.9952
59.9952
59.9808
59.952
60.0096
60.0096
60.0096
60.0096
59.9952
59.9808
60.0096
59.9808
59.952
59.9808
59.9377
59.9952
60.024
60.0096
60.024
60.0096
60.0096
59.9664
60.0096
59.952
59.9952
60.0096
59.9952
60.0096
59.9952
59.9952
60.0096
59.9377
60.024
60.0096
59.9808
59.9952
60.024
60.024
60.0096
59.9952
60.024
60.024
60.024
60.024
60.0096
60.0096
60.024
59.9664
59.952
59.9808
59.9377
60.024
60.024
60.024
59.952
59.952
60.024
60.0096
59.952
59.952
59.9952
59.9952
60.0096
60.0096
60.0096
60.024
60.0096
60.024
60.0096
60.0096
60.0096
59.9377
59.9664
59.9664
60.0096
59.9808
59.9952
60.0096
59.9952
59.9952
59.9952
59.9377
60.0096
59.9952
60.024
59.9808
59.9664
59.9952
60.0096
60.0096
59.9952
59.9808
59.9808
60.0096
60.024
60.0096
59.9808
59.9664
60.0096
60.0673
59.952
59.952
60.024
60.0096
59.9952
59.9952
60.0096
60.024
60.0096
60.0096
60.0096
60.024
60.0096
60.024
60.024
60.024
59.952
60.024
59.9952
59.9952
60.024
59.9952
59.9664
59.9952
59.9808
60.0096
59.9952
60.0096
60.0096
59.9952
59.9808
60.024
60.0096
60.0096
59.9664
59.9664
59.9808
59.9377
60.0096
60.024
60.024
60.0384
59.9952
59.9952
60.0096
60.0096
59.9808
60.024
59.9664
59.9952
59.9952
60.0096
60.024
60.024
60.024
59.9808
59.952
59.9664
59.9377
60.0096
59.9664
60.024
60.0096
59.9808
59.9664
59.9664
59.9664
59.9664
59.9952
60.0096
60.024
60.024
59.952
59.9952
60.024
60.024
59.9952
60.024
60.0096
59.9952
60.024
59.9808
60.024
59.9664
59.9808
59.952
59.9664
59.952
59.9952
60.0096
59.9377
59.952
59.9664
59.9377
60.0096
60.024
59.9664
59.952
59.9952
60.024
59.9377
60.024
60.024
60.024
59.9808
59.952
59.9808
59.9664
59.952
59.9664
59.9664
59.9808
60.0096
59.9952
60.0096
59.9664
59.9808
59.9952
60.0096
59.9664
59.952
60.0096
60.024
59.9664
59.952
59.9952
60.0096
59.9952
59.952
60.0384
59.952
59.9377
60.0096
60.0096
59.9664
60.024
59.9952
59.9952
60.0096
60.024
59.9664
59.952
59.9377
59.9952
60.0096
60.024
60.0096
59.9808
59.9952
60.0096
60.024
59.9952
59.9952
60.0096
59.9664
59.9377
59.952
60.0096
60.024
59.9664
60.0096
60.0096
60.0096
59.9664
60.0096
59.9664
59.9664
59.9377
59.952
59.952
59.9664
59.9377
60.0096
60.024
59.9808
59.9664
59.9952
60.024
59.952
59.952
60.0096
60.0096
60.0096
60.0096
59.9952
60.0096
60.024
60.024
60.0096
60.024
[/table]

robtillaart:

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.

One can calculate the frequency also by doing integer math. If one expresses the time in micros then the frequency is:

...

period = micros() - start;
long freq = 1000000L/period;
Serial.print("freq: ");
Serial.println(freq);
...




if one wants to add 3 decimals (1 and 2 decimal are similar)


...
period = micros() - start;
long freq = 10000000000L/period;  // note the extra 000
Serial.print("freq: ");
Serial.print(freq/1000);
Serial.print('.');
Serial.print(freq%1000);
...

Hi Rob,

I thanks! I have added a function hertz() now, see also changed the website:

int FreqPeriodCounter::hertz()
{ if (timeFunctionPtr == micros) return 1000000/period;
  else return 1000/period;
}

I'm measuring the frequency of the AC electricity, so the measurement is around 60Hz. I have a real time monitor set up on a Digital multimeter, and also have historical data, so I know sort of how the frequency behaves (and it's not by jumping from one discrete value to another). a favorite seems to be 60.024 (about 20% of all values are 60.024HZ , lol).
When plotted in excel it seems to have a distinct upper and lower bound (say 59.953 to 60.0421), and in between it leaps around almost at random
is there something I can adjust to make it more granular of a measurement?

That's not really nice, I want the library improve further if possible.
1. Printing is not allowed during the measurement. Maybe you can store the data in an array (memory of the Arduino), and later print it out?
2. If you have used polling, try interrupt operation instead of polling.

here's a small excerpt of the data. In its repetitiveness of the smae values over and over it is very representative of the whole dataset.

Repeating output values are probably caused by the fact that you are reaching the limits of the accuracy.

Test:

Copy the numbers to a speadsheet in colum A
Sort that colum from low - high
Make colum B : "=A2-A1" extended for the whole colum A
There will appear 2 distinct values : 0 and 0,0144 (+- 0,0001)
which means the resolution the (current) algorithm produces is 0,0144, so printing with more than 2 decimals makes no sense

If you want more decimals you need to do a numerical analysis of the algorithm (and hardware sample freq/timinig/adc precision etc)).

Hope this helps,

avandalen:
That's not really nice, I want the library improve further if possible.
1. Printing is not allowed during the measurement. Maybe you can store the data in an array (memory of the Arduino), and later print it out?
2. If you have used polling, try interrupt operation instead of polling.

I think something may be getting lost in between languages or something. I really did not mean to be unkind or "not nice" in any way.

I think I am simply not smart enough to use the interrupt operation. I keep getting error messages when trying to compile, but I am using an Arduino Mega 2560, so maybe it wasn't written for that platform. Or, it could just be that I am really new to all this and just haven't learned enough yet.

Hi,
is there any way with this library to get Hertz in a decimal?
I need accuracy up to about 850Hz, to calculate engine RPM.
Having hertz only as a whole number is reducing the accuracy.

Thanks!

is there any way with this library to get Hertz in a decimal?
I need accuracy up to about 850Hz, to calculate engine RPM.
Having hertz only as a whole number is reducing the accuracy.

change the freq to be float iso long wouyld be the first step ...

Is there a way to run 2 instances of this counter at once?
I need to measure 2 discreet frequencies.
One can be an interrupt, the other would have to be with polling (as my other interrupt pin is doing another job in this project).

I try and compile with;

FreqPeriodCounter counter(counterPin, micros, 0);
FreqPeriodCounter counter2(shaftPin, micros, 0);

but it throws up errors as all the variables (counter.hertz, counter.period etc etc) are being defined twice.

Can I copy the library files to another one, call it FreqPeriodCounter2, and add a 2 to all the variable names? Would that work??

New link:

hi how can we calculate duty cycle using this library.

second thing when i use this library freq. change occurs only once.For e.g. after rotating potentiometer of 555 timer (PWM generator mode) only first instance is recorded, to further change the freq. i have to cut off the supply of 555 timer.

Just calculate pulseWidth/Period