//By Mike Freda - April 2020 - Original Code
//Modified by Stan Cap for different application - April 2023 - Again Thank you Mike you Star!
//Diecast Racing electronic finish line.
//Only accurate timing for each lane if start is triggered exactly same time for both cars. Please see below.
//2 Lane winning LED indication with Timer LCD displaying time from Start Trigger to crossing finish line trigger
//This code version for use with Momentary switch only - Normally closed to Normally opened back to Normally closed - Such as a momentary footswitch.
//Timing starts when switch is triggered from N/C to N/O. (Either of the footswitches power their relay that opens circuit) This Code Version is modified for momentary swithch to trigger start at first press and not to reset when let go.
//When Both relay and solenoids work on one footswitch time is accurate for both cars
//When Drag racing with staging and footswitch time will start with fastest footswitch and first car to cross finish. This will not mean it matches lane, footswitch and winning car time. So for accuracy of time only use one lane testing or on footswitch trigger for both relays.
//Time is triggered with first press of a Momentary Footswitch. Normally closed to Open for trigger (breaking 5V HIGH) then back to 5V HIGH when swithc is let go back into normally closed state.
//First car to break IR beam is the lane winner
//Displays Elapsed time and winner on a 16x2 LCD.
//time stays displayed on LCD until next race is triggered - original code - times resets when start gate is closed.
//Calculated time is in microseconds and gets converted to Seconds when displayed. Races can be that close.
//Uses Gikfun 5mm 940nm IR LED's emitters and receivers: EK8443.
//HOW TO add LCD Library see - https://github.com/marcmerlin/NewLiquidCrystal or https://www.youtube.com/watch?v=M6PZOqNHKxM&t=0s
//Adding the LCD Library
#include <Wire.h>
#include <hd44780.h> //main hd44780 header.
#include <hd44780ioClass/hd44780_I2Cexp.h>
hd44780_I2Cexp lcd;//By Mike Freda - April 2020
int analogOutPin1 = A1; //finish line beam lane 1 on A1 PIN
int analogOutPin2 = A2; //finish line beam lane 2 on A2 PIN
const int ledPin1 = 11; //lane 1 winning LED on D11 PIN
const int ledPin2 = 12; //Lane 2 winning LED in D12 PIN
int StartSwitch = 2;
int sensorValueFinish1 = 0;
int sensorValueFinish2 = 0;
int StartState = 1; // Relay is wired as normally closed as HIGH 5V 1 = HIGH 5V - So StartState as 1 means there is a 5V HIGH on Arduino Pin 2 or also known as D2
int sensorThresh = 500; //Sets the trigger sensing threshold of the IR receivers. ~1000 = high
unsigned long timeLane1; //finish line lane 1
unsigned long timeLane2; //finish line lane 2
float StartTime = 0;
float ET1 = 0;
float ET2 = 0;
void setup()
{
Serial.begin(9600);
pinMode(StartSwitch, INPUT);
pinMode(ledPin1, OUTPUT); //lane 1
pinMode(ledPin2, OUTPUT); //lane 2
//Flash testing both lane LED's before start of Racing
delay(500);
digitalWrite(ledPin1, HIGH);
delay(500);
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
delay(500);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin1, HIGH);
delay(500);
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
delay(500);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin1, HIGH);
delay(500);
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
delay(500);
digitalWrite(ledPin2, LOW);
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, HIGH);
delay(500);
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
StartTime = 0;
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print("Version 2.0");
lcd.setCursor(0,1);
lcd.print("By: Mike Freda");
delay(2000);
lcd.setCursor(0,1);
lcd.print("Ready to race...");
}
void loop()
{
{
StartState = digitalRead(StartSwitch); //if Start, footswitch is pressed to open contact timer will start.
if(StartState == 0 && StartTime == 0)
{}
}
StartState = digitalRead(StartSwitch);
if(StartState == 0 && StartTime == 0)
{
StartTime = micros(); //use micro seconds since the races can be that close!
}
//Read the analog in value of IR's:
sensorValueFinish1 = analogRead(analogOutPin1);
sensorValueFinish2 = analogRead(analogOutPin2);
//DEBUGGING to see values - Do below
//remove "//" from below for Debugging and checking actual sensor values.
// You may have to adjust sensorThresh value for better accuracy.
// The sensors should read around 900-1000 then go "low" (less than 400) when a car passes through the beam.
//Serial.println(StartTime);
//Serial.println(StartState);
//Serial.print("Sensor Finish1 = " );
//Serial.println(sensorValueFinish1);
//Serial.print("Sensor Finish2 = " );
//Serial.println(sensorValueFinish2);
//delay(500);
//wait/check for the Finish Line sensors to be triggered
if(sensorValueFinish1 < sensorThresh && ET1 == 0)
{
timeLane1 = micros();
ET1 = timeLane1 - StartTime;
ET1 = ET1 / 1000000;
}
if(sensorValueFinish2 < sensorThresh && ET2 == 0)
{
timeLane2 = micros();
ET2 = timeLane2 - StartTime;
ET2 = ET2 / 1000000;
}
if (ET1 < ET2 && ET1 != 0 && ET2 != 0)// Set winner Lane 1, turn on winner LED
{
digitalWrite(ledPin1, HIGH);
}
if(ET1 > ET2 && ET2 != 0 && ET1 != 0) // Set winner Lane 2, turn on winner LED
{
digitalWrite(ledPin2, HIGH);
}
if(ET1 > 0 && ET2 > 0) // Race is over, display times for both lanes. // both cars have to finish to display times.
{
//WIN SECTION BELOW IS FOR LANE1 TIME AND POSSIBLE WIN SECTION
lcd.clear();
lcd.setCursor(0,0); //0 is first LCD block to display in and ,0 is to display in first or top line of LCD display
lcd.print("LANE1" );
lcd.setCursor(6,0);
lcd.print(ET1, 4); //The 4 after ET2 is how many decimal digits to display on LCD for microseconds
if (digitalRead(ledPin1) == HIGH)
//If LANE2 wins the below will prompt WIN display next to LANE2 time
{
lcd.setCursor(12,0);
lcd.print(" WIN");
}
//WIN SECTION BELOW IS FOR LANE2 TIME AND POSSIBLE WIN SECTION
lcd.setCursor(0,1); // 0 is first LCD block to display in and ,1 is to display in second line of LCD display
lcd.print("LANE2" );
lcd.setCursor(6,1);
lcd.print(ET2, 4); //The 4 after ET2 is how many decimal digits to display on LCD for microseconds
if (digitalRead(ledPin2) == HIGH)
//If LANE2 wins the below will prompt WIN display next to LANE2 time
{
lcd.setCursor(12,1);
lcd.print(" WIN");
}
delay(30000); //This is the time Lane Win LED indication will stay on - Adjust according to preference - currently it is 30 seconds
digitalWrite(ledPin1, LOW); //turn off lane winner LED
digitalWrite(ledPin2, LOW); //turn off lane winner LED
timeLane1= 0;
timeLane2= 0;
StartTime = 0;
ET1 = 0;
ET2 = 0;
}
}