I'm working on a project that will test PC cooling fans - both 3-pin non PWM type and 4-pin PWM type. It will adjust 3-pin types via voltage and 4-pin via PWM obviously. It will display fan RPM, PWM% and Voltage on the LCD. It works perfectly (still need to add the voltage part of the code) with 3-pin fans but on most PWM fans the RPM reads way too high (like 9k+ RPM) if the PWM is anything but 0 or 100. The only PWM fans I've found that work correctly are the stock Intel CPU heat sink fans. Those read correctly no matter the PWM setting. Any thoughts as to what could be causing it?
Here's the code so far (still need to add the voltage reading portion of it):
// Code for PC fan testing unit
// By Will Lyon - http://www.computersandcircuits.com
#include <LiquidCrystal.h>
LiquidCrystal lcd(4, 5, 6, 7, 8, 9);
volatile int NbTopsFan;
int Calc;
const int fan1 = 2;
const int PotPin = A0;
const int pwmPin = 10;
const int voltPin = A2;
int fanPwm;
int val;
int pwm;
typedef struct{
char fantype;
unsigned int fandiv;
}fanspec;
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan = 1;
void rpm ()
{
NbTopsFan++;
}
void setup() {
pinMode(fan1, INPUT);
pinMode(PotPin, INPUT);
pinMode(voltPin, INPUT);
attachInterrupt(0, rpm, RISING);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print(" Computers And ");
lcd.setCursor(0, 1);
lcd.print(" Circuits ");
delay(2000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Computer Fan ");
lcd.setCursor(0, 1);
lcd.print(" Testing Unit ");
delay(2000);
lcd.clear();
}
void loop() {
NbTopsFan = 0;
sei();
delay (1000);
cli();
Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);
lcd.setCursor(0, 0);
lcd.print ("RPM");
lcd.setCursor(5, 0);
lcd.print ("PWM%");
lcd.setCursor(12, 0);
lcd.print ("Volt");
lcd.setCursor(0, 1);
if (Calc < 1000) lcd.print (' ');
if (Calc < 100) lcd.print (' ');
if (Calc < 10) lcd.print (' ');
lcd.print (Calc);
lcd.setCursor(4, 1);
lcd.print (" ");
pwm = analogRead(0);
fanPwm = map(pwm, 0, 1023, 0, 255);
analogWrite(pwmPin, fanPwm);
val = map(fanPwm, 0, 255, 0, 100);
lcd.setCursor(5, 1);
if (val < 100) lcd.print (' ');
if (val < 10) lcd.print (' ');
lcd.print(val);
}