• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

Making a display for fan RPM

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.
Try reading the duration of the tach pin being low. That should be a stronger signal.
Alternatively another thing you can do is use a dedicated resistor to pull the tach line high, and may it a smaller value. If you're using a 10k right now, try a 5k. If you're using a 5k, try a 3k.
Lower than 2.2k isn't recommended. That should give you the cleanest HIGH though.
 
Oh by the way, so u don't' have to mess with the, use the on board pullup resistor:

void setup() {

pinMode(tachIn, INPUT);
tachIn(digitalWrite, HIGH);

}

tried it with setting pin 2 to HIGH and not using the pull up resistor... Still the same inconsistencies in the RPM readouts.

Try reading the duration of the tach pin being low. That should be a stronger signal.
Alternatively another thing you can do is use a dedicated resistor to pull the tach line high, and may it a smaller value. If you're using a 10k right now, try a 5k. If you're using a 5k, try a 3k.
Lower than 2.2k isn't recommended. That should give you the cleanest HIGH though.

Setting the pulseIn() to read the LOW does make it better, but it still goes crazy in the mid range of teh duty cycle.

I'm thinking maybe pulseIn() is not the way to go... If it were; it would have been used by now.
 
It might have, it also might not. It's a bit outside the normal box thinking though that's for sure.
Give the 2.2k and pulseIn HIGH a shot.
Or slap the 555 thing together on a breadboard (unless you sent me all your 555s, heh) and see what it thinks about life.
 
tried it with setting pin 2 to HIGH and not using the pull up resistor... Still the same inconsistencies in the RPM readouts.



Setting the pulseIn() to read the LOW does make it better, but it still goes crazy in the mid range of teh duty cycle.

I'm thinking maybe pulseIn() is not the way to go... If it were; it would have been used by now.

Oh I was just saying that so that you don't' have to use a resistor to pull the pin high.

Also, who knows how accurate that pulsIn() function is read read that It can misread and miss pulses... I forget what article it was, but it was on my adventure to get rpm readings
 
Oh I was just saying that so that you don't' have to use a resistor to pull the pin high.

Also, who knows how accurate that pulsIn() function is read read that It can misread and miss pulses... I forget what article it was, but it was on my adventure to get rpm readings

I tried it with the built in pull up resistor and it was kind of flaky...

