Help with multiple timers activated by sensors

I’ve created a timer system for a dirt drag racing track. It consists of four lasers and photo-resistors to sense the start and end of the track. The hardware side of things works fine, the voltage from each sensor increases to about 5v while the beam is blocked.

My program is giving me issues with counting the time after the first beam is broken until the end beam is broken. The main issue seems to be that once the start sensor of one lane is triggered, the program gets stuck in that void for either left or right, and then doesn’t actually count. Everything needs to run simultaneously for this to work. I also have an additional set of beams at the end in order to calculate speed at the end, but if i can get the timing to work first i’ll be able to implement that later.

/* 
 *  Drag Strip Timer 
 *  
 *  October 8, 2019
 *  A0 = sLeft, A1 = eLeft, A2 = sRight, A3 = eRight, A4 = mphLeft, A5 = mphRight
*/

int ambLight;
int startRight;
int startLeft;
int endRight;
int endLeft;
int stage;
int start = 0;
int timeLeft = 0;
int timeRight = 0;
int mphTimeLeft;
int mphTimeRight;
int mphLeft;
int mphRight;
int amb0;
int amb1;
int amb2;
int amb3;

const int mphDist = 2;  //distance betwwen end time beam and mph beam in ft
int done = 0;

const unsigned long interval = 10;

void setup() {

Serial.begin(9600);

pinMode(2, INPUT);

amb0 = analogRead(A0);
amb1 = analogRead(A1);
amb2 = analogRead(A2);
amb3 = analogRead(A3);

Serial.print("Ambient Light level: ");
Serial.print(ambLight);

}

void loop() {

  
  left();
  right();
  win();

}

void left() {

  boolean state = false;
  unsigned long currentTime = millis();
  unsigned long previousTime = 0;

  if (analogRead(A0) > (amb0 + 50)) {
      Serial.println("left start");
      state = true;

  }
  
    

   while (state == true) {

      if (currentTime - previousTime >= interval) {

          timeLeft = timeLeft +.01;

          previousTime = currentTime;
        Serial.println("count");
      }
     if (analogRead(A1) > (amb1 + 50)) {
    state = false;
     done = done+1;
     Serial.println("left end");
   }
   
   }

}

void right() {
  boolean state = false;
  unsigned long currentTime = millis();
  unsigned long previousTime = 0;

  if (analogRead(A2) > (amb2 + 50)) {
      Serial.println("right start");
      state = true;

  }
 
   while (state == true) {

      if (currentTime - previousTime >= interval) {

          timeLeft = timeLeft +.01;

          previousTime = currentTime;
        
      }
     if (analogRead(A3) > (amb3 + 50)) {
    state = false;
    done = done+1;
    Serial.println("right end");
   }

   }
}

void win() {

if (done >= 2) {

  
     if (timeLeft < timeRight) {
    
    Serial.println("Left -- WIN");
    Serial.println("300ft -- ");
    Serial.print(timeLeft);
    Serial.print(" @ ");
    Serial.print(mphLeft);
    Serial.print(" MPH");
    Serial.println("__________________________________________");


    Serial.println("Right:");
    Serial.println("300ft -- ");
    Serial.print(timeRight);
    Serial.print(" @ ");
    Serial.print(mphRight);
    Serial.print(" MPH");
    done = 0;
    
    }
    else if (timeRight < timeLeft) {
    
    Serial.println("Right -- WIN");
    Serial.println("300ft -- ");
    Serial.print(timeRight);
    Serial.print(" @ ");
    Serial.print(mphRight);
    Serial.print(" MPH");
    Serial.println("__________________________________________");


    Serial.println("Left:");
    Serial.println("300ft -- ");
    Serial.print(timeLeft);
    Serial.print(" @ ");
    Serial.print(mphLeft);
    Serial.print(" MPH");
    done = 0;
    }

    else {

        Serial.println("Time Error");
        done = 0;
      
    }
  }

}

This type of program usually best addressed with a state machine. You have 3 states for a track: WAIT_FOR_START, WAIT_FOR_END, FINISHED

You start in the WAIT_FOR_START state and wait for the runner to cross the beam. When he does, you note the time and go to state WAIT_FOR_END. When the end beam is crossed, you calculate the duration and move to the FINISHED state;

You do this for both tracks.

when both runners are in the FINISHED state you print the results. (you might not want to wait for the second one to arrive, just a decision to make)

This is totally untested and typed here, but that could look like this (assuming your ambient light detection thingy works as you said):

const byte leftTrackStartPin = A0;
const byte leftTrackEndPin = A1;
const byte rightTrackStartPin = A2;
const byte rightTrackEndPin = A3;

int ambientLightLeftTrackStart;
int ambientLightLeftTrackEnd;
int ambientLightRightTrackStart;
int ambientLightRightTrackEnd;

enum trackStatus_t : byte {WAIT_FOR_START, WAIT_FOR_END, FINISHED};
trackStatus_t leftRunnerStatus ;
trackStatus_t rightRunnerStatus;

unsigned long leftRunnerChrono;
unsigned long rightRunnerChrono;

void prepareRun()
{
  leftRunnerStatus  = WAIT_FOR_START;
  leftRunnerChrono = 0;
  rightRunnerStatus = WAIT_FOR_START;
  rightRunnerChrono = 0;
  // read twice the analog value as switching pin quickly may result in misread
  ambientLightLeftTrackStart  = (analogRead(leftTrackStartPin), analogRead(leftTrackStartPin));
  ambientLightLeftTrackEnd    = (analogRead(leftTrackEndPin), analogRead(leftTrackEndPin));
  ambientLightRightTrackStart = (analogRead(rightTrackStartPin), analogRead(rightTrackStartPin));
  ambientLightRightTrackEnd   = (analogRead(rightTrackEndPin), analogRead(rightTrackEndPin));
}

void setup()
{
  Serial.begin(115200);
  prepareRun();
}

void loop()
{
  switch (leftRunnerStatus) {
    case WAIT_FOR_START:
      if (analogRead(leftTrackStartPin) > (ambientLightLeftTrackStart + 50)) {
        leftRunnerChrono = millis();
        leftRunnerStatus = WAIT_FOR_END;
      }
      break;
    case WAIT_FOR_END:
      if (analogRead(leftTrackStartPin) > (ambientLightLeftTrackEnd + 50)) {
        leftRunnerChrono = millis() - leftRunnerChrono;
        leftRunnerStatus = FINISHED;
      }
      break;
    default: break;
  }

  switch (rightRunnerStatus) {
    case WAIT_FOR_START:
      if (analogRead(rightTrackStartPin) > (ambientLightRightTrackStart + 50)) {
        rightRunnerChrono = millis();
        rightRunnerStatus = WAIT_FOR_END;
      }
      break;
    case WAIT_FOR_END:
      if (analogRead(rightTrackStartPin) > (ambientLightRightTrackEnd + 50)) {
        rightRunnerChrono = millis() - rightRunnerChrono;
        rightRunnerStatus = FINISHED;
      }
      break;
    default: break;
  }

  if ((leftRunnerStatus == FINISHED) && (rightRunnerStatus == FINISHED)) {
    Serial.print(F("Left chrono = "));
    Serial.println(leftRunnerChrono);
    Serial.print(F("Right chrono = "));
    Serial.println(rightRunnerChrono);
    
    if (rightRunnerChrono == leftRunnerChrono) {
      Serial.println(F("Same timing"));
    } else if (rightRunnerChrono > leftRunnerChrono) {
      Serial.println(F("Right wins"));
    } else {
      Serial.println(F("Left wins"));
    }
    prepareRun();
  }
}

Thanks for the suggestion, I will give it a try.