• 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.
Seebs the nidec probably needs a filter on the PWM output. They're often horrendously noisy.
Bing laid out a 555 circuit for PWM stuffs.
You could try a 0.1uf cap between the tach pin and ground too though.

lol Actually I doubt it has anything to do with the PWM signal itself. To torque instantaneously from 900-3000 rpm would produce a very obvious speeding up and slowing down and it sounds like thats not happening:

"The fan is spinning at ~1000 rpm at the moment and the sketch is just not showing any kind of consistent RPM reading"

He proly not talking about the actual motor speed fluctuating, just the RPM reading...

If that's the case... I'm 95% sure the fan and the Arduino, which I'm assuming is taking the RPM readings, are not sharing a common ground...hence the well known "floating effect" error. Floating signals are bad, this is the same reason you need Pulldown/Pullup resistors
 
Maybe. There was a decent chunk of the PWM fan thread involved with filtering the output of high end fans so that mobo connectors didn't have wildly random tach readings.

I have a delta that crashes windows and prevents post when the tach line is plugged in :p

I have to leave right now, I'll scope the tach outputs when I get home (in 8 hours or so).
 
I can't get this damn thing to read properly...

@amora

1. Not sure what you mean by "It's last *".... I know you're referring to the RPM equation, but what about that last "*"? I've been Googleing for a different method all nite and a bit of this morning and I always end up with the same formula.

2. The common ground was it. I have added a wire running from the GND wire that feeds the Fan to the GND pin on the Arduino and the RPM is now being read properly... It still goes crazy when I speed the fan up (RPM goes to 50K), but I thing that has to do with the formula more than anything else.

@ Ed

I added the 0.1uF cap between the tach line and GND and it does help...

Fan is spinning at ~1000 rpm now and LCD is fluctuating between 1000 and 1020... So close enough, but the "high side" is what doesn't work yet.... LCD jumps to over 50K if I ramp the Fan up.


EDIT1: I found a place that shows the RPM formula with a "/" instead of a "*" at the end.... I thought that was it, but once I change that; the LCD outputs "2" and that's it. :shrug:

EDIT2: This damn thing is buggy as hell... I figured out why the LCD shows 50K+ when I ramp up the speed of the fan... The formula spits out a 10K reading before it settles down to the normal speed and that last 0 at the end stays "ON" even after the RPM levels down to the 6K level that the fan produces.
 
Last edited:
See if you can find the 555 tach filter Bing posted, I'd put good money that's your issue.

You could also try taking the road less traveled and using pulseIn to get a time between pulses in microseconds.
 
I have a delta that crashes windows and prevents post when the tach line is plugged in :p

I have to leave right now, I'll scope the tach outputs when I get home (in 8 hours or so).

That doesn't sound right the RPM wire pulls the sense pin low. Is that delta wire outputting voltage?
 
I can't get this damn thing to read properly...

@amora

1. Not sure what you mean by "It's last *".... I know you're referring to the RPM equation, but what about that last "*"? I've been Googleing for a different method all nite and a bit of this morning and I always end up with the same formula.

2. The common ground was it. I have added a wire running from the GND wire that feeds the Fan to the GND pin on the Arduino and the RPM is now being read properly... It still goes crazy when I speed the fan up (RPM goes to 50K), but I thing that has to do with the formula more than anything else.

@ Ed

I added the 0.1uF cap between the tach line and GND and it does help...

Fan is spinning at ~1000 rpm now and LCD is fluctuating between 1000 and 1020... So close enough, but the "high side" is what doesn't work yet.... LCD jumps to over 50K if I ramp the Fan up.

EDIT1: I found a place that shows the RPM formula with a "/" instead of a "*" at the end.... I thought that was it, but once I change that; the LCD outputs "2" and that's it. :shrug:

EDIT2: This damn thing is buggy as hell... I figured out why the LCD shows 50K+ when I ramp up the speed of the fan... The formula spits out a 10K reading before it settles down to the normal speed and that last 0 at the end stays "ON" even after the RPM levels down to the 6K level that the fan produces.

Opps That wasn't mean to be literal. It was meant to correct my grammar of the post above it. I was driving and didn't have time to "edit" so i posted new
 
S33bs you may want to start from scratch and write your own formula. Not because it would be better, but because if you conjure it up and write it down you're likely to understand every little bit of it rather than trying to figure out wtf is going on.
 
I can't get this damn thing to read properly...

Code:
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() {
    Serial.begin(9600);
   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
   Serial.print (Calc, DEC); //Prints the number calculated above
   Serial.print (" rpm\r\n"); //Prints " rpm" and a new line
 
  }
 
See if you can find the 555 tach filter Bing posted, I'd put good money that's your issue.

