# Hall effect Speedometer, Help to understand code or Bug ?

Hi,
I'm using Arduino nano
I'm using Code that i've adapted from this topic/post :

https://forum.arduino.cc/index.php?topic=345156.msg2820766#msg2820766

The goal of this application is to determine the speed of a wheel from a HALL effect sensor

On the previous link 4 magnets have been used to detect the speed,
in my code, i'm using 2 magnets.

and here's the code that i'm using :

``````const byte LED_pin = 13;

// wheel radius in mm * 100 * 2 * ( pi * 10000 ) = 94.248000 mm circumference.
// 6 0's were used in scaling up radius and pi, 6 places are divided in the end
// and the units work out. You can use integers more accurate than float on
// Arduino at greatly faster speed. Both type of long can hold any 9-digits.
// Arduino variable type long long can hold any 19 digits is 19 place accuracy.
// if you work in Small Units and scale back later, integers are plenty accurate.
// remember, this value has to be divided by microseconds per turn.
const unsigned long wheel_circumference = 310000UL * 2UL * 31416UL; // = 94,248,000
// wheel circumference gets divided by microseconds, 1,000,000/sec (usec or us).
// wheel turns once for 94248000 mm/100 in 1000000 usecs =

unsigned long Speed = 0;
unsigned long PrevSpeed = 0;

volatile byte hall_rising = 0; // interrupt flag
volatile unsigned long irqMicros;

unsigned long startMicros;
unsigned long elapsedMicros;

unsigned long ledFlashStartMillis;
const unsigned long ledFlashWaitMillis = 10;

unsigned long displayStartMillis;
const unsigned long displayWaitMillis = 200;

void wheel_IRQ()
{
irqMicros = micros();
hall_rising = 1;
}

void setup()
{
pinMode( 2, INPUT_PULLUP ); // pin # is tied to the interrupt
pinMode( LED_pin, OUTPUT );
Serial.begin( 9600 ); // can this be faster? faster would be better
Serial.println(wheel_circumference);
delay( 1000 );

attachInterrupt( 0, wheel_IRQ, FALLING ); // pin 2 looks for HIGH to LOW change
}

void loop()
{
static unsigned long loopCount = 0; // I expect loop() runs > 33KHz

if ( hall_rising == 1 )
{
digitalWrite( LED_pin, HIGH );
elapsedMicros = irqMicros - startMicros;
startMicros = irqMicros;

ledFlashStartMillis = millis();
hall_rising = 2;
}
else if  ( hall_rising == 2 )
{
if ( millis() - ledFlashStartMillis >= ledFlashWaitMillis )
{
digitalWrite( LED_pin, LOW );
hall_rising = 0;
}
}

if( elapsedMicros != 0 )
{
Speed = (wheel_circumference * 0.0018) / elapsedMicros;

//Speed = (wheel_circumference * 0.0009) / elapsedMicros;
//. here i added a coefficient that means i'm converting to km/h so it's micrometers *3600 / 10^6 and /4 (num of //.magnets)

if ( Speed != PrevSpeed )
{
Serial.print( Speed ); // this now shows mm/sec with no remainder
Serial.println( "km/h" );
loopCount = 0; // HERE IS THE FIX JUST THIS ONE LINE ADDED
}

PrevSpeed = Speed;
}

if(elapsedMicros > 200000)
{
Speed = 0;
}

}
``````

the code itself is quite understandable but i'm a bit lost with maths calculus...

my wheel radius is 31 cm so i've adapted wheel_cirumference like so :

``````wheel_circumference = 310000UL * 2UL * 31416UL;
``````

and i've adapted coefficient for 2 magnets :

``````4 magnets =  Speed = (wheel_circumference * 0.0009) / elapsedMicros;
2 magnets =  Speed = (wheel_circumference * 0.0018) / elapsedMicros;
``````

the output looks correct, but i've a bug :

Example :

...
1452 km/h
19 km/h
1454 km/h
19 km/h
1520 km/h
19 km/h
1458 km/h
19 km/h
1460 km/h
...

i could simply, on a dirty way remove all values >100 km/h and get a clean output but i'd like to understand the cause.

Thank you,

4 magnets = Speed = (wheel_circumference * 0.0008) / elapsedMicros;
2 magnets = Speed = (wheel_circumference * 0.0018) / elapsedMicros;

So, 8 * 2 is 18 in your world?

What is the purpose of loopCount? You only assign it a value of 0.