Frequency Counter (for fan tachometer or RPM)

I’m looking for a frequency counter library to measure the speed of a 3 wire fan. After testing a fan, it seems that the frequency output from the tachometer pin is twice the frequency of the rotations. i.e.

fan frequency = tachometer frequency / 2

So to read a fan speed of 3000 RPM you need to read a frequency of at least a 100Hz square wave.

Have any frequency counting libraries been ported to the spark core yet?

Thanks

Some examples I found for other systems:
https://www.pjrc.com/teensy/td_libs_FreqCount.html
http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-frequency-counter-library/

Edit: seems like there is at least one. I’ll try it out soon.

3 Likes

Hey that's sweet! Didn't know that was available :smile:

1 Like

@waspinator, if duty cycle is not important (which it is not in your application), you can count the pulses on a pin using an interrupt (rising or falling edge only). Then, using SparkIntervalTimer, create a timer that fires off an interrupt every second or fraction thereof. At every timer interrupt, you take the pulse count and reset it for the next cycle. If the timer is set to 1 second, then the number of pulses represents your rotations per second or RPS which, when divided by 60 is revolutions per minute or RPM. If your rotation is very slow, then you can increase the timer interval accordingly.

I am not sure how you measured the frequency of the “tachometer pin” but if you were measuring both rising and falling edges of the signal, the “frequency” would be double since every period of the signal has a rising and falling edge. If you need help putting this together, let me know. :smile:

I like that FreqPeriodCounter library because it has debouncing built in. With interrupts, you have to implement your own debouncing code, add an external debouncing RC filter, or just get lucky with a signal that doesn’t bounce. Things to keep in mind :slight_smile:

@BDub, I just remembered that the library is designed such that it can be used with interrupts! DOH!!! Just look at the example!! :stuck_out_tongue:

1 Like

Hi Peekay,

I finally got around to trying the library you ported, but without success. Have you tried reading a frequency using it and a spark core?

Besides including the library in my app, this is the main .ino file. Can you see if I’m making any mistakes?

All you need to do to test my code is flash the program and connect A0 to D4.

I checked D4 with an oscilloscope and it has a 500Hz 3.3V signal.

Thanks for your help.

#include "FreqPeriodCounter.h"

const byte simulated_fan_output_pin = A0;
const byte counter_interrupt_pin = D4; 
FreqPeriodCounter counter(counter_interrupt_pin, micros, 0);

const int k_seconds_per_minute = 60;

void setup() 
{
    Serial.println("Computer fan RPM Demo");
    
    pinMode(simulated_fan_output_pin, OUTPUT);
    analogWrite(simulated_fan_output_pin, 100); // any number here should create a 500Hz frequency
    
    attachInterrupt(counter_interrupt_pin, counter_interrupt_service_routine, RISING);
    Serial.begin(9600);
}

void loop() 
{
    int period;
    long hertz;
    int rotations_per_minute;
    
    if(counter.ready()) {
        period = counter.period;
        hertz = counter.hertz();
        rotations_per_minute = hertz * k_seconds_per_minute;
        
        Serial.print("Period: ");
        Serial.print(period);
        Serial.print("\t");
        
        Serial.print("Hertz: ");
        Serial.print(hertz);
        Serial.print("\t");
        
        Serial.print("RPM: ");
        Serial.print(rotations_per_minute);
        Serial.print("\t");
        
        Serial.println();
        
    }
}

void counter_interrupt_service_routine()
{ 
    counter.poll();
}

@waspinator, I don’t see where you set the counter_interrupt_pin as INPUT. Look at the example (test.ino) for tips. :smile:

not sure why I missed the test.ino. It works with that, so I’ll just have to make sure my code follows it. Thanks again.

1 Like

Okay, I got it to read RPM readings with the code below. You have to connect the power supply ground pin to the Spark Core and pull the tachometer pin on the fan high through a 10k resistor before connecting it to pin D4. It works with both 3.3V and 5V levels. (not all pins support 5V though, but D4 does)

