I have a circuit which controls the fan speed based on the amount of light in the room. The fan I'm using is a 3pin fan, the yellow wire is the reporting one. My code is able to read the RPM of the fan when I set the PWM pin to either 0 or 255. Ex:
analogWrite(transistor,0); //RPM 0
analogWrite(transistor,255); // RPM around 900
however, say I were to write
analogWrite(transistor,123); //roughly half the speed
the RPM would not be accurate, and would be very far off.
Here's the code I'm currently using:
/*To disable interrupts:
cli(); // disable global interrupts
and to enable them:
sei(); // enable interrupts
*/
//Varibles used for calculations
int NbTopsFan;
int Calc;
int ldr; //Light sensor
//Pin Locations
int OnGreenLed = 4;
int OffRedLed = 7;
int SpeedOrangeLed = 11;
int buttonPin = 8; //For Button
int transistor = 9;
int currentState = LOW;
int hallsensor = 2;
//int ldr = 0;
// ldr = analogRead(0)/4;
typedef struct{ //Defines the structure for multiple fans and their dividers
char fantype;
unsigned int fandiv;
}fanspec;
//Definitions of the fans
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan = 1; //This is the varible used to select the fan and it's divider, set 1 for unipole hall effect sensor
//and 2 for bipole hall effect sensor
void rpm () //This is the function that the interupt calls
{
NbTopsFan++;
}
//This is the setup function where the serial port is initialised,and the interrupt is attached
void setup()
{
pinMode (hallsensor, INPUT);
pinMode(OffRedLed,OUTPUT);
pinMode(OnGreenLed,OUTPUT);
pinMode(SpeedOrangeLed,OUTPUT);
pinMode(buttonPin, INPUT);
Serial.begin(9600);
attachInterrupt(0, rpm, RISING);
setPwmFrequency(9,1); //to remove the high frequency sound when fan is being pwm controlled
}
void loop ()
{
// read the state of the pushbutton value:
ldr = analogRead(A1);
currentState = digitalRead(buttonPin);
if(currentState == HIGH){
digitalWrite(OffRedLed, LOW);
digitalWrite(OnGreenLed, HIGH);
analogWrite(SpeedOrangeLed,ldr/4);
// delay(10);
analogWrite(transistor,ldr/4);
}
else{
// turn LED off:
digitalWrite(OffRedLed, HIGH);
digitalWrite(OnGreenLed, LOW);
digitalWrite(SpeedOrangeLed,LOW);
analogWrite(transistor,0);
}
NbTopsFan = 0; //Set NbTops to 0 ready for calculations
sei(); //Enables interrupts
delay (1000); //Wait 1 second
cli(); //Disable interrupts
Calc = ((NbTopsFan * 60)/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 Button State: "); //Prints " rpm" and a new line
Serial.print(currentState);
Serial.print(" ldr reading = ");
Serial.print(ldr);
Serial.print("\n");
}
void setPwmFrequency(int pin, int divisor) {
byte mode;
if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 64: mode = 0x03; break;
case 256: mode = 0x04; break;
case 1024: mode = 0x05; break;
default: return;
}
if(pin == 5 || pin == 6) {
TCCR0B = TCCR0B & 0b11111000 | mode;
} else {
TCCR1B = TCCR1B & 0b11111000 | mode;
}
} else if(pin == 3 || pin == 11) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 32: mode = 0x03; break;
case 64: mode = 0x04; break;
case 128: mode = 0x05; break;
case 256: mode = 0x06; break;
case 1024: mode = 0x7; break;
default: return;
}
TCCR2B = TCCR2B & 0b11111000 | mode;
}
}
is the tutorial I followed on how to read the RPM.
Any suggestions?