Fan RPM

Circuito muito simples que nos permite obter a velocidade de uma ventoinha através do fio amarelo:

 

Este projecto está disponível na página oficial do Arduino: http://www.arduino.cc/playground/Main/ReadingRPM

Esquema que fiz e utilizei:

A ventoinha liga a uma fonte de 12V e o fio amarelo liga ao pino 2 (pino digital), temos de ligar o Ground da fonte de 12V ao Ground do Arduino.

A leitura é feita com base nos 'Interrupts' do Arduino, que tem 2 (por defeito) externos e neste caso é usado o do pino 2 (attachInterrupt(0, rpm_fun, RISING);). 

Os códigos utilizados podem ser:

//-----------------------------------------------

 volatile byte rpmcount;

 unsigned int rpm;

 unsigned long timeold;

 void setup()

 {

   Serial.begin(9600);

   attachInterrupt(0, rpm_fun, RISING);

   rpmcount = 0;

   rpm = 0;

   timeold = 0;

 }

 void loop()

 {

   if (rpmcount >= 20) { 

     //Update RPM every 20 counts, increase this for better RPM resolution,

     //decrease for faster update

     rpm = 30*1000/(millis() - timeold)*rpmcount;

     timeold = millis();

     rpmcount = 0;

     Serial.println(rpm,DEC);

   }

 }

 void rpm_fun()

 {

   rpmcount++;

   //Each rotation, this interrupt function is run twice

 }

//-----------------------------------------------

Código do projecto da página oficial

ou

//code by Crenn from http://thebestcasescenario.com

//project by Charles Gantt from http://themakersworkbench.com

/*To disable interrupts:

 cli();                // disable global interrupts

and to enable them:  

 sei();                // enable interrupts

*/

                                   //Varibles used for calculations

int NbTopsFan; 

int Calc;

                                  //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

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

 Serial.begin(9600); 

 attachInterrupt(0, rpm, RISING); 

void loop () 

{

   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\n"); //Prints " rpm" and a new line

}

Update:

Como apenas temos 2 pinos disponíveis para utilizar a função "attachInterrupt", apenas podemos utilizar 2 ventoinhas. Como alternativa, e para utilizarmos mais ventoinhas, podemos recorrer à função "pulseIn". A ventoinha devolve uma onda quadrada, se usarmos a função pulseIn temos a frequência dessa onda, se temos a frequência temos assim a rotação da ventoinha.

 O resultado da função pulseIn dá-nos a largura do pulso capturado pela entrada em microsegundos. Por exemplo, se tivermos o resultado de "3600":

pulseIn = 3600 microsegundos;

multiplicamos por 2 (um ciclo) = 7200us;

invertemos: 1/7200 = 0,138888kHz = 138Hz;

multiplicamos por 60 (1 minuto) = 8280rpm;

dividimos por 2 (ventoinha com dois pulsos por volta) = 4140rpm.

(Para um 'duty cycle' de 50%)

Testei com o sensor da ventoinha ligado ao pino 8 do Arduino e com o seguinte código:

int pin = 8;

unsigned long duration;

float duration2;

void setup()

{

  Serial.begin(9600); // Inicializa a comunicação serial

  pinMode(pin, INPUT);

}

void loop()

{

  Serial.println("-----");

  duration = pulseIn(pin, HIGH);

  Serial.println(duration);

  duration2=(duration*2);

  Serial.println(duration2);

  duration2=(1/duration2);

  duration2=(duration2*1000);

  duration2=(duration2*1000);

  Serial.println(duration2);

  duration=(duration2*60/2);

  Serial.println(duration);

}

Exemplo do resultado obtido:

-----

3622      -> Valor lido no pulsein

7244.00   -> multiplicado por 2

138.05    -> não sei se é bem isto mas ao resultado de 1/7244 multipliquei depois 2x por 1000

4141      -> Resultado RPM

-----

3628

7256.00

137.82

4134

-----

3623

7246.00

138.01

4140

-----

3628

7256.00

137.82

4134

-----

3622

7244.00

138.05

4141

Os valores ficam assim próximos dos obtidos pela função "attachInterrupt".