Bicycle Speedometer

Arduino Project – Bicycle Speedometer with Hall Sensor

In this project, we will use a Hall sensor and an Arduino Nano to build a bicycle speedometer.

Hall sensor (or Hall effect sensor) is an electronic device that detects the presence and strength of a magnetic field. It works based on the Hall Effect, a principle discovered by physicist Edwin Hall. The principle states a magnetic field passing perpendicular to a current-carrying conductor, inside the sensor, will generate a small voltage (called Hall voltage). This voltage is measured and converted into a usable output signal.

There are two types of Hall sensors: digital hall sensor and analog hall sensor. In this project, we will use the digital hall sensor A3144.

Hardware Required

For more information, visit What is Arduino Nano? A Beginner’s Guide.

  • 9 V Battery
9V Battery
Battery Connector
  • 10k Ohm Resistor
  • Jumper Wires
  • 22 AWG Wire
  • Hot Glue Gun
  • Container

Working Principle

  • The hall sensor switches to a LOW digital signal when a magnetic field is detected. We will be recording the times of two consecutive LOW digital signals to get the time (T) it takes to complete one cycle of motion. 
  • Calculate the circumference (L) of the wheel. You can find the outer diameter on the tire. For example 26, 28 inches.

$$L=2πR=πD$$

  • Calculate the speed (v).

$$v=\frac{L}{T}$$

Diagram

Bicycle Speedometer Diagram

Setup

Bicycle Speedometer

1. Cut out a container to fit the electronic components

Make sure to have a hole for the LCD module, 4 legs of button, switch, and wires (Hole for wires shown on the side of the container below).

2. Prepare pin headers

Break off two pin headers with three pins. Cut jumper wires in half and strip the wire to expose the metal part. Solder the small side of the pin header with exposed wire.

Then, attach the red jumper to the 5V of the Arduino Nano. Attach the black wire to the GND of the Arduino Nano. This will allow us to connect multiple components to GND and 5V.

3. Connect the LCD Display to the Arduino Nano

Attach the LCD Display onto the container, so the display is visible, using hot glue.

Connect the LCD with the Arduino Nano following the table below.

LCD DisplayArduino Nano
GND (Brown)GND
VCC (Red)5V
SDA (Orange)A4
SCL (Yellow)A5

4. Connect the Hall Sensor to the Arduino Nano

Extend the jumper wires using 22 AWG wires, so the length of the wire can reach part of your bike next to the wheel. Cut the jumper wires in half and expose the metal on both wires.

After exposing the metal wire on both components, solder them together to obtain 3 long wires.

Cover exposed wires.

Insert the three wires through the holes made in the container.

Connect the Hall Sensor with the Arduino Nano using the 3 wires.

Hall SensorArduino Nano
– (Brown)GND
+ (Red)5V
S (Orange)D5

5. Connect the Push Button to the Arduino Nano

Use two unconnected legs of the push button. There are 4 options shown below.

In this project, we use the following two legs.

Push ButtonResistorArduino Nano
Leg 1 (Red)5V
Leg 2 (Brown)10k Ohm Resistor (Black)GND
Leg 2 (Brown)D2

In order for Leg Two to connect to both the GND and D2, a split in the wire need to be made. First, strip the wire while making sure the wire isn’t cut.

Solder a 10k Ohm Resistor onto the bare wire.

Get another jumper wire and cut it in half. Expose its wire and solder it onto the other side of the 10k Ohm resistor.

Connect Leg 1 to 5V using a regular jumper wire. For Leg 2, attach the side with only one wire with the Leg. Then attach the black and brown wire to GND and D2 of the Arduino, respectively.

Hot glue the wire and button to make it stay.

6. Connect the battery connector to the Arduino Nano

Solder the red wire to one half of a jumper wire to ensure it can connect to a pin, if necessary. Solder the black wire onto the switch, and solder half a jumper wire onto the other side of the switch.

Attach the red and black jumper wires to the Arduino Nano as shown below. Put the switch in the hole made.

Battery ConnectorArduino Nano
+ (Red)Vin
– (Black)GND

