I am having difficulty setting up an interrupt to count how many times the magnet passes so that I can count something like every 100 ms the actual speed.
I have a little code put together from the Internet:
const byte LED_pin =13;
const unsigned long wheel_circumference = 431800UL * 2UL * 31416UL; // = 94,248,000
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 = 100;
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
delay( 1000 );
attachInterrupt( 0, wheel_IRQ, RISING ); // pin 2 looks for LOW to HIGH change
}
void loop()
{
if ( hall_rising == 1 )
{
elapsedMicros = irqMicros - startMicros;
startMicros = irqMicros;
hall_rising = 2;
}
else if ( hall_rising == 2 )
{
if ( millis() - ledFlashStartMillis >= ledFlashWaitMillis )
{
hall_rising = 0;
}
}
// print speed 1000/Wait (10) times per second
if ( millis() - displayStartMillis >= displayWaitMillis )
{
Speed = wheel_circumference * 0.0009 / elapsedMicros;
displayStartMillis += displayWaitMillis;
if ( Speed != PrevSpeed )
{
Serial.print(Speed); // this shows mm/sec with no remainder
Serial.println(" kmh");
}
PrevSpeed = Speed;
}
}
But when I use this code in U8glib to display the value on a GLCD . Values are totally wrong. Can someone help me?
1 Answer 1
You either need to change your code to count the number of revolutions in the interrupt. Then divide that value in your main loop by the elapsed time to get the angular velocity. This may or may not work, as the number of revolutions may be small or even zero when you do the calculations. Thus contributing to errors.
Or, change your code to record the elapsed time between rising edges in the interrupt. Then find the inverse of this value. This may be better as you could even miss an event in your main loop and still calculate the speed. Careful not to take the inverse of zero.
To calculate speed you need to find the rotational speed of the wheel, and, consequently, how fast you are bicycling. Use this equation: enter image description here ...where omega is the revolutions per time as calculated by the 1st method above or reported by the interrupt routine in the 2nd method above. Do not forget that the interrupt routine is probably using milliseconds and not seconds.
Also, do not forget to clear out the last value reported by the interrupt. No matter which of the above 2 approaches you take.
Also consider special cases. For instance, when you stop bicycling the interrupt will never fire. In your main loop you may have a second counter which, when exceeded, indicates that your speed is zero.
-
The code is already in micros to get a good resolution. Actually its for a motorcycle. Can you explain the 0kmh thing?Fabrizio Cinquino– Fabrizio Cinquino07/06/2016 06:15:10Commented Jul 6, 2016 at 6:15
-
I did not say in the answer, but, from what you said, I think the U8glib display library is taking too much time to execute and the code to calculate speed, not being robust, is failing. I think you need to change the code from counting revolutions to counting the time between revolutions. As for 0kmh, you need a second way of timing to indicate there has not been a revolution for a long time. Perhaps more than a dozen seconds. When this occurs, replace the last displayed speed with zero.st2000– st200007/06/2016 12:07:37Commented Jul 6, 2016 at 12:07
-
So i should use an interrupt that says time = x microseconds every impulse?Fabrizio Cinquino– Fabrizio Cinquino07/07/2016 14:44:51Commented Jul 7, 2016 at 14:44
-
That is the approach I would use. Remember to convert from ms to hours.st2000– st200007/07/2016 17:00:54Commented Jul 7, 2016 at 17:00
count how many times the magnet passes
. In your entire code, you never count the number of times the interrupt is fired. You're code assumes that the loop function is called at least as many times as the interrupt is fired. If the loop function takes longer, by e.g. using the GLCD library, multiple interrupts could have fired, leading toelapsedMicros
being a multiple of the value you expect. Leading to your code thinking the motor is running at half, or one-third, etc. the speed.