#include <LiquidCrystal_I2C.h>
#define UNCALIBRATED_LASER_INDICATOR_LED 33
#define CALIBRATED_LASER_INDICATOR_LED 32
#define LAP_INDICATOR_LED 34
#define LDR_1 16
#define LDR_2 4
#define BUTTON_CALIBRATE 13
bool calibrated;
bool calibrate_button;
int calibrated_value;
int tolerance = 150;
LiquidCrystal_I2C lcd(0x27, 16, 2);
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
int buttonState;
int lastButtonState = LOW;
unsigned long last_time_lap = 0;
unsigned long lap_time_before = 0;
void setup()
{
pinMode(UNCALIBRATED_LASER_INDICATOR_LED, OUTPUT);
pinMode(CALIBRATED_LASER_INDICATOR_LED, OUTPUT);
pinMode(LAP_INDICATOR_LED, OUTPUT);
pinMode(LDR_1, INPUT);
pinMode(LDR_2, INPUT);
pinMode(BUTTON_CALIBRATE, INPUT);
Serial.begin(9600);
lcd.init();
initial_message();
calibrated = false;
calibrate_button = false;
calibrated_value = 0;
}
void loop()
{
calibrated_led();
see_if_to_calibrate();
if (!calibrated && calibrate_button) {
calibrate();
last_time_lap = millis();
calibrated_message();
Serial.print("Calibrated value: ");
Serial.println(calibrated_value);
}
if (calibrated) {
bool new_lap = detect_laser_off();
// Ensure a minimum lap time of 2 seconds (for testing purposes).
if (new_lap && (millis() - last_time_lap > 2000)) {
lap_time_before = get_lap();
lap_mode_message(lap_time_before);
lap_led();
Serial.print("Last Lap: ");
Serial.println(lap_time_before);
}
}
}
void calibrate() {
calibrating_message();
calibrated_value = analogRead(LDR_1) + analogRead(LDR_2);
delay(5000);
int new_value_ldr = analogRead(LDR_1) + analogRead(LDR_2);
tolerance = abs(new_value_ldr - calibrated_value) / 2;
if (abs(calibrated_value - new_value_ldr) <= tolerance) {
calibrated = true;
calibrate_button = false;
} else {
calibrated = false;
Serial.println("Calibration failed, retrying...");
}
}
void calibrated_led() {
digitalWrite(UNCALIBRATED_LASER_INDICATOR_LED, !calibrated);
digitalWrite(CALIBRATED_LASER_INDICATOR_LED, calibrated);
}
void see_if_to_calibrate() {
int reading = digitalRead(BUTTON_CALIBRATE);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == HIGH) {
calibrated = false;
calibrate_button = true;
calibrated_value = 0;
}
}
}
lastButtonState = reading;
}
void lap_led() {
digitalWrite(LAP_INDICATOR_LED, HIGH);
delay(500);
digitalWrite(LAP_INDICATOR_LED, LOW);
}
void initial_message() {
lcd.clear();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("Press Button");
lcd.setCursor(2, 1);
lcd.print("To Calibrate");
}
void calibrating_message() {
lcd.clear();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("Calibrating");
lcd.setCursor(2, 1);
lcd.print("Please Wait");
}
void calibrated_message() {
lcd.clear();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("Calibrated");
lcd.setCursor(2, 1);
lcd.print("Ready");
}
void lap_mode_message(unsigned long lap_time) {
lcd.clear();
lcd.backlight();
lcd.setCursor(2, 0);
lcd.print("Last Lap:");
lcd.setCursor(2, 1);
lcd.print(lap_time / 60000);
lcd.print(":");
lcd.print((lap_time / 1000) % 60);
lcd.print(":");
lcd.print(lap_time % 1000);
}
unsigned long get_lap() {
unsigned long lap_time = millis() - last_time_lap;
last_time_lap = millis();
return lap_time;
}
bool detect_laser_off() {
int new_value_ldr = analogRead(LDR_1) + analogRead(LDR_2);
return new_value_ldr > (calibrated_value + tolerance);
}