/* PhototransistorVoltage Solar Car Timer by Nelson Farrier
* Power each phototransistor with 5v and GND
* Connect the 2 phototransistors yellow wires
* into A0 & A1 to detect start and stop of car.
* Use 4 pins (below) to indicate laser alignment
* Use 4 analog pins (A0-A3) for detecting photo transistor voltage
*/
#include <LiquidCrystal_I2C.h> // Must be downloaded separtely & put in your Arduino's libraries folder
/*----- LCD Pin configuration-----*/
//GND - GND
//VCC - 5V
//SDA - ANALOG Pin 4
//SCL - ANALOG pin 5
LiquidCrystal_I2C lcd(0x27, 16, 2);
const boolean testing = false;
const int align1Pin = 8; // pin to show laser is on 1st mark
const int align2Pin = 9; // pin to show laser is on 2nd mark
const int align3Pin = 10; // pin to show laser is on 1st mark
const int align4Pin = 11; // pin to show laser is on 2nd mark
const int interval = 10; // accuracy of timer in milliseconds
float threshold = 0.75; // voltage where phototransistor shows car is in the way
float v1, v2, v3, v4, timer1Count, timer2Count;
boolean A, B, C, D, doneLtiming, doneRtiming, triggeredL, triggeredR, overLmtL, overLmtR, statusLCDshown, statusRshown, statusLshown, finishLshown, finishRshown; // A & C on one lane, B & D on other
int count=0, msg = 0;
char inSerial[15];
const int StartL = 1;
const int StartR = 2;
const int FinishL = 3;
const int FinishR = 4;
const int leftLane = 0;
const int rightLane = 1;
const float overtime = 60000; // 1 minute
// bluetooth codes
const int Reset = 9;
const int Other = 10;
void setup() // Built-in initialization block
{
Serial.begin(9600); // Set data rate to 9600 bps
pinMode(align1Pin,OUTPUT);
pinMode(align2Pin,OUTPUT);
pinMode(align3Pin,OUTPUT);
pinMode(align4Pin,OUTPUT);
Serial.println("!Waiting to connect to Bluetooth...");
lcd.begin();
lcd.clear();
lcd.setCursor(16,2);
lcd.backlight();
lcd.setCursor(0 ,0);
}
void loop() {
lcd.setCursor(16,2); // initialize the lcd for 16 chars 2 lines, turn on backlight
lcd.backlight();
A = B = C = D = doneLtiming = doneRtiming= triggeredL = triggeredR = overLmtL = overLmtR = statusLCDshown = false; // A & C on one lane, B & D on other
finishLshown = finishRshown = statusLshown = statusRshown = false;
boolean wait = true;
waitForAlignment();
timer1Count = 0;
timer2Count = 0;
count = 0;
delay(1000);
Serial.print("!Ready...");
lcd.clear();
lcd.setCursor(0 ,0); //Start at character 4 on line 0
lcd.print("Ready...");
delay(1000);
Serial.println("Set...");
lcd.print("Set...");
while ((!doneLtiming) || (!doneRtiming)) {
if (triggeredL || triggeredR) {
if (!statusLCDshown) {
lcd.setCursor(0 ,1);
lcd.print("Race Started!");
if (testing) {
Serial.println(A);
Serial.println(B);
Serial.println(C);
Serial.println(D);
}
statusLCDshown = true;
}
if ((triggeredL) && (!statusLshown)) {
Serial.println("Race started in left lane");
statusLshown = true;
}
if ((triggeredR) && (!statusRshown)) {
Serial.println("Race started in right lane");
statusRshown = true;
}
}
if (triggeredL && !doneLtiming) { // add interval to timer because L lane has started
timer1Count = timer1Count+interval;
}
if (triggeredR && !doneRtiming) { // add interval to timer because R lane has started
timer2Count = timer2Count+interval;
}
if (timer1Count > overtime) {
doneLtiming = overLmtL = true;
}
if (timer2Count > overtime) {
doneRtiming = overLmtR = true;
}
v1 = volts(A0);
v2 = volts(A1);
v3 = volts(A2);
v4 = volts(A3);
if (v1 < threshold) { digitalWrite(align1Pin, LOW); } // turn off (and leave off) LED's as they are triggered
if (v2 < threshold) { digitalWrite(align2Pin, LOW); }
if (v3 < threshold) { digitalWrite(align3Pin, LOW); }
if (v4 < threshold) { digitalWrite(align4Pin, LOW); }
if (!triggeredL) {
triggeredL = (v1 < threshold) || (v3 < threshold); // initial trigger L (front or back)
A = (v1 < threshold);
C = (v3 < threshold);
}
else {
if (A) { // final trigger L (front or back)
if (v3 < threshold) {
doneLtiming = true;
if (!finishLshown) {
Serial.println("Left lane finished");
showLaneTime(leftLane,timer1Count,overLmtL);
finishLshown = true;
}
}
}
if (C) {
if (v1 < threshold) {
doneLtiming = true;
if (!finishLshown) {
Serial.println("Left lane finished");
showLaneTime(leftLane,timer1Count,overLmtL);
finishLshown = true;
}
}
}
}
if (!triggeredR) {
triggeredR = (v2 < threshold) || (v4 < threshold); // initial trigger R (front or back)
B = (v2 < threshold);
D = (v4 < threshold);
}
else {
if (B) { // final trigger R (front or back)
if (v4 < threshold) {
doneRtiming = true;
if (!finishRshown) {
Serial.println("Right lane finished");
showLaneTime(rightLane,timer2Count,overLmtR);
finishRshown = true;
}
}
}
if (D) {
if (v2 < threshold) {
doneRtiming = true;
if (!finishRshown) {
Serial.println("Right lane finished");
showLaneTime(rightLane,timer2Count,overLmtR);
finishRshown = true;
}
}
}
}
delay(interval); // Delay for defined time
}
// end timer count and display results
flashScreen();
delay(80);
if (testing) {
Serial.print(triggeredL);
Serial.print(triggeredR);
Serial.print(doneLtiming);
Serial.println(doneRtiming);
}
Serial.println("!Race Complete");
showLaneTime(leftLane,timer1Count,overLmtL);
showLaneTime(rightLane,timer2Count,overLmtR);
Serial.println(""); // print blank line
//loop until bluetooth "Reset" sent or rebooted
while (wait) {
int i=0;
int m=0;
delay(500);
if (Serial.available() > 0) {
while (Serial.available() > 0) {
inSerial[i]=Serial.read();
i++;
}
inSerial[i]='\0';
msg = Check_Protocol(inSerial);
wait = (! msg == Reset);
if (msg == Reset) {
flashLED(8);
}
}
}
}
//-----------------------------------------
void showLaneTime(int lane, float timerCount, boolean overLmt) {
if (lane == leftLane) {
Serial.print("Left Lane Time: ");
lcd.setCursor(0,0);
lcd.print("L Time=");
} else {
Serial.print("Right Lane Time: ");
lcd.setCursor(0,1);
lcd.print("R Time=");
}
if (!overLmt) {
Serial.print(timerCount/1000); // Display timerCount in #.## format
Serial.println(" sec");
lcd.print(timerCount/1000);
lcd.println(" sec ");
}
else {
Serial.print("past limit");
lcd.println(" past lmt ");
}
}
float volts(int adPin) // Measures volts at adPin
{ // Returns floating point voltage
return float(analogRead(adPin)) * 5.0 / 1024.0;
}
void flashScreen() {
for(int i = 0; i< 3; i++)
{
lcd.backlight();
delay(150);
lcd.noBacklight();
delay(150);
}
lcd.backlight(); // finish with backlight on
}
int Check_Protocol(char inStr[]){
int i=0;
int m=0;
uint32_t c=0; // color of bounce
Serial.println(inStr);
if (!strcmp(inStr,"Reset")){ //Reset system
//Serial.println("Reset");
return Reset;
for(m=0;m<11;m++){
inStr[m]=0;}
i=0;
}
if (!strcmp(inStr,"other")){
Serial.println("Other");
return Other;
for(m=0;m<11;m++){
inStr[m]=0;}
i=0;
}
else{
for(m=0;m<11;m++){
inStr[m]=0;}
i=0;
}
}
void flashLED(int pinNum) {
digitalWrite(pinNum, LOW);
delay(200);
digitalWrite(pinNum, HIGH);
delay(200);
digitalWrite(pinNum, LOW);
delay(200);
digitalWrite(pinNum, HIGH);
delay(200);
digitalWrite(pinNum, LOW);
delay(200);
digitalWrite(pinNum, HIGH);
delay(200);
digitalWrite(pinNum, LOW);
}
void waitForAlignment() {
boolean Start1 = false;
boolean Start2 = false;
boolean Finish1 = true;
boolean Finish2 = true;
Serial.println("!Checking Laser Alignment..."); // wait for either phototransistor to be dimmed
lcd.clear();
lcd.setCursor(0 ,0); //Start at character 1 on line 0
lcd.print("Checking Laser");
lcd.setCursor(0 ,1); //Start at character 1 on line 1
lcd.print("Alignment...");
delay(2000);
boolean done = false;
lcd.clear();
while (!done) {
v1 = volts(A0);
digitalWrite(align1Pin, !(v1 < threshold));
Start1 = !(v1 < threshold);
alignmentCheck(Start1,StartL,v1);
if (testing) {
Serial.print( " ");
Serial.print(v1); // Display measured A0 volts
Serial.println(" volts ");
}
v2 = volts(A1);
digitalWrite(align2Pin, !(v2 < threshold));
Start2 = !(v2 < threshold);
alignmentCheck(Start2,StartR,v2);
if (testing) {
Serial.print( " ");
Serial.print(v2); // Display measured A1 volts
Serial.println(" volts ");
}
v3 = volts(A2);
digitalWrite(align3Pin, !(v3 < threshold));
Finish1 = !(v3 < threshold);
alignmentCheck(Finish1,FinishL,v3);
if (testing) {
Serial.print( " ");
Serial.print(v3); // Display measured A2 volts
Serial.println(" volts ");
}
v4 = volts(A3);
digitalWrite(align4Pin, !(v4 < threshold));
Finish2 = !(v4 < threshold);
alignmentCheck(Finish2,FinishR,v4);
if (testing) {
Serial.print( " ");
Serial.print(v4); // Display measured A3 volts
Serial.println(" volts ");
}
Serial.println(" ");
delay(500); // Delay for 0.5 seconds
done = (Start1 && Start2 && Finish1 && Finish2);
}
Serial.println("!Lasers Aligned"); // wait for either phototransistor to be dimmed
lcd.clear();
lcd.setCursor(0 ,0); //Start at character 4 on line 0
lcd.print("Lasers Aligned");
delay(2000);
}
void alignmentCheck(boolean aligned, int section, float v) {
String fullTextOut, smTextOut;
if (section == StartL) {
fullTextOut = "Left Start";
smTextOut = "A";
lcd.setCursor(0, 0);
}
if (section == StartR) {
fullTextOut = "Right Start";
smTextOut = "B";
lcd.setCursor(8, 0);
}
if (section == FinishL) {
fullTextOut = "Left Finish";
smTextOut = "C";
lcd.setCursor(0, 1);
}
if (section == FinishR) {
fullTextOut = "Right Finish";
smTextOut = "D";
lcd.setCursor(8, 1);
}
if (aligned) {
Serial.println(fullTextOut+" Aligned");
lcd.print(smTextOut+"=OK ");
}
else {
Serial.print(fullTextOut+"="); // Display "Ax = "
lcd.print(smTextOut+"=");
Serial.print(v); // Display measured Ax volts
Serial.println(" volts "); // Display " volts" & newline
lcd.print(v); // Display measured Ax volts
lcd.print("v "); // Display " volts" & newline
}
}
Comments