#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ---------------- CONFIGURATION ---------------- //
// Set to HIGH if sensors trigger on HIGH, LOW if sensors trigger on LOW
#define TRIGGER_STATE LOW
// Pin assignments
const int car1SensorPin = 2; // Car 1 IR sensor
const int car2SensorPin = 3; // Car 2 IR sensor
const int buttonPin = 4; // Start/reset button
// LCD configuration
LiquidCrystal_I2C lcd(0x27, 16, 2); // Adjust address (0x27 or 0x3F)
// ---------------- VARIABLES ---------------- //
bool raceActive = false; // Flag: is race running?
unsigned long startTime = 0; // Time when race started
bool car1Finished = false;
bool car2Finished = false;
float car1Time = 0;
float car2Time = 0;
// ---------------- SETUP ---------------- //
void setup() {
Serial.begin(9600);
pinMode(car1SensorPin, INPUT_PULLUP);
pinMode(car2SensorPin, INPUT_PULLUP);
pinMode(buttonPin, INPUT_PULLUP); // Button with pull-up
lcd.init();
lcd.backlight();
startMessage(); // Show start message
}
// ---------------- MAIN LOOP ---------------- //
void loop() {
// Wait for button press to start/reset race
if (digitalRead(buttonPin) == LOW && !raceActive) {
delay(50); // Debounce
if (digitalRead(buttonPin) == LOW) {
while (digitalRead(buttonPin) == LOW)
; // Wait for release
startRace();
Serial.println("Start Race");
}
}
// Check both sensors
if (raceActive) {
// Check if both sensors triggered same time
if (digitalRead(car1SensorPin) == TRIGGER_STATE && digitalRead(car2SensorPin) == TRIGGER_STATE) {
car1Finished = true;
car2Finished = true;
car1Time = (millis() - startTime) / 1000.0;
}
else if (!car1Finished && digitalRead(car1SensorPin) == TRIGGER_STATE) {
car1Finished = true;
car1Time = (millis() - startTime) / 1000.0;
Serial.print("car 1 Time:");
Serial.println(car1Time);
}
if (!car2Finished && digitalRead(car2SensorPin) == TRIGGER_STATE) {
car2Finished = true;
car2Time = (millis() - startTime) / 1000.0;
Serial.print("car 2 Time:");
Serial.println(car2Time);
}
// Decide winner once at least one finishes
if (car1Finished || car2Finished) {
raceActive = false;
showResult();
}
}
}
// ---------------- FUNCTIONS ---------------- //
// Display Start Message
void startMessage() {
lcd.clear(); // Clear Display
lcd.setCursor(0, 0);
lcd.print("Press Button...");
lcd.setCursor(0, 1);
lcd.print("for New Race");
}
// Start a new race
void startRace() {
// Before new race reset the variables
raceActive = true;
car1Finished = false;
car2Finished = false;
car1Time = 0;
car2Time = 0;
startTime = millis();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Race Started! ");
lcd.setCursor(0, 1);
lcd.print("Go Cars Go! ");
}
// Show race result on LCD
void showResult() {
lcd.clear();
Serial.println("Show Result");
// Compare the time of each car to decide the winner
if (car1Finished) {
lcd.setCursor(0, 0);
lcd.print("Car 1 Wins!");
lcd.setCursor(0, 1);
lcd.print("Time: ");
lcd.print(car1Time, 2);
lcd.print(" s");
Serial.println("Car 1 wins");
Serial.println(car1Time);
} else if (car2Finished) {
lcd.setCursor(0, 0);
lcd.print("Car 2 Wins!");
lcd.setCursor(0, 1);
lcd.print("Time: ");
lcd.print(car2Time, 2);
lcd.print(" s");
Serial.println("Car 2 wins");
} else if (car2Time == car1Time) {
lcd.setCursor(0, 0);
lcd.print("It's a Tie!");
lcd.setCursor(0, 1);
lcd.print("Both: ");
lcd.print(car1Time, 2);
lcd.print(" s");
Serial.println("It's a tie");
}
delay(2000); // wait for 2 seconds
}