The Tachometer

Rotational speed is the most important parameter that we need to measure in the hybrid powertrain. Since all of the mechanical components are connected via the planetary gearset, knowledge of the air engine speed and electric motor speed will enable us to calculate output speed. We measure the speed of these components using a tachometer. There are many possible designs for a tachometer, but we will use one based on a 'daisy wheel' and Hall-Effect sensor.

A bicycle tachometer uses a magnet and a magnetic sensor to detect each revolution of the wheel.

A tachometer has two main components. The first is a sensor that fires when it senses that a certain part of the rotating shaft is near. The figure at right shows a simple bicycle tachometer, which uses a magnet (usually attached to the spokes of the wheel) and a magnetic sensor. Each time the wheel rotates, the magnetic sensor sends an electrical pulse to the 'brain' of the tachometer.

The second component is a system for counting the pulses coming from the sensor, and then dividing the number by the elapsed time. We use Arduino for this purpose, since it has a built-in clock. It also has 'interrupt pins' which we can use to count the pulses even when the controller is busy doing something else.

An interruption-type sensor fires when its slot is blocked by the daisywheel.

The Tachometer Sensor

The sensor's job is to detect when a part of the rotating shaft is in proximity. For this there are several options including optical, magnetic and mechanical (e.g. a limit switch triggered by a 'bump' in the shaft.) One common method is to use a 'daisywheel', as shown in the figure at right. The sensor is triggered when one of the 'petals' on the daisywheel fills the slot. By counting pulses, and dividing by the number of petals on the wheel, the shaft speed can be measured.

The two most common types of sensor for this application are optical and Hall-Effect. The optical sensor has an LED (usually infrared) on one side of the slot, and a detector on the other side. This was the first type of sensor we tried when prototyping the tachometer, since it seemed to be the simplest (the daisywheel can be made of any opaque material). Unfortunately, we found that the optical sensor had intermittent reliability, even in a laboratory setting. What is worse, the 'faculty-prototype' seemed to work reliably, but many of the student prototypes gave spurious readings. We finally traced the problem to variations in laboratory lighting. Since the faculty prototype was always used in the same spot, there were no variations in lighting, but since the students worked wherever they could find space, the presence of sunlight wreaked havoc with the sensor. Our conclusion is that optical sensors are best suited to applications where lighting is constant and reliable, and not to a university laboratory setting.

The next most common type of interruptor sensor is Hall-Effect. In this sensor, a permanent magnet is on one side of the slot and a detector on the other side. If the slot is blocked by a ferrous material, the sensor is triggered. This requires that the daisywheel be made of steel or iron, which makes fabrication more involved than with the optical sensor. Of course, you can make the daisywheel primarily of thin plastic, and glue pieces of steel to the petals if you don't have access to a waterjet machine.

OBH900 Schematic

The sensor we used for our prototype is the Optek OHB900 Hall-Effect sensor, which is available from Mouser electronics. It's not cheap ($8.06 each in September of 2013), but the price goes down considerably if you buy in bulk. The datasheet for the OHB900 can be found here. Examining the datasheet, you can see that the OHB900 is configured as a sort of transistor, with the output at the collector and the base connected to the Hall-Effect sensor. If you're new to sensors, this may seem like a strange way to do things, but it is fairly common. In this configuration, the transistor acts as a switch. When the magnet is detected, the switch is closed, and electrical current is free to flow from the 5V power supply to ground. When the magnet is blocked, the switch is open, and no current flows.

When the magnet is detected, the transistor goes into a state called 'saturation', where current flows from collector (the top) to emitter (the bottom) with very low resistance. In fact, the resistance is so small that the voltage at the collector is very low (remember Ohm's law?). In the datasheet, the Output Saturation Voltage is listed at 100mV, or 0.1V - very close to ground. When the magnet is blocked, the output is very close to 5V, since no current flows through the transistor. Thus, the sensor outputs 0.1V (close to ground) when the magnet is detected and 5V when it is blocked.

To build the circuit, we must find a suitable size for the resistor, R. If R is too small, too much current will flow through the transistor, which will destroy it. If R is too large, not enough current will flow for the transistor to enter saturation, and the output won't be able to reach ground. In the datasheet, the Output Saturation Voltage is listed as 100mV, for a saturation current of 20mA, so we will use 20mA as a target value for the saturation current.

If we add the voltage drops across the circuit, we have

\begin{equation} 5V-V_R-V_{Sat}=0 \end{equation}

where \(V_R\) is the voltage drop across the resistor and \(V_{Sat}\) is the saturation voltage (0.1V). The voltage drop across the resistor can be calculated using Ohm's law

\begin{equation} V_R=iR=20\text{mA}\cdot R \end{equation}

Rearranging this equation to solve for R we have

\begin{equation} R= \frac{4.9\text{V}}{20\text{mA}} = 245\Omega \end{equation}
OBH900 Schematic with LED

We'll use 270Ω, since it's the nearest common value that will keep the current under 20mA. During the prototyping phase, it is very useful to have a visual indication that your sensor is working properly. One simple way to do this is with an LED, as shown in the circuit at right. When the magnet is detected (and current is flowing through the transistor) the LED will light up. It will turn off when no current is flowing (when the magnet is blocked). We'll need to resize the resistor to account for the voltage drop across the LED.

The voltage drop across most LEDs is between 2 and 2.5 volts. Substituting this into Equation (1), we have


And solving for the resistor gives

\begin{equation} R= \frac{2.9\text{V}}{20\text{mA}} = 145\Omega \end{equation}

The nearest commonly-available value is 150Ω.

//Tachometer Air Motor const int Tach = 3; // pin20 Hall Effect sensor AM, interrupt 3 float rpmVal = 0; // current value of rpm float rpmOld = 0; // rpm from last calculation unsigned long timeOldAM = 0; // time at last interrupt unsigned long timePulseAM; // time between interrupts const int ticks = 6; // number of pulses per rev (number of slots in daisy unsigned long time=0; void setup() { pinMode(Tach,INPUT); attachInterrupt(Tach, rpm_function, FALLING); // Initialize interrupt pin for tachometer Serial.begin(9600); } void loop() { rpmVal = function_rpmVal(rpmVal, rpmOld, timePulse, timeOld, Tach, 0, 3000); Serial.print("rpmVal "); Serial.print(rpmVal,3); } // ************************************************************************************************** // Interrupt function // ************************************************************************************************** void rpm_function() { timePulse = (micros() - timeOld); timeOld = micros(); } // ************************************************************************************************** // RPM calculation function // RPM=revolution per minute=1/(timepulse*6) the rest is convertion from micros to minutes. // ************************************************************************************************** int function_rpmVal(float rpmVal,float rpmOld, unsigned long timePulse,unsigned long timeOld,... const int Tach, const int minRpmVal,const int maxRpmVal) { const int ticks=6; // Number of ticks of the daisy Wheel rpmOld = rpmVal; // store previous value of rpm rpmVal = 60*1000000/timePulse/ticks; // calculate current rpm rpmVal = constrain(rpmVal, minRpmVal, maxRpmVal); if(micros() - timeOld > 500000) { rpmVal = 0; } // motor has stopped return rpmVal; }