Friday, June 14, 2013

Measure RPMs Arduino



Video




Schematic





The Fan



Code

Download RPM.ino
// read RPM

volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;

void setup(){
 Serial.begin(9600); 
 attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
}

void loop(){
 
 if (millis() - lastmillis == 1000){  /*Uptade every one second, this will be equal to reading frecuency (Hz).*/
 
 detachInterrupt(0);    //Disable interrupt when calculating
 
 
 rpm = rpmcount * 60;  /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
 
 Serial.print("RPM =\t"); //print the word "RPM" and tab.
 Serial.print(rpm); // print the rpm value.
 Serial.print("\t Hz=\t"); //print the word "Hz".
 Serial.println(rpmcount); /*print revolutions per second or Hz. And print new line or enter.*/
 
 rpmcount = 0; // Restart the RPM counter
 lastmillis = millis(); // Uptade lasmillis
 attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
  }
}


void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmcount++;
}


// Elimelec Lopez - April 25th 2013

Code v2 (Calculate Average)
Download RPM_V2.ino

// read RPM and calculate average every then readings.
const int numreadings = 10;
int readings[numreadings];
unsigned long average = 0;
int index = 0;
unsigned long total; 

volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile 
unsigned long rpm = 0;
unsigned long lastmillis = 0;

void setup(){
 Serial.begin(9600); 
 attachInterrupt(0, rpm_fan, FALLING);
}

void loop(){
 
  
 if (millis() - lastmillis >= 1000){  /*Uptade every one second, this will be equal to reading frecuency (Hz).*/
 
 detachInterrupt(0);    //Disable interrupt when calculating
 total = 0;  
 readings[index] = rpmcount * 60;  /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/
 
 for (int x=0; x<=9; x++){
   total = total + readings[x];
 }
 
 average = total / numreadings;
 rpm = average;
 
 rpmcount = 0; // Restart the RPM counter
 index++;
 if(index >= numreadings){
  index=0; 
 } 
 
 
if (millis() > 11000){  // wait for RPMs average to get stable

 Serial.print(" RPM = ");
 Serial.println(rpm);
}
 
 lastmillis = millis(); // Uptade lasmillis
  attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
  }
}


void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
  rpmcount++;
}








18 comments:

  1. rpmcount should be volatile see: http://arduino.cc/en/Reference/Volatile.

    ReplyDelete
  2. O.K

    Thank you very much, I changed the code.

    ReplyDelete
  3. What is the pair of IR led and diode you are using, can you provide a datasheet or link from where to buy them?
    Are they suitable for a distance of about 5 inch?
    Does this work of low rpm (approx 100rpm) ?
    Thanks :)

    ReplyDelete
  4. Hello,

    I'm using an IR photodiode and an standard IR transmiter. You can use any IR receiver and transmiter.

    Of course, it will work with low RPM. I'm not sure about the distance, but you can try or use an IR laser instead.

    Elimeléc

    ReplyDelete
  5. Here is the datasheet of the Photodiode:

    https://www.dropbox.com/s/kw0pl4yfdj2eb99/Photo_diode_S186p.pdf


    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. sketch_jan14a.ino: In function 'void setup()':
    sketch_jan14a:12: error: 'rpm_fan' was not declared in this scope
    sketch_jan14a.ino: In function 'void loop()':
    sketch_jan14a:26: error: 'rpm_fan' was not declared in this scope

    getting these errors

    ReplyDelete
  8. Hello, Nitin

    The problem was in the comments, now you should be able to copy and paste. I also added the link to download the .INO file directly.

    Elimelec

    ReplyDelete
  9. amigo felicitaciones ahora mi pregunta es si con esto puedo hacer que mida las revoluciones de la velocodad de mi carro y con esto ver si en un segundo han cambiado osea han aumentado y activar o desactivar algo , saludos y graci spor su ayuda

    ReplyDelete
  10. amigo no se que paso se cambio lo que escribi , quiero implementar este codigo para que en sobrepase un determinado numero de revoluciones me active o desactive alguna cosa se podra hacer me podria ayudar gracias

    ReplyDelete
  11. Thanks for the response Elimelec. I am having issues with my project. Your code is not reading any input from the sensor. I dont see any analogread() for it to read the sensor. Where is it printing the results???? I think this is not the full code. Is there any way i can get the full code??? That will be really helpful

    ReplyDelete
  12. Hola, Nicola

    Por supuesto que puedes hacer lo que deseas.

    Elimelec

    ReplyDelete
  13. Hello, Nitin

    The code does not read any analog input, just a digital one and the result is printed over the serial port.

    Elimelec

    ReplyDelete
  14. i am new in programming so i have alot of questions and i tried alot of sources before asking questions in this thread. How are you reading/ which digital pin are you using. According to my knowledge, i dont see any digitalread()/write in the code. Moreover, where can see this printed serial port data.
    thanks and regards

    ReplyDelete
  15. Hello, Nitin

    The reason you don't see the digitalRead function it's because we are using interrupts, the digital pin two (2) it's used as shown in the schematic. Please visit the following links to help you out:

    http://arduino.cc/en/Reference/attachInterrupt

    http://playground.arduino.cc/Code/Interrupts

    http://www.jeremyblum.com/2011/03/07/arduino-tutorial-10-interrupts-and-hardware-debouncing/

    http://www.ladyada.net/learn/arduino/lesson4.html

    http://www.gammon.com.au/forum/?id=11473


    Elimeléc

    ReplyDelete
  16. I am using this code for an RPM-display on an outboard-motor that contains a much larger setup-function, plus a Power On Self test.
    This results in the fact that millis is way over 10000 when the loop starts. As the loop is only called when millis - lastmillis equals a value, the arduino does nothing.
    I suggest to use a ">= value" expression, to avoid this problem.

    ReplyDelete
  17. can i apply this code for motor dc?? so i can get the rpm of motor dc??
    please reply, i really need help, thank you

    ReplyDelete
  18. Yes, the motor in the video it's DC.

    ReplyDelete