PulseIn para RPM ?

:cold_sweat:

Viva!

Com arduino consigo facilmente contar as voltas de uma ventoinha..:

Através do código disponível em Arduino Playground - ReadingRPM, e da função "attachInterrupt" tenho um valor de 4200 RPM

No entanto, eu quero usar a função PulseIn() uma vez que a nível de "attachInterrupt" apenas posso usar 2 pinos (2 ventoinhas) e queria obter a info de RPM de mais ventoínhas..

Estou a utilizar este código:

int pin = 7;
unsigned long duration;

void setup()
{
  Serial.begin(9600); // Inicializa a comunicação serial
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
}

funciona bem, a única diferença é que retorna o valor de 3600, como a função PulseIn() retorna micro-segundos.. alguém sabe como chegar aos 4200 RPM da função "attachInterrupt", pois deverá ser este o valor real.. e não os 3600, tenho de converter como?

Opz, bele?

Onde acho a biblioteca do arduino duemilanove pro Proteus?
Esta que vc usou ai no seu desenho!
Pode disponibilizar aki , ou um link pra download?

:roll_eyes:

nao entendi,
vc esta tentando usar a funcao pulsein para medidir os pulsos gerados pelo giro da ventoninha?
note que a funcao pulsein retorna o tempo de um pulso, a largura de um pulso que pode HIGH ou LOW. Voce nao consegue contar pulsos com ela.

Radames:
nao entendi,
vc esta tentando usar a funcao pulsein para medidir os pulsos gerados pelo giro da ventoninha?
note que a funcao pulsein retorna o tempo de um pulso, a largura de um pulso que pode HIGH ou LOW. Voce nao consegue contar pulsos com ela.

Olá,

Sim a função pulsein devolve micro-segundos, conseguimos converter para Hz e depois para rpm? ou algo assim..?

Com esta função consigo saber se a ventoinha está parada ou a rodar e era mesmo excelente se conseguisse calcular +/- a velocidade a que está a trabalhar...

entao,
definitivamente vc nao esta utilizando a forma correta!
o pulseIN faz isto

http://www.arduino.cc/en/Reference/PulseIn

the length of the pulse (in microseconds) or 0 if no pulse started before the timeout (unsigned long)

ele te retorna a largura de um pulso em microsegundos!

para vc contar múltiplas ventoinhas precisa fazer um tachometer para múltiplas entradas, procure este chip LM2907 , ele converte frequência, para voltagem, assim vc pode ler sem acrescentar mais nada 6 ventoninhas utilizando 6 portas analógicas.

Radames:
entao,
definitivamente vc nao esta utilizando a forma correta!
o pulseIN faz isto

http://www.arduino.cc/en/Reference/PulseIn

the length of the pulse (in microseconds) or 0 if no pulse started before the timeout (unsigned long)

ele te retorna a largura de um pulso em microsegundos!

para vc contar múltiplas ventoinhas precisa fazer um tachometer para múltiplas entradas, procure este chip LM2907 , ele converte frequência, para voltagem, assim vc pode ler sem acrescentar mais nada 6 ventoninhas utilizando 6 portas analógicas.

XD :blush: ups!

Vou procurar alguma informação então de circuitos do LM2907 com o arduino :slight_smile:

Obrigado pela resposta!

post os resultados aqui!!! até

Bom.. toda a informação que encontro está associada para carros.. no datasheet do chip o exemplo que mais se adapta será este:

Em vez daqueles 2 fios no "Magnetic Pickup" secalhar dá para meter apenas o fio amarelo vindo da Fan.. a nível de Vout é que não deve dar para ligar directamente a um pino analógico do arduino.. tem de se ver o que sai dali

veja o datasheet
http://www.national.com/profile/snip.cgi/openDS=LM2907
tem mais application examples.

mas da para medir sim, a ventoinha tem um sensor hall!

Usa PCINT's

Mas o pulsein tenho quase a certeza que funciona, isso é onda quadrada, se só te dá meia onda multiplicas o tempo por dois.

Sim.. mas alguma ideia do que tenho de alterar ou qual o cálculo a adicionar?

Se utilizar o método do attachInterrupt tenho 4200 Rpm´s, usando o pulsein ele dá-me 3600

attachInterrupt:

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

Pulsein:

int pin = 7;
unsigned long duration;

void setup()
{
  Serial.begin(9600); // Inicializa a comunicação serial
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
}

