#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Initialize the LCD screen (address might differ, check your LCD documentation)
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Pin Definitions
const int hallPin = 2; // Hall effect sensor pin
const int voltagePin = A0; // Voltage divider pin
const int currentPin = A1; // ACS712 pin
// Variables for speed measurement
volatile unsigned int pulseCount = 0;
unsigned long lastTime = 0;
float wheelCircumference = 0.628; // Example wheel circumference in meters
float speed = 0; // Speed in km/h
// Variables for battery monitoring
float voltage = 0;
float current = 0;
float batteryCapacity = 10000; // in mAh, example value
float batteryRemaining = 100; // in percentage
void setup() {
lcd.init();
lcd.backlight();
pinMode(hallPin, INPUT);
attachInterrupt(digitalPinToInterrupt(hallPin), countPulses, RISING);
// Initial LCD display
lcd.setCursor(0, 0);
lcd.print("Speed: 0 km/h");
lcd.setCursor(0, 1);
lcd.print("Bat: 100% Range:");
Serial.begin(9600);
}
void loop() {
unsigned long currentTime = millis();
// Update speed every second (1000 ms)
if (currentTime - lastTime >= 1000) {
speed = calculateSpeed();
displaySpeed(speed);
// Read battery voltage and current
voltage = readVoltage();
current = readCurrent();
// Estimate remaining battery charge
batteryRemaining = estimateBatteryPercentage(voltage);
// Estimate remaining driving range
float remainingRange = calculateRemainingRange(batteryRemaining, current);
// Update LCD display
displayBatteryAndRange(batteryRemaining, remainingRange);
lastTime = currentTime;
pulseCount = 0;
}
}
// Interrupt Service Routine for Hall effect sensor
void countPulses() {
pulseCount++;
}
// Calculate speed based on pulse count
float calculateSpeed() {
float rpm = (pulseCount / 20.0) * 60; // Assume 20 pulses per revolution
float speed_mps = (rpm * wheelCircumference) / 60.0; // Speed in m/s
return speed_mps * 3.6; // Convert m/s to km/h
}
// Read battery voltage
float readVoltage() {
int sensorValue = analogRead(voltagePin);
float voltage = sensorValue * (5.0 / 1023.0) * 11; // Adjust the multiplier based on your voltage divider
return voltage;
}
// Read current from ACS712
float readCurrent() {
int sensorValue = analogRead(currentPin);
float current = (sensorValue - 512) * (5.0 / 1023.0) / 0.066; // For ACS712 30A module
return current;
}
// Estimate battery percentage based on voltage
float estimateBatteryPercentage(float voltage) {
// Adjust these values for your specific battery type
if (voltage >= 12.6) return 100;
else if (voltage >= 11.8) return 50;
else if (voltage >= 11.0) return 10;
return 0;
}
// Calculate remaining driving range based on current and battery percentage
float calculateRemainingRange(float batteryRemaining, float current) {
float batteryChargeAh = (batteryCapacity * (batteryRemaining / 100)) / 1000; // in Ah
if (current > 0) {
float rangeHours = batteryChargeAh / current; // Time in hours
float estimatedSpeed = speed; // km/h
return rangeHours * estimatedSpeed; // Remaining range in km
} else {
return 0; // No current consumption, infinite range
}
}
// Display speed on LCD
void displaySpeed(float speed) {
lcd.setCursor(0, 0);
lcd.print("Speed: ");
lcd.print(speed);
lcd.print(" km/h ");
}
// Display battery percentage and range on LCD
void displayBatteryAndRange(float batteryRemaining, float remainingRange) {
lcd.setCursor(0, 1);
lcd.print("Bat: ");
lcd.print(batteryRemaining);
lcd.print("% Range:");
lcd.print(remainingRange);
lcd.print(" km ");
}