Best Way to Conver Hall Effect Sensor Singal into KM/H

Hello guys, in a previous post I learned how to convert the 12v square signal into a 5v square signal for the Arduino input range. The sensor that outputs this type of signal is a hall effect sensor for speed in my car. I was now doing the programming part and I am trying to do it by dividing the distance (circumference of the wheel) by the time it takes for 1 rotation. However, it does not seem to work very well. Unfortunately, I don't have any datasheet that shows specifications and other useful information about the sensor. What do you guys suggest in order to obtain an accurate speed in km/h? What type of logic should I use?

Thanks to all

What do you mean by Best ?

We need a bit more information about this.

Most here would start with examining the output waveform then do some experimenting to get information.

Hi, thanks for your answer. This is my circuit simulation that shows my input (the square wave on the left) here is the link. Also, I have a video showing how when I move my car by pushing very slowly the voltage oscillates between 12v to 0v Here is the video.

For best I mean I have these pulses when the wheel of my car spin and I would like to figure out the best logic/code to convert it into km/h


Explain this more.

What is the correspondence between pulses and speed?
Does a doubled speed produce the double frequency of the pulses?

In that case I suggest making a little measuring sketch. Do like this: Drive the car in a decided speed. Let's say 20 mph, 36 km/h. Then start the sketch. It will count the number of pulses during, let's say 1 or 10 seconds. The rest is desktop math.

That is a great idea thanks for the help I will try doing that!

I suspect you are getting the number of pulses per revolution wrong. In your video it doesn't look like there is only one pulse per revolution. You also didn't show your code so you may be measuring time incorrectly.

If the pulse frequency is low measuring the time needed for a certain number of pulses, 100, 1000,.... could be a way to calibrate the device.

Actually this is quite inaccurate, because the tyre is flattened at the bottom, so the radius is not what you would expect it to be from the wheel's circumference.

There are two ways to deal with this, and I've done both (although on a motorcycle).

First method: put the car on a large, flat area of ground (like an empty car park). Choose which wheel you will observe, and push the car until the valve is exactly at the bottom of the wheel. Mark the ground with a chalk line - this represents your starting point. It helps to mark a line on the tyre, next to the valve, for even better accuracy.

With the steering straight, push the car along, counting how many times the wheel turns. After (say) five turns, line the valve up at the bottom and draw another line. Then measure the distance between the lines with a tape measure. Divide by five to get the distance travelled per revolution of the wheel. Then, when you know the RPMs of the wheel, you can calculate the speed.

It helps if there is another person who can monitor how many pulses are produced by the sensor as you push the car along for five (or whatever) full revolutions of the wheel. Then you will know how many pulses you get for each turn of the wheel, and you have all the information you need to make your speedometer.

Second method: On a long, straight, empty road, use a GPS to measure your speed. Start at, say, 10kph and go up in 10kph jumps. A passenger monitors the pulses from the sensor and notes their frequency - this normally requires a portable oscilloscope, of course. Then you can plot a graph of frequency against speed, and from that work out the formula to convert from the pulse frequency to the speed in kph.

I do not really understand your circuit simulation. Are you now trying to read the tachometer output that goes to the MCU, what you are calling the "tach out to MCU" ? Perhaps it is a language thing?? "Tach" to me means Tachometer" which measures engine speed.
Where does the "tach from sensor" signal originate?

In your other post I thought you were trying to read the wheel sensors. If that is still the case you need to first determine how many pulses per wheel revolution. Then I would suggest using an interrupt routine in the Arduino to determine the number of pulses over a measured time interval. Once you have this the rest is simple math.

@oldvetteguy yes the sensor is the wheel sensors. Now I have a square 0V 5V signal.

I saw already one example that used interrupt routine however I am not very expert and I don't know how it works. Can you please share an example or the logic behind it?


@SteveThackery Thanks this helps! I have just a question do you have any suggestion for getting the difference in time? After knowing the total distance and the total pulses I imagine I will need to divide by the time. How I can do it with Arduino?

Certain pins on the Arduino can be used as interrupt pins. The wire carrying the square wave signal is attached to one of these pins. An interrupt routine is attached to this pin so that when the square wave goes high the interrupt is activated. Your code should count the number of interrupts on this pin and save the time when the first one is counted and the time when the last one is counted, giving you the number of revolutions and the time interval. That is the reason you need to figure out how many signal spikes you have per revolution.