You could also try taking the road less traveled and using pulseIn to get a time between pulses in microseconds.

Ed...

I'm messing with the PulseIn() function and I almost got it to the point where it works. :D

Here's what i'm doing

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); 

// Declare variables
	int tachIn = 2;
	unsigned long duration;

void setup() {
// set up the LCD's number of columns and rows: 
	lcd.begin(16,2);
	pinMode(tachIn, INPUT);

}

void loop(){
	/* pulseIn() gets the time in microseconds that it takes the tach
	wire to send each pulse.
	Convert to seconds (* 1,000,000) and then
	to minutes (* 6)... The fan sends two pulses per revolution (*2)
	*/
	duration = 12000000 / pulseInt(tachIn, HIGH);

	lcd.setCursor(0,0);
	lcd.print("TEST");
	lcd.setCursor(0,1); 
	lcd.print(rpm,DEC);
  }
}

This thing works like a charm.... Except for one little thing... WHen I ramp up the fan it some times spits out a pulseIn() value that makes formula output something with 3 more zeroes (0) to the right... It then goes back to displaying the right RPM, but those three zeros remain on the screen.

I wonder if there is a way to limit the number of characters that lcd.print shows.
 
There should be a command to clear the screen. I set my stuff up to clear the screen every half second or second and start over.

Alternatively you could put an if/else just before the lcd.print and if the value it is about to print is too large (too many zeros!) skip that print cycle.
 
Ed...

I'm messing with the PulseIn() function and I almost got it to the point where it works. :D

Here's what i'm doing

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); 

// Declare variables
	int tachIn = 2;
	unsigned long duration;

void setup() {
// set up the LCD's number of columns and rows: 
	lcd.begin(16,2);
	pinMode(tachIn, INPUT);

}

void loop(){
	/* pulseIn() gets the time in microseconds that it takes the tach
	wire to send each pulse.
	Convert to seconds (* 1,000,000) and then
	to minutes (* 6)... The fan sends two pulses per revolution (*2)
	*/
	duration = 12000000 / pulseInt(tachIn, HIGH);

	lcd.setCursor(0,0);
	lcd.print("TEST");
	lcd.setCursor(0,1); 
	lcd.print(rpm,DEC);
  }
}

This thing works like a charm.... Except for one little thing... WHen I ramp up the fan it some times spits out a pulseIn() value that makes formula output something with 3 more zeroes (0) to the right... It then goes back to displaying the right RPM, but those three zeros remain on the screen.

I wonder if there is a way to limit the number of characters that lcd.print shows.

are you using an external pullup?
 
I think lcd.ClearScreen(); is the command, though its possible thats only the command for the Graphical lcd's. Some of the lcd librarys overlap, and some don't
 
Oh hey, you might want to use an unsigned long for the tachin, what variable type the arduino calculates with makes a rather large difference sometimes, and 12000000 doesn't fit into 65,500 very well.
If it's working it probably isn't an issue and it's more efficient as an int, but the atmega328 is woefully overpowered for what we're doing with it here. Kind of like one of our benching boxes playing Zork.
 
I guess no one else has noticed that the code CAN'T work "rpm" isn't' declared anywhere

Or maybe you're assuming its declared elsewhere...that code will not compile if and will throw a "not declared within this scope" error
 
I guess no one else has noticed that the code CAN'T work "rpm" isn't' declared anywhere

Or maybe you're assuming its declared elsewhere...that code will not compile if and will throw a "not declared within this scope" error

My bad... that last line of code should read
Code:
lcd.print(duration,DEC);

Instead of the rpm bit... I posted teh code before making that last change.

PS:

I think it's the pulseIn() part... It's not consistent within the range of speeds.

At 10% duty cycle I get 14780 (uS) sent in from the tach wire and if I raise it to 100% I get 2260 (uS) which makes sense since the fan is spinning faster and the time between pulses is shorter.... Problem is that once the duty cycle is changed the pulseIn() function goes bonkers and sarts outputting numbers that fluctuate too much for any accuracy to be possible.
 
My bad... that last line of code should read
Code:
lcd.print(duration,DEC);

Instead of the rpm bit... I posted teh code before making that last change.

PS:

I think it's the pulseIn() part... It's not consistent within the range of speeds.

At 10% duty cycle I get 14780 (uS) sent in from the tach wire and if I raise it to 100% I get 2260 (uS) which makes sense since the fan is spinning faster and the time between pulses is shorter.... Problem is that once the duty cycle is changed the pulseIn() function goes bonkers and sarts outputting numbers that fluctuate too much for any accuracy to be possible.

Thats why I use interrupts and set the delay to only update every 1/2 seconds. If you do on the fly updating things get screwy.
 
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);

}
 
Back