I had to divide the frequency by two as I speculated earlier. I tried running the interrupt on RISING to avoid it, but then I could never get counter.ready() to equal true.

According to documentation specifying fan tachometer signal standards there are two pulses per revolution.

2.3 Tachometer Output Signal

Fan shall provide tachometer output signal with the following characteristics:

  • Two pulses per revolution
  • Open-collector or open-drain type output
  • Motherboard will have a pull up to 12V, maximum 13.2V

Thanks again for your porting efforts.

#include "FreqPeriodCounter.h"

const int simulated_fan_output_pin = A0;
const int counter_interrupt_pin = D4; 

FreqPeriodCounter counter(counter_interrupt_pin, micros, 0);

const int k_seconds_per_minute = 60;
const int k_pulses_per_revolution = 2;
const int k_hertz_to_RPM_conversion_factor = k_seconds_per_minute / k_pulses_per_revolution;

void setup(void) 
{
    Serial.begin(9600);
    Serial.println("Computer fan RPM Demo");
    
    pinMode(simulated_fan_output_pin, OUTPUT);
    analogWrite(simulated_fan_output_pin, 128); // any number here should create a 500Hz frequency
    
    pinMode(counter_interrupt_pin, INPUT);
    attachInterrupt(counter_interrupt_pin, counter_interrupt_service_routine, CHANGE);
    
}

void loop() 
{
    int period;
    long hertz;
    int RPM;
    
    if(counter.ready()) {
        period = counter.period;
        hertz = counter.hertz();
        RPM = hertz * k_hertz_to_RPM_conversion_factor;
        
        
        Serial.print("Period: ");
        Serial.print(period);
        Serial.print("\t");
        
        Serial.print("Hertz: ");
        Serial.print(hertz);
        Serial.print("\t");
        
        Serial.print("RPM: ");
        Serial.print(RPM);
        Serial.print("\t");
        
        Serial.println();
        
    }
    else {
        Serial.print(".");
    }
}

void counter_interrupt_service_routine()
{ 
    counter.poll();
}
2 Likes

Hello!
I’d like to use freqCount.h in my project, but I can’t understand how to include it in my project in a private way (this library is not in the community libraries and I have not understand how to use them in a project)
Could you please help me? :slight_smile:
Thank you!

Double posting is not appreciated.
I already have answered to the same question in this thread

@ScruffR already answered in another thread, but including non-community libraries in the Web IDE simply requires a few cut and paste operations. Open web IDE and recall whatever project you are working on. Create a new tab (click the “+” in the top right corner) and name the tabs: “FreqPeriodCounter.cpp” and “FreqPeriodCounter.h”. Go to @peekay123 's Github repository and copy the contents of each of those files and then paste them into your newly created tabs. Done.

Sorry! I've read this thread after a while and seemed to be more appropriate.

Thank you. I had some problems in saving firmware acting like that but I'll try with this library too. Have you already used this library with particle photon? Does it fit with photon hardware?
Thank you!

Still have the same issue as for the other library: i cannot save the firmware. I copied/pasted the files and I can’t save them :confused:

Can you post the raw errors from the Web IDE?

I just compiled the example from the githup repo and it compiled without error. Here’s a shared app of the example. There must be something else in your code causing the issue. Posting the raw errors would help identify what the issue is. Posting your code or a shared link is also preferable.

This Frequency Counter library if hardware dependent and will not work on the Particle as-is. @ninjatill, the fact that it compiles may be a fluke.

Sorry, I wasn’t clear. @peekay123 I was compiling your FreqPeriodCounter. Not the other library brought up by @Aloap.

1 Like

I would, but I cannot get the sharable link too :confused:
At a glance, it doesn't seem to have any differences from yours

Ok, my issue doesn’t depend on what I’m compiling… I cannot save anything! :disappointed_relieved:
I’ll try to figure it out, thank you to all! :slight_smile:

  • If Windows: DON’T use IE or Edge

otherwise

1 Like