# How do I measure the RPM of a wheel?

I'm trying to make an onboard system for my bike using an Arduino or maybe the Lilypad boards.

I think I should use a Hall effect sensor, but any alternative is good as well.

I want to output my speed to an LCD display and I'm wondering the best way to go about this.

Using a hall effect sensor as Starliner suggested will be one way to interface with the wheel. Achim and Shutterdrone's suggestion to use a reed switch makes more sense though, given the supporting hardware a hall effect sensor requires to get a clean digital signal.

You might be able to pickup a magnet and sensor from a broken bicycle computer but if you can't, a local component store should have one of each in stock. The advantage of a recycled sensor and magnet is the you will already have the mounting hardware.

There is a page on the arduino wiki on ReadingRPM signals. To calculate the speed multiply the RPM value by the circumference of the wheel (2 * pi * radius [in meters]). The result will be in meters per minute.

Edit: I've notice that the linked code is for systems with two pulses per revolution. One magnet is sufficient for your task. Additionally, for a bicycle computer you'll probably want the result to be in KPH (or MPH if you live somewhere that still thinks that's civilised). I've made some (untested) mods to the code on the wiki to print out KPH and pasted them bellow.

volatile byte revolutions;

unsigned int rpmilli;
float speed;

unsigned long timeold;

void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, RISING);

revolutions = 0;
rpmilli = 0;
timeold = 0;
}

void loop()
{
if (revolutions >= 20) {
//Update RPM every 20 counts, increase this for better RPM resolution,
//decrease for faster update

// calculate the revolutions per milli(second)
**rpmilli = (millis() - timeold)/revolutions;** EDIT: it should be revolutions/(millis()-timeold)

timeold = millis();
**rpmcount = 0;** (EDIT: revolutions = 0;)

// WHEELCIRC = 2 * PI * radius (in meters)
// speed = rpmilli * WHEELCIRC * "milliseconds per hour" / "meters per kilometer"

// simplify the equation to reduce the number of floating point operations
// speed = rpmilli * WHEELCIRC * 3600000 / 1000
// speed = rpmilli * WHEELCIRC * 3600

speed = rpmilli * WHEELCIRC * 3600;

Serial.print("RPM:");
Serial.print(rpmilli * 60000,DEC);
Serial.print(" Speed:");
Serial.print(speed,DEC);
Serial.println(" kph");
}
}

void rpm_fun()
{
revolutions++;
}


Also, I've enabled 'community wiki' on this, which I think means other users can edit it. If my maths is wrong (and you can prove it!) jump in and fix it for me. :)

Actually, Achim has made a very good point here.

There is a big difference between a Reed (magnetic) relay (switch), and a Hall effect sensor.

Primarily, a Reed relay will connect a switch whenever enough magnetic force is acting upon it, giving you an on/off signal. A Hall effect sensor provides a voltage level indicating how much magnetic force is being applied to it.

The code shown above would only 'directly' work with a Reed relay, which is not to say that it won't work at all for a hall effect sensor, but that it would provide additional challenges using a hall-effect sensor.

The primary challenge will be that you're treating an analog device as a digital one - expecting to trigger on rise of a pulse. Now, the signal won't be pulsed - it will be generally like a bell-curve, with all sorts of fluctuations. You might trip past the minimal voltage for a high signal (around 3.5v, IIRC?) several times as the magnet passes the hall-effect sensor.

Of course, our first instinct when using something like a hall effect sensor is to use the ADC and read the voltage level on an analog pin. However, you're limited to 10,000 reads, roughly, per second on an analog pin (each read takes 100uS). That assumes also that all you do is loop and read values - doesn't leave you much other time to update a display, calculate, etc. Not to mention, if you read at the wrong time, you missed your signal!

I'm sure it's possible to use interrupts somehow linked to the ADC, but I don't have such knowledge handy.

Instead, if you wish to use an actual Hall Effect sensor, I'd suggest feeding it into a Schmitt trigger to convert it to a digital (on/off) signal at a calibrated level that indicates "directly under the magnet." Additionally, depending on the level of hysteresis implemented in the Schmitt trigger, you may need to do some de-bouncing that would change the rate of de-bounce based on current speed. Then you could treat it like a normal Reed relay.

!c

• You can get the best of both worlds. ATMega8 components can be configured to provide access to the internal comparator. With a suitable voltage reference (adjustable with say, a trimpot), you can have interrupts on rising (or falling or both) edge of the analog signal. link to forum topic explaining just that :arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1163394545 Sep 7 '10 at 23:42
• There are hall-effect devices with a schmitt-trigger thresholded output. They're quite common. Also, with a reed switch, you're going to have to debounce the output anyways. Sep 8 '10 at 4:26

Hall effect sensors and reed switches are the most mentioned here, and they're the best solution.

The reed switch will be cheaper, but may give you false pulses when the bike gets a shock. If that's just one from riding of the curb the software may easily filter it out, but it's different when you're riding over cobblestones, which may give you false pulses all the time. More shock resistant reed switches will require a stronger magnetic field to activate, but a Neodymium magnet will fix that.

edit in answer to m.Alin's questions
Reed switches are fast. That's because the reed has a low mass (= low inertia) and a low travel, often only a few tenths of a mm. This reed switch has an operate time of < 0.6 ms, and a release time of < 0.1 ms. At 36 km/h the switch travels 5 mm in 1 ms when mounted halfway the wheel's diameter. So it's fast enough to be activated when it passes the magnet.
This document about the same switch gives a life expectancy of > 10$^7$ operations, and that's not as much as it seems. If you would do 25 km a day you reach that 10$^7$ switch events in 2 years.
end of edit

The Hall effect switch doesn't have these disadvantages, but is somewhat more expensive.

You get time $T$ between 2 pulses as information from the sensor. Then

speed $v = \dfrac{\pi D}{T}$

in m/s if wheel diameter $D$ is expressed in meters, and $T$ in seconds. Convert to km/h by dividing by 3.6, divide by 5.79 for mph.

distance $s = \text{pulse count} \times \pi \times D$

in meters if wheel diameter $D$ is expressed in meters. Divide by 1000 for distance in km, by 1609 for miles.

A magnet can be mounted on the edge of the wheel's rim and the Hall Effect sensor mounted very close to (but not contacting) the magnet. As the wheel spins and the magnet passes the sensor, the sensor will pick up the variation in the magnetic field.

If you still want to go solid-state, they are many "Hall effect switches" which include the Hall effect sensor and Schmitt trigger with hysteresis to provide clean digital output without bounce. They switch whenever some threshold flux density (provided in datasheet) is reached. You can calculate a good combination of magnet and switch or simply experiment.

This site will tell you a lot more.

The parts in bicycle computers are reed-contacts not hall effect sensors. They are completely different. But I think you all are talking about the reed-contacts.

The magnet can be mounted on a spoke, and the sensor on one of your forks, or the chainstay.

Rather than multiplying by pi etc, the method suggested by my last bike computer was to measure one revolution's linear distance (chalk on the tyre, measure between the two chalk marks), then you can just multiply the revolutions by the circumference direct.

[EDIT] I've just found this guide on the piclist site for implementing a bike computer using a PIC, maybe some of the information might be of use to you.