Subscribe to Arduino Academy and start learning today for FREE!

Optical Tachometer

A while back I discussed a IR emitter / detector pair, and talked about building a optical tachometer for determining the RPM of a fan or motor. So now I’m making good on that promise. Connect the emitter / detector as shown in the previous post, using pin 2 on the Arduino (interrupt 0). Put something reflective on one blade of the fan, or cover one half of the motor shaft with black tape, to get one trigger per revolution. We based this project on the work found at

Become the Maker you were born to be. Try Arduino Academy for FREE!

// based on
// 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;
unsigned long rpm = 0;
unsigned long lastmillis = 0;

void setup(){
attachInterrupt(0, rpm_fan, FALLING);

void loop(){

if (millis() – lastmillis >= 1000){  //Update every one second, this will be equal to reading frequency (Hz).

detachInterrupt(0);    //Disable interrupt when calculating
total = 0;
readings[index] = rpmcount * 60;  // Convert frequency to RPM, note: this works for one interruption per full rotation. For two interrupts 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
if(index >= numreadings){

if (millis() > 11000){  // wait for RPMs average to get stable

Serial.print(” RPM = “);

lastmillis = millis(); // Update lastmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt

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

Become the Maker you were born to be. Try Arduino Academy for FREE!

Notify of
Inline Feedbacks
View all comments


Would love your thoughts, please comment.x