I could show some code, but you need to figure it out yourself.
Do an internet search for "arduino hall effect interrupt rpm" for some examples.

1 Like

How far the sensor is from center of the wheel ?
What kind of vehicle is it ?

The procedure I described, where you measure how many pulses per revolution of the wheel, and the distance travelled per revolution of the wheel, means you can now work out how many pulses are generated per kilometre. I have no idea how many that might be, but let's just say 1000 pulses per kilometre (one pulse per meter) to make the arithmetic easier.

When the car is travelling at 1 metre per second (1 m/s = 3.6kph) the pulses are one second (1000 ms) apart. Now, imagine the pulses are arriving 400 ms apart. The speed of the car is then: (1000/400) * 3.6 = 9kph. Thus by measuring the interval between pulses you can calculate the speed, using the principle just explained.

Let me emphasise something @oldvetteguy said: You need to find out how many pulses per revolution of the wheel you get, and you need to measure how far the car travels per revolution of the wheel.

Look at any 'C' tutorial to find out how to do basic maths like multiplication and division, then you will be able to get your Arduino speedometer working.

Have a go at it and post your code if you still need help.

1 Like

I would suggest that you start with a very simple program that simply reads a single pulse every time the wheel sensor is triggered. Sounds like you are pushing or driving the car when trying out your code. How about just jacking up one of the non driven wheels and turning it by hand, much easier to do while getting your code working.

1 Like

I agree. I suggested pushing the car only as part of the calibration procedure. To generate pulses for testing purposes, jacking up the car and turning the wheel would make sense.

So I made some progress and I figured out that there are 11396.011396 precisely pulses in 1KM. So I made this simple program, let me know if you think there is a better way to find the time (in ms) between one pulse and another one. Also, I would be very happy if you can have a general look at it.

int SpeedLastUpdate = 0;
int Pulses = 0;
float TimeBefore;
float TimeAfter;
float DeltaTime;
float Speed;

void setup() {

void loop() {
    if(millis() - SpeedLastUpdate >= 250){ // Update Speed every 250 ms
        while (digitalRead(PIN_WHEEL_SENSOR) == LOW) {} // Waits until the wheel sensor value is HIGH
        TimeBefore = millis(); // Records the time when the sensor is HIGH
        while (digitalRead(PIN_WHEEL_SENSOR) == HIGH) {} // Waits until the wheel sensor changes again value form HIGH to LOW
        while (digitalRead(PIN_WHEEL_SENSOR) == LOW) {} // Waits until the wheel sensor value is HIGH
        TimeAfter = millis(); // Records the time when the sensor is HIGH again
        DeltaTime = TimeAfter - TimeBefore; // Finds the difference in time between one pulse
        Speed = (11396.011396/DeltaTime)*3.6; // Finds the speed
        SpeedLastUpdate = millis();

I haven't studied every line carefully, but it looks good to me.

Be aware that it will sit forever in one of the while{} statements when the vehicle is stationary, so the last speed displayed will remain showing, rather than going to '0'.

One last point: you aren't debouncing the sensor input, but I don't think that should be necessary with this type of sensor. If it sometimes shows glitchy speed readings, take a look at the incoming signal from the sensor and consider how to clean it up. As I say, I very much doubt it will be necessary.

How did you derive the "11396.011396 precisely pulses in 1KM"?

Your code may work, but you may need to place the
SeedLastUpdate = millis(); statement outside the
if(millis() - SpeedLastUpdate >= 250) brackets
For example if the value of SpeedLastUpdate is set less than 250 the code inside the if(millis() - SpeedLastUpdate >= 250) brackets will never update.
Of course 250 ms would be 164 km/hr so you may never exceed that speed.

In fact do you really need the if(millis() - SpeedLastUpdate >= 250) line? Just use the code inside the brackets and use delay() to slow it down.
Do you really need to display the speed every 250 ms.?

Have you tried your code yet?
If your speed readings tend to jump around you may consider using an interrupt routine and averaging the time for say 10 pulses.
Did you ever determine how many pulses per wheel revolution?