Introduction: Measure RPM - Optical Tachometer
This Instructable will show you how to make a Portable Digital Optical Tachometer using an Arduino Uno.
Instead of a slotted sensor , it has a reflection based sensor. So :
1. You don't have to worry about the thickness of the rotor
2. The number of blades won't change your readings
3. It can also read the RPM of drum style rotors which slotted sensor can't
What is a tachometer ?
A tachometer is a device used to measure the RPM or Revolutions Per Minute of any rotating body. Tachometers can be contact based or non-contact ones. The non-contact or contact-less optical tachometers usually use laser or Infrared beam to monitor the rotation of any body. This is done by calculating time taken for one rotation.
Attachments
Step 1: Part List :
Step 2: Build the Sensor
For the sensor you'll need an IR LED and a Photodiode.
1. Start by sanding the LED and photodiode to make it flat ( do not sand it too much or you'll destroy it ).
2. Then fold a strip of paper sheet as shown. Make two such Structures so that the LED and Photodiode fit tightly into it. Joint these together by glue and paint them black.
3. Insert your LED and Photodiode in them in such a way that the positive ( longer ) lead of the LED is right above the shorter lead of the photodiode.
4. Glue them into the cover using superglue and solder the positive ( longer ) lead of the LED to the shorter lead of the photodiode.
5. Solder the 3 wire ribbon cable to the remaining leads
In my case :
1. Orange wire --> LED's positive pin and photodiode's shorter lead
2. Yellow wire --> photodiode's longer lead
3. Green Wire --> LED's ground pin
You're ready to make the board >>
Step 3: Making the Sensor Board
Take a small piece of Perfboard and place the components according to the schematics.
The resistor values may vary depending on what kind of photodiode are you using.
The potentiometer helps in reducing or increasing the sensitivity of the sensor.
Finally solder the sensor wires as shown and solder 3 headers.
The headers ( in order ) are shown on the left side of the schematic.
make a cuboidal paper tube whose length is equal to the sensor wires.
Step 4: The 3-pin LCD
This method uses a 8-bit shift register 74HC595 with a 16 x 2 LCD. Normally this LCD uses 6 pins but using a shift register reduces the pin requirement by 3.
The full instruction guide and the library can be downloaded from THIS WEBSITE !
## Recent Update : The library provided on the website has a lot of errors and conflicts. I've uploaded my version of enhanced ShiftLCD library. I recommend you to use the one attached below.
The only thing that I've changed is :
instead of going for (2, 4, 3) configuration I've used (8, 10, 9)
So be sure to change the pin mapping accordingly
Attachments
Step 5: Make the Box
You can use any type of case for this but I've used a piece of cardboard to make enclosure.
Cut the cardboard as shown and cut appropriate sized slits for the USB port , power jack and the sensor board.
Mount the Arduino on the platform using screws.
Attach the sensor and push it through the hole.
Connect the LCD to Arduino as shown.
Close the box and paint.
Step 6: Finishing Touch
Make a small ( 5mm ) hole to fix the status LED. Solder a 270 ohm resistor to the LED and insert it into pin 12 on Arduino.
Fold the cardboard along the lines to complete the enclosure. Keep the folds in place by using pins.
Cover the sensor with a cubical paper tube to give additional mechanical strength.
Place the LCD module over the box.
Your device is ready for calibration and programming.
Step 7: Program
Step 8: Explanation and Calculation
This program basically monitors the IR sensor's value constantly and with the highest priority using Interrupts.
The Arduino Uno has 3 interrupts and the Interrupt 0 is pin 2 on the arduino.
attachInterrupt(0, RPMCount, RISING);
This line attaches an interrupt to pin 2 on arduino in "RISING" mode. This means that whenever the sensor goes from LOW to HIGH , the function RPMCount(); is invoked.
This means that in one revolution , the function will be called twice ( REV++ ). Therefore actualREV = REV/ 2.
rpm = 30*1000/(millis() - time)*REV;
To calculate the actual RPM, we need the time taken for one revolution. And (millis() - time) is the time taken for one full revolutions.
In this case , let t be the time taken for one full revolution , so the total number of revolutions RPM in 60sec ( 60*1000 millisecond ) is :
rpm = 60*1000 / t * actualREV => rpm = 60*1000 / (millis() - time ) * REV/2
OR rpm = 30*1000 / (millis() - time) * REV;
Step 9: Testing and Troubleshooting
Testing :
1. Take a DC fan and stick a white tape to one of it's blades. Place the sensor 2~7 cm from the blades
2. The readings will appear on the LCD
3. If the sensor gets no readings for 5 sec then it will automatically display the idle screen
4. The Idle screen will display the maximum RPM reached in that particular run.
TROUBLESHOOTING :
1. If the status LED is not blinking, try to adjust the potentiometer until the sensor is able to get readings
2. Ambient light may sometimes interfere with the sensor. Decreasing the sensitivity would eliminate the chance of getting false readings.
3. Check the polarity of the photodiode properly.
4. If everything fails , check your sensor manually by using :
Serial.println( digitalRead(2) ) ;
if your sensor doesn't show " 1 " when any object is placed in front of it then try increasing the value of 33k resistor.
Step 10: Conclusion
Though there are many optical tachometers available in the market, this device is comparatively cheap and works quite well. I've tested it above 20000 RPM and it works every time ! Being open source and programmable , there arise infinite possibilities of customizing this project.
Feel free to ask anything about this project. Suggestions , queries , corrections and "grammatical errors" are welcome !
Happy Tinkering :)

