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".