Sim, almamater e é simples.

O resultado da função pulseIn, como você já sabe, nos dá a largura do pulso capturado pela entrada em microsegundos. Acompanhe:

pulseIn = 3600 microsegundos;

x 2 (um ciclo) = 7200us;

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

x 60 (1 minuto) = 8280rpm;

/ 2 (ventilador com dois pulsos por volta) = 4140rpm.

Só funciona se o duty cycle for de 50%.

Boa sorte!

:%

Muito obrigado pela explicação!! mesmo!

Bem.. testei fazer o seguinte:

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

Resultado:


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


Assim parece estar Ok! mas vou testar ainda mas só amanhã que agora tenho de ir dormir..

Tenho uma situação, colocando apenas o código para obter o valor pulsein funciona bem:

void loop()  { 
  Serial.println("-----FAN1");

  duration = pulseIn(pin1, HIGH);
  duration2=(duration*2);
  duration2=(1/duration2);
  duration2=(duration2*1000);
  duration2=(duration2*1000);
   duration=(duration2*60/2);

  Serial.println(duration);
}

Se colocar código associado a outras coisas já se atrofia todo.. exemplo:

void loop()  { 
  Serial.println("-----FAN1");

  duration = pulseIn(pin1, HIGH);
  duration2=(duration*2);
  duration2=(1/duration2);
  duration2=(duration2*1000);
  duration2=(duration2*1000);
  duration=(duration2*60/2);

  Serial.println(duration);

//Temperatura:
sensors.requestTemperatures(); 
Serial.print("Temperature for Device 1 is: ");
temperature=(sensors.getTempCByIndex(0));
Serial.println(temperature);
Serial.print("Temperature for Device 2 is: ");
temperature=(sensors.getTempCByIndex(1));
Serial.println(temperature);
}

Fico com valores de 18032 em vez de 3050

Para obter os valores correctos de RPM tenho de executar o código pilsein sozinho?

Possa... é muito complicado obter valores certos, usando simplesmente este código:

int pin = 7;
unsigned long duration;

void setup()
{
  Serial.begin(9600); // Inicializa a comunicação serial
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
}

Tenho valores completamente diferentes consoante as ventoinhas, com uma bastante potente de 80mm tenho 3600 de resultado, com uma ventoinha de 120mm já tenho 15084.

Pensei que fosse por ser de 120mm, mas testei uma outra de 80mm e tenho os mesmo valores ~14033..

Usando o attachInterrupt os valores batem sempre certo independentemente do tipo de ventoinha.. tem a ver com o tipo de hall effect sensor ?

almamater:
...
Tenho valores completamente diferentes consoante as ventoinhas, com uma bastante potente de 80mm tenho 3600 de resultado, com uma ventoinha de 120mm já tenho 15084.

Pensei que fosse por ser de 120mm, mas testei uma outra de 80mm e tenho os mesmo valores ~14033..
...

Quanto mais potente a ventoinha, mais rapido ela gira... e menos tempo ela demora para dar uma volta....
a ventoinha de 120mm é maior mas não mais rápida e daí o tempo maior...

Testa o código e veja se melhora

int pin = 7;
unsigned long duration;
float resultado;
void setup()
{
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  resultado = ( 1000000.0 / float(duration) ) * 60.0;
  Serial.println(resultado);

}

fabiohbm007:
Testa o código e veja se melhora

int pin = 7;

unsigned long duration;
float resultado;
void setup()
{
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  resultado = ( 1000000.0 / float(duration) ) * 60.0;
  Serial.println(resultado);

}

Fábio,

Assim não fica impossível de ler no serial monitor ? Ele irá printar valores alguns milhares de vez por segundo, não ? :stuck_out_tongue:

Ainda não testei o código do Fábio, e desde já agradeço as vossas respostas.

O meu objectivo é implementar um ATMega168 num sistema de refrigeração com 4 ventoinhas, para além de controlar as mesmas queria apresentar/obter a rotação +/- real de cada uma.

Será que existe alguma outra forma (outro controlador/chip) que possa utilizar para esta parte do projecto? em que seja mais fácil? já pesquisei muito na web mas acabo sempre por concluir que com o arduino é mais simples.. mas não sei se existem controladores específicos para ler as rpm´s das ventoinhas

Alguma ideia de como posso saber se a ventoinha está parada ou não?

Usando este código:

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