Participated in the
Microcontroller Contest

Participated in the
Formlabs Contest

Participated in the
Remix Contest

Participated in the
Tech Contest
260 Comments
Question 2 years ago
Hi, can you post the electric scheme?
Question 2 years ago on Introduction
Sir is it applicable for real time measurement?
2 years ago
Can u please send the explanation for the code...
Question 2 years ago
Hi, thanks a lot for this excellent design. A question though, what if I want to store the data in a log file - TXT or CSV? Any modifications and tips would be awesome.
Question 3 years ago on Step 10
What is the slowest rpm this device can detect?
3 years ago
Thanks for sharing. Have 2 questions
1. Dont know much about shift registers. Is it very necessary to use it or it is to lessen the number of pins required.
2. Can I use it with a say other IR sensors or even Hall effect sensor
Question 3 years ago
I bought some parts, hoping to connect it to a TinkerKit that came with a screen...
My IR LED & Receiver LED both look exactly the same (clear) - any idea how to tell them apart?
3 years ago on Step 10
How to use this method to check rpm of power-off gears in trucks??
3 years ago
Is there a picture of the
Step 4: The 3-pin LCDthat shows the pins on arduino UNO R3. ? Some of the links on this thread don't work it seems.
Question 4 years ago
Hey
Thanks for sharing this helpful project. I tried measuring RPM with 'pulseIn' function, but it seems there is a problem. Here is my code:
[code]
const byte pulsePin=2;
unsigned long t;
void setup() {
Serial.begin(9600);
pinMode(pulsePin,INPUT);
}
void loop() {
t=pulseIn(pulsePin,HIGH,3000000);
Serial.println(60000000/t);
}
[/code]
Do you have any idea?
Thanks:)
4 years ago on Step 6
Question 4 years ago
Hi, Thank you so much for sharing this awesome project. I have a question. Do you know what is the closest the IR sensor can be to the reflective material in order to work? I would like to use this for a project but distance is a constrain, I need to be very close to the axis of rotation and I would like to avoid using magnets if possible.
Question 4 years ago
Hello mate,
This a very cool project I have a simple question as I had a problem one day, the thing is about the library used shiftLCD.h, can't we use LiquidCeystal.h instead because when I tried to compile your code I got an error message saying that Error compiling for board Arduino/Genuino.
I tried to include a library from the sketch button but the is no library from there or may be should I download the Library from the internet?
Thanks.
4 years ago
Hello and thanks for the scheme.
I'm wondering if it is possible to use this sensor to monitoring the speed of a turbine engine I'm building.
I also have a tachometer, I need help for the sensing part.
I will paint the shaft half black and half white, but my problem is that I need a sensor that can read up to 150'000rpm/2.5kHz.
This scheme will do the job?
Thank you a lot!
Davide
4 years ago
Awesome project. I just finished my trickle charger windmill with a 12 inch 5 bladed fan.
It charged a 6 volt battery fairly quickly and trickles a 12 volt battery if there is windyness.
The tach will be cool aiming the sensor at the blades without touching them! :)))
Question 5 years ago
HI there.
Well, I have a different question in mind. I want to build hydrogen generation that works with RPM, so I need it to be active from 1500RPM and stay active when the rpm is constant and when it increases but shuts off when the RPM drops. That said it must also work with the RPM to generate a given PWM out to the mosfet to increase the amount of gas generation for the car because the fuel prices keep climbing in South African and I want to give a try. but I am very new to this Arduino.
Question 5 years ago
Can i have the output on my laptop ?
Question 5 years ago
bruh,i want to get rpm data through obd interface on my motorcycle but my vehicle is nonobd..is it possible for you to make it using inbuilt pulse or external sensor???
6 years ago
I must have missed something because I am baffled by something that you stated in step 8 - Explanation and calculation where you stated the following:
"This line attaches an interrupt to pin 2 on arduino in "RISING" mode. This means that whenever the sensor goes from LOW to HIGH , the function RPMCount(); is invoked.
This means that in one revolution , the function will be called twice ( REV++ ). Therefore actualREV = REV/ 2"
What confuses me is why there would be TWO rising edge interrupts for each revolution, if there is only one reflective area on the unit being measured. As the IR Led emitter hits the leading edge of the reflective surface, it will cause the IR Photo Diode detector to become activated and cause the voltage to rise to slightly less than the VCC voltage, which in turn will trigger the interrupt of Int0 to fire and invole the RPMCount ISR as the RISING edge is detected. That voltage level will remain at the active level until the IR LED emitter is no longer over the reflective surface and exciting the IR Photo Diode and the signal level will FALL to 0 but because the Int0 interrupt only reacts to the RISING edge, the RPMCount ISR will NOT be invoked. It would seem to me that the RMPCount would only be invoked two times per revolution if the Interrupt mode was set to activate on the condition of "Logic Change"
Thus i believe that your RPM value is off by a factor of 2, because you divide the time in half to account for the "2 interrupts" that are not actually 2, but are rather only one.
Reply 6 years ago
one thing i realized is that the rev/2 probably originated from measuring a 2 blade rotor. the only reason I can make this assumption is because my IR sensor is tripping the interrupt twice for each blade. for IR depending on the sensitivity set on your photodiode, reflective materials can be almost any surface. Much like how you can change the channel on your TV even when aiming at the wall in the other direction. Just remember to take into account the number of blades if your RPMs way higher than usual (like by a factor of 2 lol)
ps - Also, you guys rock! I couldn't have finished this without you guys.