Wheel speedometer using Hall Effect.

Trying to accurately measure speed using a hall effect and magnet attached to a wheel. This function can be the main function and run without being interrupted, but I do have other small functions that need to run. So if this function counts one wheel rotation then does other stuff, and comes back, that's fine.

How I decided to do it was sample Millis, then count falling edges until 5000MS has passed. I'm going to shorten this down to 1000ms when I implement it, but I can't move a magnet on my breadboard that fast, so for testing, it's 5000ms. I can't come up with a good way, that doesn't hang while still catching falling edges. Note, the vehicle needs to be accurate from 5mph to 120mph, which is around 1 to 18 RPM. Also, the hall effect is normally HIGH and goes LOW when the magnet passes it.

Here is what I have.

  // record MILLIS , count ticks, after MILLIS + 1000, compute speed
  int future = millis()+5000;
  int ticks = 0;
  while(future > millis()) // 1 second hasn't passed
    if(digitalRead(speedPin) == HIGH){       //if the input to goes HIGH again (senses magnet)
      if(digitalRead(speedPin) == LOW){      //and then it goes LOW (no magnet) we know one pulse happened.

  // speed is ticks per second
  Serial.print("Ticks: "); Serial.println(ticks);
  ticks = 0;
  Serial.println("Pulse Time: 5000ms");

My issue is that it's not counting accurately. Is there a better way?

Just checking your maths.
120 miles per hour
2 miles per minute
3560 yards per minute
about 59 yards per second
divide this by 18 gives a wheel circumference of about 10 feet.
divide by pi gives a diameter of about 3 foot?

You have a tractor that goes 120 mph?

Math is not my strong suit.... wheel diameter is 17 inches.

Let me try this again:
17 inches * pi / 12 = 4.45 ft circumference
120 mph = 2 miles per minute = 10560 ft per minute

10560 / 4.45 = 2373 rotations per minute = 39.5 rotations per second

So if I count 40 rotations in a single 1000ms period, I'm going around 120 mph, is this possible with an arduino?

Now onto my code! Suggestions?

is this possible with an arduino?

Sure. While it is not reading the sensor, it can be flashing LEDs, too.


Get busy writing some.

OK with a bit of maths, I find that 1mph is equivalent to 17.6 inches per second.

So here's a rough sketch that could get you started. I've no doubt that there's probably a few bugs in it but hopefully enough to give you the general idea.

#define wheelDiameter 17
float wheelCircumference;
volatile unsigned long lastPulse=0;
volatile unsigned int MPH;

void setup()
wheelCircumference = wheelDiameter * 3.14;

attachInterrupt( 0, pulseISR, RISING);

unsigned long lastDisplay=0;

void loop()
unsigned long t=millis();

//If wheel isn't turning, MPH will not get updated
//So we'll reset it here if sensor hasn't been triggered for four seconds
if ((t - lastPulse) > 4000)

//only update display once per second
if ( ( t-lastDisplay) >= 1000)
  Serial.println(" MPH");  

void pulseISR() {
unsigned long newPulse = millis();
unsigned long turnTime = newPulse - lastPulse;
float inchesPerSecond = wheelCircumference * 1000 / turnTime;
float mph = inchesPerSecond / 17.6;
MPH = mph;


Just for the record, I think we need a video of said tractor at 120MPH.

Just for the record, I think we need a video of said tractor at 120MPH.

He tried, but the earth dug up by the plough sprayed up and covered the camera lens. :slight_smile: