Reading RPm from 3 wire fan.

Greetings guys.

I need help reading RPM from a 3 wire 12v 1.3a fan.

the problem is that I get my Rpm reading at constant 0.

Here lies my code.

int potPin = 0;                           // Analog pin 0 connected to the potentiometer
const int transistorPin = 9;                  // connected from digital pin 9 to the base of the transistor
int potValue = 0;                       // value returned from the potentiometer
int NbTopsFan; int Calc;              //variables used for calculations

//The pin location of the sensor
int hallsensor = 2; typedef struct {

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

//Definitions of the fans
//This is the variable used to select the fan and it's divider
//set 1 for unipole hall effect sensor
// and 2 for bipole hall effect sensor
fanspec fanspace [3] = {{0, 1}, {1, 2}, {2, 8}}; char fan = 1;

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() {                          // set  the transistor pin as an output

  pinMode(transistorPin, OUTPUT);
  pinMode(hallsensor, INPUT);
  Serial.begin(9600);
  attachInterrupt(0, rpm, RISING);

}


void loop() {                           // read the potentiometer, convert it to between 0 - 255 for the value accepted by the digital pin.
  potValue = analogRead(potPin) / 4;    // potValue alters the supply from pin 9 which in turn controls the power running through the transistor
  analogWrite(9, potValue);
  NbTopsFan = 0;

  //Enables interrupts
  sei();

  //Wait 1 second
  delay(1000);

  //Disable interrupts
  cli();

  //Times NbTopsFan (which is approximately the frequency the fan
  //is spinning at) by 60 seconds before dividing by the fan's divider
  Calc = ((NbTopsFan * 60) / fanspace[fan].fandiv);

  //Prints the number calculated above
  Serial.print (Calc, DEC);

  //Prints "rpm" and a new line
  Serial.print(" rpm\r\n");

}

here's how i hook it up

Where did i go wrong? :confused:

pinMode(hallsensor, INPUT_PULLUP);

it's still displaying 0 man :confused:

Hi,
Your delay(1000) does just that, delays everything for a second.
In the IDE look for the "blink without delay" sketch, it will show you how to delay and still have the controller carrying out its program.

Tom... :slight_smile:

int potPin = 0;                           // Analog pin 0 connected to the potentiometer
const int transistorPin = 9;                  // connected from digital pin 9 to the base of the transistor
int potValue = 0;                       // value returned from the potentiometer
int NbTopsFan; int Calc;              //variables used for calculations

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
const long interval = 500;           // interval at which to blink (milliseconds)

//The pin location of the sensor
int hallsensor = 2; typedef struct {

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

//Definitions of the fans
//This is the variable used to select the fan and it's divider
//set 1 for unipole hall effect sensor
// and 2 for bipole hall effect sensor
fanspec fanspace [3] = {{0, 1}, {1, 2}, {2, 8}}; char fan = 1;

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() {                          // set  the transistor pin as an output

  pinMode(transistorPin, OUTPUT);
  pinMode(hallsensor, INPUT_PULLUP);
  Serial.begin(9600);
  attachInterrupt(0, rpm, RISING);

}


void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;


    // read the potentiometer, convert it to between 0 - 255 for the value accepted by the digital pin.
    potValue = analogRead(potPin) / 4;    // potValue alters the supply from pin 9 which in turn controls the power running through the transistor
    analogWrite(9, potValue);
    NbTopsFan = 0;

    //Enables interrupts
    sei();

    //Wait 1 second
    //delay(1000);

    //Disable interrupts
    cli();

    //Times NbTopsFan (which is approximately the frequency the fan
    //is spinning at) by 60 seconds before dividing by the fan's divider
    Calc = ((NbTopsFan * 60) / fanspace[fan].fandiv);

    //Prints the number calculated above
    Serial.print (Calc, DEC);

    //Prints "rpm" and a new line
    Serial.print(" rpm\r\n");
  }
}

Hi Tom..

I've changed it and now it displays only one but still at 0.

Just had a better look at your Fritzing diagram.
AFAIK, you can't PWM a 3-pin fan by switching the ground/negative with a NPN transistor or N-channel fet and read the hall sensor at the same time, because ground is also used by the hall sensor.
Therefore you have to use 2-transistor high-side switching.

To test the RPM part of your program, connect fan positive to supply, fan negative to ground, and the yellow (or white) hall wire to the digital input with pull-up enabled.
RPM should work this way.
Then think about speed control.

Back EMF diodes go across the fan, not across the transistor.
Leo