This is a shortened translation from Russian of my article published in Радiоаматор (Radioamateur) magazine, no. 2-3 (2009) pp. 42-45. In this project we design a digital tachometer. This Instrument can be used for measuring rotating speed of various sources in RPM. The working range is 30RPM - 9999RPM. Rotation speeds outside of this range are displayed as "____" (for lower RPM) or "----" (for higher RPM). The photo below shows measuring the speed of a computer fan. For this we glued at its rotor a disk cut of a standard white paper, one half of which is colored black. The unit (the black box on the right) has built-in infrared emitter and receiver. The receiver captures every change of the disk color through the reflected light of the emitter and measures the time interval between those events. The length of this interval is inverse proportional to the rotation speed. The unit is pretty sensible and can catch the speed from approx. 2" distance. It operates best with no bright lamps around, since their turn on/off frequency (60/120 Hz in our area) can interfere with the measurements. The day light, however, practically does not affect the operation. After attaching the power the unit displays 0 and start measuring automatically upon approaching it to the rotating disk.
Counting RPM | Sensor disk | |
The sensor for the speed measurement is a pair consisting from an infrared emitting diode and an infrared photo-transistor. We used generic ones available from RadioShack. The infrared waves emitted by the diode reflects from the object and reach the photo-transistor. The last one changes its resistance, which is measured by an analog amplifier and converted into a digital form.
If the object is a rotating disk, one half of which is white and the other is black, then every disk rotation produces a couple of different signals: a weaker one for the black part and a stronger one for the white one. Those signals are amplified by the left (on schematic) op-amp. The impulses at its output are already close to rectangular ones. To improve the pulse raising/falling edges the second op-amp is used, which works as a comparator. The 10K resistor in its feedback circuit is used for increasing the comparator hysteresis, which the 0.01μF cap in the feedback of the left op-amp is used to prevent the self-generation of the analog part. The period of the rectangular waveform at pin 7 of the op-amp equals the one for the disk rotation. Those pulses are forwarded to the CCP1 input of PIC for measurement.
Schematic | Front view | Back view | ||
The PIC measures the input pulse period T in microseconds and converts it into RPM. Obviously, RPM = (106/T)·60. The period T is actually measured in the number of periods of a sample frequency of 2.5MHz by the PIC's CCP module. The PIC runs at 10MHz, so 2.5MHz is its instruction cycle frequency. If N periods of the sample frequency occurred during one disk rotation (or capturing cycle) then T = N·(1/2.5) μsec. Combining the last two formulas, the rotation speed can be computed by the following formula:
RPM = (2.5·106/N)·60 = 15·107 / N
The computed value is displayed on a LED display consisting of four single-digit 7-segment indicators. The LEDs have a common cathode configuration and are multiplexed by MOSFET transistors, which are, in turn, controlled by the PIC. At each time moment just one of the digits is on. The refresh frequency is about 65Hz and the average power consumption is close to 80mA. The device can be powered from a generic 9V walwart power supply. The board contains a 5V voltage stabilizer for a normal operation of all components.
The unit is assembled on two PCBs inside a 3"x2"x1" plastic project case from RadioShack. The top PCB contains the LED display along with its current-limiting resistors and the op-amp with most of its surrounding parts. It is assembled on an perf-board by using a point-to-point layout. The other board carries all the remaining parts. The boards in case are mounted on the internal standoff and are separated by a 4mm nylon spacers. The PIC oscillation frequency is stabilized with a 10MHz crystal. The infrared emitting diode and the photo-transistor are put into ca. 0.5" plastic heat shrink pipes to isolate them from each other and protect the sensor from ambient light.
Display board | LED layout | Assembled unit | ||
The mail loop of the program starts with displaying the current RPM value. Each digit is on for 4 msec during the multiplexing, which results in 16 msec display refresh rate. Parameter SPEED determines the display update frequency. Every RPM value is not changed on display for a certain number of display refreshes determined by parameter SPEED, which is currently set to 10. Hence, every number on display is not changed for SPEED·16msec, which is 160msec. This is done for reducing fast change of numbers on the display and improving its readability. After SPEED times of screen refreshing the unit starts a finite state machine (FSM for counting a new RPM value.
To count a new RPM value the CCP module is used. This module captures two time events between two pulse raising events at input CCP1 of PIC. The time events are measured in periods of a sample frequency of FOSC/4, which is 2.5MHz. The number of periods is counted by TMR1 and an additional 8-bit variable n2, that counts the number of times TMR1 overflows. This way the number of periods between two capturing events is a 24-bit value with n2 being its MSB and two lower order bytes stored in TMR1.
The FSM machine can be in one of 3 states, corresponding to the number of captures done so far. This number is encoded in bits 0 and 1 of variable flag. If the number of captures is 0, we request the first capture by enabling CCP1 module and indicate this by setting bit 3 of variable flags. The unit remains in state 0 by waiting for the first capture a certain number of display refreshes specified in variable wait. Currently, the value of wait is 5, so we wait for the first capture for about 0.8sec. All this time the old RPM value is displayed. If no capture is done during the waiting time, we re-initiate the capture and display 0 on the display. Each capture initiates an interrupt, which is processed as specified below.
After the first capture the unit transfers to state 1. In this state we wait for the second capture provided by TMR1 and variable n2. If the time interval between two captures becomes too large (so n2 reaches the value of 256 and reset back to 0), this corresponds to a too slow rotation, which is not further processed. In this case bit 2 of variable flag is set to 1 and we return back to state 0, displaying "____" on display.
Upon getting the second capture, the program disables any further captures by disabling the CCP1 module, and starts an analysis. The capture time stamps are stored in 3-byte variables n1 and n2. First, the difference between them is computed and compared with 15000. If the difference is below 15000, this corresponds to a too fast rotating speed (above 10000RPM) which we cannot display on 4 digits and, thus, indicate a too high speed by displaying "----". Otherwise, we analyze msb(n2) and report too low speed ("____") if it is set. If the difference is finally in the right range, the code computes the ratio of 15·10^7 / n2, which does not exceed 9999 and, thus, occupies at most 14 bits. The division is implemented by using the subtract and shift method, so this loop runs at most 14 times. Before the loop the value of n2 is shifted to the left so that its msb becomes at the same position as the msb of the number 15·10^7. At each iteration of the loop a 32-bit subtraction is performed followed by a 32-bit restoring addition if the difference becomes negative. After this the value of n2 is shifted to the right and the process repeats. This way computing the ration takes at most 14 iterations of the loop compared with implementation of the division by using subtraction, which may lead to 9999 subtractions.
The obtained 2-byte value of RPM is further modified by using a sliding averaging with 3 previously computed RPM values. This prevents large jumps of the values on the display and makes the operation much smoother.
The interrupt service routine processes interrupts initiated by two modules: CCP1 and TMR1. If an interrupt is initiated by CCP1, it must be either the first or the second capture, depending on bit 3 of variable flags. In the first case we store the corresponding time stamp in n1, and in n2 otherwise. If an interrupt is caused by TMR1 overflow, we increment the overflow counter and check it with 0. In the later case bit 2 of the variable flags is set, which indicates a too slow rotation and processed by the main code.
Last modified:Mon, Jan 23, 2023.