Hello there,
The project I am currently working on is a speedometer that measures the speed of a rotating wheel using a hall effect sensor. Whenever the magnet, placed on the wheel, passes the hall effect sensor, the program uses the time between the last two passes of the magnet to calculate the speed during that period.
Normally what happens is that when the sensor is triggered, the current time, millis() is stored to a variable called start_time. Then, when the sensor is triggered again, a variable, delta_t is calculated as the difference between the current time and start_time. Then start_time is set to the current time.
However, when triggering the hall effect sensor about 5 times a second, I get strange results. For some reason, delta_t will not resolve to any numbers between 190 and 260! Meaning the speedometer will read 13MPH, or 19MPH, but nothing in between.
Here is my code:
#include <SevenSeg.h>
// Give names to the pins to be used for each segment
int a_pin = 9;
int b_pin = 12;
int c_pin = 3;
int d_pin = 8;
int e_pin = 7;
int f_pin = 2;
int g_pin = 11;
int decimal_pin = 4;
// And the digit pins
const int num_of_digits = 3;
int digit_1 = 10;
int digit_2 = 6;
int digit_3 = 5;
int digit_pins[num_of_digits] = {digit_1, digit_2, digit_3};
int hall_effect_pin = 0;
// Initialize the seven segment display
SevenSeg disp(a_pin, b_pin, c_pin, d_pin, e_pin, f_pin, g_pin);
// Useful variables for counting rotations.
volatile long start_time = 0;
volatile long delta_t = 20000;
// Size of the wheel and various helpful constants
// Change wheel_diameter_inches to whatever is needed
float wheel_diameter_inches = 20.0;
float wheel_circumference_inches = wheel_diameter_inches * 3.141592;
float inches_per_mile = 63360.0;
float current_mph = 0;
volatile bool triggered = false;
void setup() {
Serial.begin(9600);
// Tell the library what common pins to use for digits, and what pin is for the decimal point
disp.setDigitPins(num_of_digits, digit_pins);
disp.setDPPin(decimal_pin);
disp.setDigitDelay(1000);
// Use the hall effect pin as an input
pinMode(hall_effect_pin, INPUT);
// Draws a fun opening animation
String intro_string = " SPEEDOTRON 2000 ";
while (millis() <= (intro_string.length()-2)*200){
int first_letter_index = round(millis() / 200);
disp.write(intro_string.substring(first_letter_index, first_letter_index + 3));
}
}
void loop() {
bool hall_effect_state = digitalRead(hall_effect_pin);
if (hall_effect_state == LOW and !triggered){
trigger();
count_revolution();
} else if (hall_effect_state == HIGH){
triggered = false;
}
// Update display every second
current_mph = convert_delta_t_to_mph(delta_t);
//If there is more than 2 seconds with no revolutions, the speed is 0 mph
if (millis() - start_time > 2000){
current_mph = 0.0;
}
// Write the speed to the 7 segment display
disp.write(current_mph);
delay(5);
}
void count_revolution(){
// Whenever the revolution happens, mark down how long it took to turn, and set the new start time
if (millis() - start_time > 100){
delta_t = millis() - start_time;
//Serial.println(delta_t);
start_time = millis();
}
Serial.print("Delta t: ");
Serial.print(delta_t);
Serial.print(" - MPH: ");
Serial.println(convert_delta_t_to_mph(delta_t));
}
void trigger(){
triggered = true;
}
float convert_delta_t_to_mph(float delta_t){
// This takes the time between the revolutions and returns the speed calculated from it
float delta_t_seconds = delta_t / 1000.0;
float in_per_second = wheel_circumference_inches / delta_t_seconds;
float in_per_hour = in_per_second * 3600.0;
float mi_per_hour = in_per_hour / inches_per_mile;
float miles_per_hour_rounded = round(100 * mi_per_hour) / 100.0;
return(miles_per_hour_rounded);
}
And here is a sample of the serial output. Notice the lack of numbers between 190 and 260
12:31:16.630 -> Delta t: 5321 - MPH: 0.67
12:31:16.809 -> Delta t: 184 - MPH: 19.40
12:31:16.972 -> Delta t: 184 - MPH: 19.40
12:31:17.160 -> Delta t: 175 - MPH: 20.40
12:31:17.356 -> Delta t: 184 - MPH: 19.40
12:31:17.804 -> Delta t: 459 - MPH: 7.78
12:31:18.145 -> Delta t: 358 - MPH: 9.97
12:31:18.328 -> Delta t: 185 - MPH: 19.30
12:31:18.522 -> Delta t: 184 - MPH: 19.40
12:31:18.709 -> Delta t: 174 - MPH: 20.52
12:31:18.993 -> Delta t: 267 - MPH: 13.37
12:31:19.220 -> Delta t: 268 - MPH: 13.32
12:31:19.433 -> Delta t: 184 - MPH: 19.40
12:31:19.591 -> Delta t: 174 - MPH: 20.52
12:31:20.140 -> Delta t: 544 - MPH: 6.56
12:31:20.680 -> Delta t: 532 - MPH: 6.71
12:31:20.840 -> Delta t: 184 - MPH: 19.40
12:31:21.041 -> Delta t: 184 - MPH: 19.40
12:31:21.220 -> Delta t: 175 - MPH: 20.40
12:31:21.417 -> Delta t: 184 - MPH: 19.40
12:31:21.676 -> Delta t: 268 - MPH: 13.32
12:31:22.012 -> Delta t: 358 - MPH: 9.97
12:31:22.484 -> Delta t: 459 - MPH: 7.78
12:31:22.870 -> Delta t: 367 - MPH: 9.73
12:31:23.120 -> Delta t: 267 - MPH: 13.37
12:31:23.286 -> Delta t: 183 - MPH: 19.51
12:31:23.490 -> Delta t: 175 - MPH: 20.40
12:31:23.677 -> Delta t: 184 - MPH: 19.40
12:31:23.836 -> Delta t: 175 - MPH: 20.40
12:31:24.020 -> Delta t: 185 - MPH: 19.30
12:31:24.189 -> Delta t: 175 - MPH: 20.40
12:31:24.749 -> Delta t: 552 - MPH: 6.47
12:31:24.932 -> Delta t: 184 - MPH: 19.40
12:31:25.104 -> Delta t: 175 - MPH: 20.40
12:31:25.385 -> Delta t: 266 - MPH: 13.42
Even when the 7 segment display is disabled, the problem still persists! I am at a loss as to what could cause this discrepancy. Any help is appreciated!
Note: The measurements are mostly accurate below delta_t=170
EDIT: The board is an Arduino Leonardo. The hall effect sensor is an AH1815 non latching hall effect sensor (https://cdn.sparkfun.com/assets/4/4/8/2/a/AH1815.pdf). Pins 1, 2, and 3 of the sensor are connected to 5V, GND, and digital pin 0, respectively. There is a pullup resistor between digital pin 0 and 5V, and a 10nf capacitor between 5V and GND.