A bit frustrating this thing... No single example of code seems to like the Nidec, or the San Ace fans. :(
 
What about more "normal" fans?

I should be able to scope the tach output of Nidec, Delta, and JouJye 5000+rpm 3.5a+ fans within the next couple hours here, I'll post video when I do.
 
I tried it with the built in pull up resistor and it was kind of flaky...

A bit frustrating this thing... No single example of code seems to like the Nidec, or the San Ace fans. :(
Err have you used my version? There's a dividor in mine u can use for dual pulse fans
 
Err have you used my version? There's a dividor in mine u can use for dual pulse fans

Here's the code I'm using right now...

Code:
// Include the library
#include <LiquidCrystal.h>

// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7,8,9,10,11, 12); 


int NbTopsFan; //store count total
int Calc;            //store result after calculation is complete          
int hallsensor = 2;          //the pin location of the sensor


typedef struct{              //Defines the structure for multiple fans and their dividers
  char fantype;
  unsigned int fandiv;
}

fanspec;
fanspec fanspace[3]={{0,1},{1,2},{2,8}}; //used to select the fan divider 

char fan = 1;   //This is the varible used to select the fan and it's divider(reference the above line)

void rpm ()      //This is the function that the interupt calls 
{ 
 NbTopsFan++; //increment the counter
} 

void setup() {
   lcd.begin(16, 2); // Initialize LCD
   pinMode(hallsensor, INPUT); //Set Hallsensor, which is attached to digital   pin2, to INPUT
   digitalWrite(hallsensor, HIGH);  //use Arduino internal pullup resistor
   attachInterrupt(0, rpm, RISING); //Uno has numbers 0 (on digital pin 2) and 1 (on digital pin 3). 
}

void loop() 
{
   NbTopsFan = 0;	//Set NbTops to 0 ready for calculations
   sei();		//Enables interrupts
   delay (500);	//Wait .5 second
   cli();		//Disable interrupts
   Calc = ((NbTopsFan * 120)/fanspace[fan].fandiv); //Times NbTopsFan (which is apprioxiamately the fequency the fan is spinning at) by 60 seconds before dividing by the fan's divider
   lcd.setCursor(0, 0);
   lcd.print("TEST");
   lcd.setCursor(0, 1);
   lcd.print(Calc,DEC);
 
  }

I have tried the 3 different fanspaces for the three different dividers; I have tried changing the dividers; I have tried changing the "* 120" part of Calc.... Nothing gives me an accurate, reliable, consistent reading.


And what's your circuit physically look like?

Circuit is just the LCD connected to the R3 and then the tach wire from teh fan straight to pin 2 on the R3. I had it with the pull up resistor, but since the code above uses the built in one; I removed it.


EDIT
Tried it on a more "conventional" PWM fan and it works fine... The only issue is that when the RPM readout on teh LCD goes from 4 characters to 3 (fan slows down below 1000 rpm) the 4th character remains ON and throws the whole thing off.
 
Last edited:
I am gonna have to play around with my qfr's later with the arduino. Ordered a smaller qfr today aswell, 150cfm and am probably gonna pickup a few nidec beta V's off ebay this week. So it will give me a chance to see what i can up with.
 
You wont' get a rock solid result, the rpm will bounce between 50-100 rpm

Additionally, the reason the 4th number stays on, is because you aren't clearing the lcd, thus the number stays there

Add lcd.clear() to the beginning of the loop and it will clear the lcd before it outputs anything
 
Also, to help out because if your extremely fast fan

change the half second delay to 1000 and change the 120 to 60

This will let teh arduino poll for a longer time, refresh will be slower but this gives you more time to get more of a count which will lead to less variance in the RPM output
 
That part of the calculation assumes that whatever is taken in .5/s will double.

take a full second of polling will give you a better reading bc your fan is so fast
 
Working on some changes now that I get more of the logic of how this works and calculates the actual RPMs...

Will update here once I get this thing sorted out.
 
I've taken some video and none of my fans have especially much noise, as long as the Arduino is willing to accept that 1v is a digital 0.

I'm going to continue digging, next up is implementing S33b's code in an Arduino and seeing what it does.


Hey try this seebs, this is with a ~10k (actually 9.7k, heh) ohm resistor between pin2 and 5v to pull it up, and pin2 connected to the fan's tach line (which is not plugged into the computer! No 12V for pin2! Killed a chip that way). EDIT: Tried it with the internal pullup, works fine.

Code:
unsigned long data;
void setup(){
  pinMode(2,INPUT);
  Serial.begin(9600);
}


void loop(){
  data = pulseIn(2,HIGH);
  Serial.print(15000000 / data);
  Serial.print(", ");
  Serial.println(1000000 / data * 60 / 4);
  delay(500);
}

My serial output (just use the arduino serial for debugging, way easier than LCD debugging!) with the JouJye Monstah looks like this:
Code:
5988, 5985
6045, 6045
6014, 6000
6009, 6000
6026, 6015
6026, 6015
6014, 6000
6028, 6015
6028, 6015
6028, 6015
5988, 5985
6045, 6045
5968, 5955
6033, 6030
6028, 6015
6028, 6015
6045, 6045
6090, 6090
6009, 6000
5968, 5955
6000, 6000
6033, 6030
5983, 5970
6050, 6045
Also worth noting is how the order of operations in the Arduino gives different RPM readings and sensitivities.
 
I've taken some video and none of my fans have especially much noise, as long as the Arduino is willing to accept that 1v is a digital 0.

I'm going to continue digging, next up is implementing S33b's code in an Arduino and seeing what it does.


Hey try this seebs, this is with a ~10k (actually 9.7k, heh) ohm resistor between pin2 and 5v to pull it up, and pin2 connected to the fan's tach line (which is not plugged into the computer! No 12V for pin2! Killed a chip that way). EDIT: Tried it with the internal pullup, works fine.

Code:
unsigned long data;
void setup(){
  pinMode(2,INPUT);
  Serial.begin(9600);
}


void loop(){
  data = pulseIn(2,HIGH);
  Serial.print(15000000 / data);
  Serial.print(", ");
  Serial.println(1000000 / data * 60 / 4);
  delay(500);
}

My serial output (just use the arduino serial for debugging, way easier than LCD debugging!) with the JouJye Monstah looks like this:
Code:
5988, 5985
6045, 6045
6014, 6000
6009, 6000
6026, 6015
6026, 6015
6014, 6000
6028, 6015
6028, 6015
6028, 6015
5988, 5985
6045, 6045
5968, 5955
6033, 6030
6028, 6015
6028, 6015
6045, 6045
6090, 6090
6009, 6000
5968, 5955
6000, 6000
6033, 6030
5983, 5970
6050, 6045
Also worth noting is how the order of operations in the Arduino gives different RPM readings and sensitivities.


YES!!! Order of operations is VERY important, I found this out the hard way.

I like this pulseIn() function, I care to I plement this with my motion sensor that I just picked up.

and yeah, the internal pull up will always work fine, it only needs an itty bitty little bit to be pulled high, high impedance, so it's super sensitive to electronics inputs. Ie being pulled low. Also the reason why u can't leave this pin not pulled in a single direction or it'll float. Even touching it with your finger will throw the pin high/low.

Not for you Bobnova, for everyone else
 
I am gonna have to play around with my qfr's later with the arduino. Ordered a smaller qfr today aswell, 150cfm and am probably gonna pickup a few nidec beta V's off ebay this week. So it will give me a chance to see what i can up with.

What is this qfr u speak of, excuse my ignorance. Additionally, now I have this awful retarded urge to buy some sort of super fan of no other reason than...oOOoo it goes fast, but will never be used by I hate noise! Yet I still want one
 
Well... no wonder this thing ain't working properly...

I just ran the code above and this is what I got..

Code:
6432, 6420
15000000, 15000000
40650, 40650
15000000, 15000000
15000000, 15000000
15000000, 15000000
15000000, 15000000
6507, 6495
15000000, 15000000
44776, 44775
6404, 6390
44776, 44775
41899, 41895
15000000, 15000000
6396, 6390
15000000, 15000000
41666, 41655
44117, 44115
6402, 6390
6524, 6510
7500000, 7500000
43731, 43725
6393, 6390
44117, 44115
15000000, 15000000
15000000, 15000000
600000, 600000
44510, 44505
41208, 41205
6510, 6510
15000000, 15000000
6487, 6480
789473, 789465
6465, 6465
6412, 6405
15000000, 15000000
39893, 39885
43227, 43215
6415, 6405
6510, 6510
40760, 40755
15000000, 15000000
40431, 40425
15000000, 15000000
15000000, 15000000
44117, 44115
40322, 40320
2500000, 2499990
6382, 6375
6507, 6495
40650, 40650
15000000, 15000000
6423, 6420
6496, 6495
15000000, 15000000
6490, 6480
15000000, 15000000
43859, 43845
41208, 41205
15000000, 15000000
6415, 6405
44247, 44235
15000000, 15000000
45317, 45315
15000000, 15000000
6521, 6510
7591, 7590
7637, 7635
7606, 7605
7618, 7605
6396, 6390
7500000, 7500000
40760, 40755
43859, 43845
15000000, 15000000
15000000, 15000000
41322, 41310
15000000, 15000000
41322, 41310
15000000, 15000000
15000000, 15000000
15000000, 15000000
6374, 6360
44247, 44235
41322, 41310
44247, 44235
2500000, 2499990
7500000, 7500000
40322, 40320
6485, 6480
3750000, 3750000
6496, 6495
2500000, 2499990
43731, 43725
39787, 39780
15000000, 15000000
15000000, 15000000
15000000, 15000000
41899, 41895
43604, 43590
600000, 600000
15000000, 15000000
 
I have tried the 3 different fanspaces for the three different dividers; I have tried changing the dividers; I have tried changing the "* 120" part of Calc.... Nothing gives me an accurate, reliable, consistent reading.


Circuit is just the LCD connected to the R3 and then the tach wire from teh fan straight to pin 2 on the R3. I had it with the pull up resistor, but since the code above uses the built in one; I removed it.


EDIT
Tried it on a more "conventional" PWM fan and it works fine... The only issue is that when the RPM readout on teh LCD goes from 4 characters to 3 (fan slows down below 1000 rpm) the 4th character remains ON and throws the whole thing off.

Oh by the way, I'm not sure if your doing this or not but don't change the fan divider array. If u alter that array you change the devisee per fan spec selection, idk if that makes sense

Only change the "char fan" = 0 or 1 or 2
 
Yup... I was playing with the char fan to get the different dividers...
The issue here is that for some reason whatever code I use; I always get those blips like you see in my previous post where the serial was reporting properly at around 6K rpm and then it jumps to 15M or 600K or 7.5M...
I tried wiht the internal pull up resistor for pin2 and also with external pull up resistor 10K Ohm. Same result.

Weird part is that if I pull the fan down to its slowest speed (10% duty cycle) the code works fine and reports between 980 and 1000 rpm constant... but change the duty cycle just one tick and the thing goes bonkers.

The problem has to be with teh way the Nidec sends out the pulses via the tach wire....

I just tested it with a normal PWM fan and this is what I got

Code:
1111, 1110
896, 885
740, 735
615, 615
518, 510
441, 435
394, 390
370, 360
357, 345
351, 345
354, 345

That's just a snapshot of what the reported RPMs were while I went from 100% to 0% duty cycle.
 
Last edited:
Back