### Measure RPM with Slotted Optical Switch

How to build a tachometer with a slotted optical switch and an Arduino board. Simple sketch based on interrupts.

Building an RPM counter is very easy with an optical switch and a way of counting pulses generated by the switch. A microcontroller, a frequency meter and even a logic analyzer can be used for this. Here, I will be using the cheapest and popular method: an Arduino. Optical switches are devices made of an emitter LED, usually infrared type and a receiver diode. Between the IR emitting LED and the receiver there is a slot. An opaque piece can pass through this slot and block IR beam. This will be detected by the receiver diode and its output will change state.

The piece that will block IR light will be a flange with a slot (a cutout area from the disc). When this passes through the switch's slot, the light reaches the receiver diode. Therefore, rotations are translated into a digital signal with a constant duty factor, dependant on flange configuration. The frequency of this signal needs to be measured and converted into RPM.

 775 motor fitted with optical switch
The image above shows a 775 DC motor with the optical switch mounted on it by means of a metallic piece and two screws. You can see in the bottom right corner a better view of the optical switch. You can also see the flange wheel with the cutout next to the motor (not mounted on shaft yet).

I used for this project an OPB930 optical switch which I found in my parts bin. You won't find this exact part number, but optical endstop switches designed for use at 3D printers are widely available for less than 1USD/piece. If you want, you can even build this yourself with an IR LED and IR photodiode.

 Slotted wheel and optical switch mounted on motor
I also had a ready made flange wheel. But, that's easy to build. You don't need too much precision, just a way of fixing a circle shaped metal sheet on the motor axis. The best setup would be to get a flange coupler and fit a metallic disc on it with screws. Flange couplers are available for different axis diameter. You can then cut the disc of any diameter you want as long as it can be fitted on the flange.

 Flange coupler and types of discs you can use for RPM counting
Connecting the optoswitch to Arduino is very easy. You only need a current limiting resistor for the IR LED. The optical switch I used has digital output. And this is needed for Arduino, because counting is based on interrupts. However if you make your own switch with a diode, you will need an opamp to convert its output to digital.

 Connect the optical switch to Arduino pin 2
To count rotations, an interrupt will increment a variable each time the signal at D2 pin is rising. The falling of the signal can be used as well. Then, once in a while, the time passed from previous calculation is read. Using the number of rotations that happened in this time, RPM is computed. This number is set back to 0 and starts counting, waiting for the next computation.

 Measured RPM of 775 motor
RPM is printed on LCD.
  noInterrupts();
uint32_t rpm = rot * 60000 / (millis() - measureTime);
rot = 0;
measureTime = millis();
interrupts();

Interrupts are disabled during RPM computation. 60000 is divided by time in milliseconds passed since previous computation [millis() - measureTime]. This converts ms to minutes. The value is then multiplied by count of rotations (rot). This counter is cleared and measureTime is updated.

The software is incredibly simple.
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

volatile uint32_t rot; // rotation count
unsigned long measureTime = 0;

void setup() {
pinMode(10, INPUT); // for LCD shield
pinMode(2, INPUT);

lcd.begin(16, 2);
lcd.print("   Tachometer   ");
delay(500);

}

rot++;
}

void loop() {
delay(1000);

noInterrupts();
uint32_t rpm = rot * 60000 / (millis() - measureTime);
rot = 0;
measureTime = millis();
interrupts();

lcd.setCursor(0, 1);
lcd.print(rpm);
lcd.print(" RPM        ");
}

LCD pins are configured for the LCD-keypad shield.

This mode of measurement can be used as long as RPM is greater than 60. Each second, at least one rotation must happen for accurate readings. I prefer to use this method of counting rotations over a larger period of time (about 1 second), instead of measuring the duration of a single rotation.