7. Upload the program

Connect the Arduino to your computer using a USB cable. Upload the program to the Arduino through the Arduino IDE software. Visit Getting Started with Arduino IDE: A Beginner’s Guide to Coding and Creating for more information.

8. Store all electronic components in the container

Bicycle Speedometer
Bicycle Speedometer

9. Attach your container onto your bike

10. Attach your magnet on the side of the bike’s wheels

11. Attach the Hall Sensor onto the frame of your bike near the wheels so that the magnet and sensor are near each other

Code

#include <LiquidCrystal_I2C.h>

//Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

unsigned long millisValue = 0;
float Speed = 0;

// Circumference of bicycle wheel expressed in centimeters
float Wheel_Circumference = 220;  

int HallSensor_Last_state;
int HallSensor_Current_state;
unsigned long Time_last_turn = 0;
boolean isonMove = false;

unsigned long total_time = 0;
unsigned long distance = 0;

#define buttonPin 2
#define hallDigitalPin 5
int hallDigital;
int buttonState = 0;

void setup() {
  Serial.begin(9600);

  // Initialize the LCD
  lcd.init();
  // Turn on the backlight
  lcd.backlight();

  pinMode(hallDigitalPin, INPUT);  
  pinMode(buttonPin, INPUT);  

  // Read the last state of the hall sensor
  HallSensor_Last_state = digitalRead(hallDigitalPin);
}

void loop() {

  // Read the state of the button
  buttonState = digitalRead(buttonPin);

  // Read the current state of the hall sensor
  HallSensor_Current_state = digitalRead(hallDigitalPin);

  // Clear data if the push button is pressed
  if (buttonState == HIGH){
    total_time = 0;
    distance = 0;
  }

  // millis() returns the number of milliseconds since the Arduino board began running the current program
  if (millis() - Time_last_turn > 3000){  // If stop moving for 3 seconds
    Speed = 0;
    isonMove = false;
  }

  // The hall sensor switches to a LOW digital signal when a magnetic field is detected
  if(HallSensor_Last_state == HIGH && HallSensor_Current_state == LOW) {
    millisValue = millis();

    if (isonMove){
      Speed = float(Wheel_Circumference) / float(millisValue - Time_last_turn);
      total_time += millisValue - Time_last_turn;
      distance += Wheel_Circumference;

      Serial.print(distance);
      Serial.print("   ");
      Serial.print(total_time);
      Serial.print("   ");
      Serial.println(Speed);

    } else {
      isonMove = true;
    }

    // Update the time of last turn
    Time_last_turn = millisValue;
  }
  
  // Update the last state of the hall sensor
  HallSensor_Last_state = HallSensor_Current_state;
  print();
}

void print() {
  float speed_for_display = Speed * 36;   // Convert cm/millisecond to km/h
  float distance_in_km = float(distance) / 100000.00;  // Convert cm to km
  int hour_for_display = int(total_time / 3600000);  // Calculate hours
  int min_for_display = int((total_time - hour_for_display * 3600000) / 60000);  // Calculate minutes
  int sec_for_display = int((total_time - hour_for_display * 3600000 - min_for_display * 60000) / 1000);  // Calculate seconds

  // Print Speed
  lcd.setCursor(0, 0);
  lcd.print("S ");
  if (speed_for_display < 10){
    lcd.print(" ");
  }
  lcd.print(speed_for_display);

  // Print Distance
  lcd.setCursor(9, 0);
  lcd.print("D ");
  if (distance_in_km < 10){
    lcd.print(" ");
  }
  lcd.print(distance_in_km);

  // Print Total Time (HH:MM:SS)
  lcd.setCursor(0, 1);
  lcd.print("T ");
  if (hour_for_display < 10){
    lcd.print("0");
  }
  lcd.print(hour_for_display); 
  lcd.print(":");
  if (min_for_display < 10){
    lcd.print("0");
  }
  lcd.print(min_for_display);
  lcd.print(":");
  if (sec_for_display < 10){
    lcd.print("0");
  }
  lcd.print(sec_for_display);

}