Introduction: Infrared Tachometer Using Arduino

Hi, this is just another tachometer as you can also find many tutorials out there. There are different approaches on measuring rpm, what I use here is based on analogRead method as written in arduino playground learning page (http://playground.arduino.cc/Learning/Tachometer) but with some modification on calculation method of rotational frequency. The code in arduino playground is very good and understandable but there are some spaces for improvement. Because it reads the number of "change in state" over specific time frame, it may lose accuracy when we try to make fast reading on slow revolution speed.

This is my first post in instructables, any feedback is welcome! :)

Step 1: Components

1. Arduino Duemilanove

2. IR LED BM1331

3. IR Phototransistor BPT1331

4. Resistor 10k Ohm

5. Resistor 150 Ohm

6. Cables, pin sockets, perfboard

7. Motor & Wheel Assy : This is not the main interest in this project, basically any arrangement that provides a wheel with adjustable speed will do. Here I used a styrofoam disk driven by a used walkman motor connected to an AC/DC adaptor through a potentiometer. Clamps, base, etc are just from the backyard. The only important thing is to make window on the wheel such that the IR LED & phototransistor can see each other sometimes while the wheel is turning.

Step 2: Assemble Parts and Make Connections

1. Put the IR LED and Receiver facing to each other in a position that make them can see each other occasionally through the window on the wheel. Better to make them not to far apart.

2. Create the shield (saying shield is somewhat fancy, actually only a circuit of limiting resistors *lol*), see the diagram.

3. Hook up with your arduino: connect the IR receiver to analog pin A0, see the diagram. Notice that the IR LED BM1331 and IR Phototransistor BPT1331 look alike, with two legs and clear head so make sure you are not mixing them. Connect the longer leg of LED to positive side of circuit (right after 150 resistor), but the longer leg of phototransistor should be connected to negative side of circuit (goes to the GND).

4. Hook up your motor (to drive the wheel), here i use external power supply to make it simple. Remember if you want to use a motor powered from the arduino board make sure you know exactly what you are doing, because you cannot draw a lot of current as for a motor through your board, you will overload her. Play safe, or use a motor shield.

Step 3: Write the Code

The code is pretty much similar to the one here: http://playground.arduino.cc/Learning/Tachometer, in fact i wrote based on that code. Only instead of counting how many times the sensors are saying hi to each other every certain period, I count how long until they can see the other again after the last meeting. Also, I find that using micros(), that returns microcontroller time in microseconds, gives a significantly more accurate result than if i used millis() on the same place.

Here is the code:

int sensorvalue;
int state1 = HIGH;
int state2;
float rps;
float rpm;
long prevMillis = 0;
long interval = 200;
long currentTime;
long prevTime = 1;
long diffTime;
int sensorthreshold = 30;  
// this value indicates the limit reading between dark and light,
// it has to be tested as it may change acording to the 
// distance the leds are placed.
// to see what number is good, check the sensorvalue variable value
// as printed out in the serial monitor


void setup()
{
  Serial.begin(9600);
  pinMode(13,OUTPUT);      // assign pin 13 led as indicator because we cannot se the IR light
}
void loop()
{
  sensorvalue = analogRead(0); // read from pin 0
  if(sensorvalue < sensorthreshold)
    state1 = HIGH;
   else
    state1 = LOW;
   digitalWrite(13,state1);   // as iR light is invisible for us, the led on pin 13 
                              // indicate the state of the circuit.

   if(state2!=state1){      //counts when the state change, thats from (dark to light) or 
                            //from (light to dark), remember that IR light is invisible to us.
     if (state2>state1){
       currentTime = micros();   // Get the arduino time in microseconds
       diffTime = currentTime - prevTime;  // calculate the time diff from the last meet-up
       rps = 1000000/diffTime;   // calculate how many rev per second, good to know
       rpm = 60000000/diffTime;  // calculate how many rev per minute
       
       unsigned long currentMillis = millis();
       
       // print to serial at every interval - defined at the variables declaration
       if(currentMillis - prevMillis > interval){ // see if now already an interval long
       prevMillis = currentMillis;       
       Serial.print(rps); Serial.print(" rps  "); Serial.print(rpm); Serial.println(" rpm");
       }
       
       prevTime = currentTime;
     }
     state2 = state1;
   }

 /* 
 //only for testing to determine the sensorthreshold value
 delay(500);
 Serial.println(sensorvalue);
 */
}

Tricky thing was on defining the sensorthreshold value. I did this: comment the main routine, and uncomment the testing section as seen in the codes below. That way arduino will write to serial monitor and update the sensor value in your screen every 500 ms. Compile and upload your code to your board, then open the serial monitor. Turn and stop the wheel so that the sensors are blocked and look what number appears in the serial monitor (in my case around 37-40), then turn and stop where the sensors can see each other through the window and look what number in the screen now (in my case 14-19). Then set a number as sensorthreshold variable value that you now know what is a good number to distinguish between "see" or "do not see" (I set 30 in my case, because my "do not see" is 37-40 and "see" is 14-19, setting between 20-36 can do the same function also, but not really safe because the value may sometimes be 35 or 21 due to interference from environment lights, in the electrical connections, or other things that I honestly do not really understand about). So, for short, check the number when the IR sensors see each other, and check it when the sensors are blocked, then find a good number in between that you are sure it will distinguish between "see" and "do not see".

Below is the code modification for checking the good number for sensorthreshold variable:

...
void loop()
{
  sensorvalue = analogRead(0); // read from pin 0
  /*
   if(sensorvalue < sensorthreshold)
    ...
   state2 = state1;
   }
*/

// only for testing to determine the sensorthreshold value
 delay(500);
 Serial.println(sensorvalue);
 }

Step 4: Serial Monitor Readings

The program writes the rev per second and rev per minute to the Arduino IDE serial monitor.

Of course this project is very rough and simple, but can be a part of further development. I will come again once I have something else. See you later...