Race car game way to time lanes required

I am developing a a car racing game to help my students with there hand-eye coordination. The children move their cars using magnets under a board. I have coded a christmas tree light starting system. There are only two lanes on the board. I have used infra red sensors at the start to check for false starts. I plan to use infra red break beam sensors to indicate when a car has finished. I need assistance with a way for the time of the cars to be indicated then the order of finishing indicated. I plan to use a mega and adafruit seven segment displays 1.2" with backpacks. The reset button needs to clear the displays and reset the timer.This code works with false starts being indicated however if there is a better way to do this please enlighten me.

int sensorPins[] = {29, 30, 31, 32, 33};
int sPinCount = 5;
int ledPins[] = {34, 35, 36, 37, 38, 39, 40, 41};
int lPinCount = 8;

void setup() {
  Serial.begin(9600);

  for (int thisPin = 0; thisPin < sPinCount; thisPin++) {
    pinMode(sensorPins[thisPin], INPUT_PULLUP);
  }

  for (int thisPin = 0; thisPin < lPinCount; thisPin++) {
    pinMode(ledPins[thisPin], OUTPUT);
  }

}

void loop() {
  //Checks (break beam sensors) to see if a car has raced and stops the timers.
  if (digitalRead(32) == LOW) {
    //record the time/elapsed time of car a
  }
  if (digitalRead(33) == LOW) {
    //record the time/elapsed time of car b
  }
  //Check if both cars have finished. If they have, the times are to be displayed for 5 seconds then the display needs to show  who was first and second.
  //if ((digitalRead(32) == LOW)&&(digitalRead(33) == LOW)){}

  //When start button is pushed Checks to see if cars are in starting positions. If yes start the light sequence.
  if ((digitalRead (29) == LOW) && ( digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
    // Resets displays and starts timer?
    //musicPlayer.playFullFile ("sye00001.mp3");
    digitalWrite(34, HIGH);  // White Led on for 2.5 seconds
    delay(2500);
    digitalWrite(34, LOW);   // White LED turns off
    delay(500);
    digitalWrite(35, HIGH); // 1st Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(35, LOW);   // LED turns off
    delay(500);
    digitalWrite(36, HIGH); // 2nd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(36, LOW);   // LED turns off
    delay(500);
    digitalWrite(37, HIGH); // 3rd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(37, LOW);   // LED turns off
    delay(500);
    digitalWrite(38, HIGH); // 1st Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(38, LOW);   // LED turns off
    delay(500);
    digitalWrite(39, HIGH); // 2nd Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(39, LOW);   // LED turns off
    delay(500);
    //check to see if a false start has occurred.
    if ((digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
      digitalWrite (40, HIGH); // Green LED turns on and starts race. Remains on for 3 seconds.
      //Timer needs to start.
      delay(2000);
      digitalWrite (40, LOW);
    }
    else
    {
      //A false start.
      digitalWrite(41, HIGH); // Blue LED turns on for 1/2 second
      delay(3000);
      digitalWrite(41, LOW);
    }
  }
}

Save the value from millis() when the cars start. When they finish save the time from millis(). Subtract the start time from the finish time and you have the elapsed time in milliseconds.

Are there any tutorials that can assist me with how to code this?

In your code set an unsigned long variable, let's call it startTime equal to millis() when the cars start.

When car a breaks the finish beam save the value of millis() to an unsigned long variable, let's call it finishTimeA
When car b breaks the finish beam save the value of millis() to an unsigned long variable, let's call it finishTimeB

As a starting point to displaying the elapsed time write a function that displays finishTimeA - startTime and finishTimeB - startTime to the serial monitor and call it when either car breaks the finish beam.

Is this how the first part is coded?

unsigned long startTime == millis();

Not sure about this.
unsigned long finishTimeA = 0;
unsigned long finishTimeB = 0;

I intend to display the results on a 7 segment display.

unsigned long startTime == millis();Should be

unsigned long startTime = millis();

Be careful about the scope of the variables that you create otherwise they may not be available where you need them. The quick and dirty way round this is to declare them as global variables so that you can access them throughout the program.

I intend to display the results on a 7 segment display.

Yes, I know. The suggestion to initially use the Serial monitor was a "get you started" step. It will also serve as a debugging aid when expanding the program. You will need to format the output as I expect that the number of elapsed milliseconds is not what you really want. You can try this and see the results on the Serial monitor before moving on to use the 7 segment display.

You will find plenty of examples of using a 7 segment display on line but be sure that any example that you choose uses the same type of display (common anode or common cathode) as the connections to the Arduino and the programming will differ. Do you have a 7 segment display yet ?

When testing the display I suggest that you do it using a separate program and write a function to display the data. When you know that it works you can copy the function to your main program and call it to display your time or times.

Thx yep I picked up the == mistake after I posted. I have the 7 segment displays already. They are the 1.2" with a backpack (Adafruit 1.2 4-Digit 7-Segment Display w/I2C Backpack - Red : ID 1270 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits). So I have attached the new code with the three new variables. When the program checks the state of the two start sensors and they are LOW the current time needs to be sent to the startTime variable. When the cars finish their times are updated. I have also created a variable called elapsedTimeA and elapsedTimeB to keep the time of the cars actual times. The issue for me is, how to put a value into these variables and the syntax. Is this how it has to go ? elapsedTimeA = (startTime - finishTimeA);
Have I coded this correctly?

unsigned long startTime = millis();
unsigned long finishTimeA = 0;
unsigned long finishTimeB = 0;
unsigned long elapsedTimeA=0;
unsigned long elapsedTimeB=0;
int sensorPins[] = {29, 30, 31, 32, 33};
int sPinCount = 5;
int ledPins[] = {34, 35, 36, 37, 38, 39, 40, 41};
int lPinCount = 8;

void setup() {
  Serial.begin(9600);
 

  for (int thisPin = 0; thisPin < sPinCount; thisPin++) {
    pinMode(sensorPins[thisPin], INPUT_PULLUP);
  }

  for (int thisPin = 0; thisPin < lPinCount; thisPin++) {
    pinMode(ledPins[thisPin], OUTPUT);
  }

}

void loop() {
  //Checks (break beam sensors) to see if a car has raced and stops the timers.
  if (digitalRead(32) == LOW) {
    finishTimeA = millis;
  }
  if (digitalRead(33) == LOW) {
    finishTimeB = millis;
  }
  //Check if both cars have finished. If they have, the times are to be displayed for 5 seconds then the timer needs to display who was first and second.
  //if ((digitalRead(32) == LOW)&&(digitalRead(33) == LOW)){}

  //When start button is pushed Checks to see if cars are in starting positions. If yes start the light sequence.
  if ((digitalRead (29) == LOW) && ( digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
    // Reset timer A and timer B to 0
    //musicPlayer.playFullFile ("sye00001.mp3");
    digitalWrite(34, HIGH);  // White Led on for 2.5 seconds
    delay(2500);
    digitalWrite(34, LOW);   // White LED turns off
    delay(500);
    digitalWrite(35, HIGH); // 1st Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(35, LOW);   // LED turns off
    delay(500);
    digitalWrite(36, HIGH); // 2nd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(36, LOW);   // LED turns off
    delay(500);
    digitalWrite(37, HIGH); // 3rd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(37, LOW);   // LED turns off
    delay(500);
    digitalWrite(38, HIGH); // 1st Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(38, LOW);   // LED turns off
    delay(500);
    digitalWrite(39, HIGH); // 2nd Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(39, LOW);   // LED turns off
    delay(500);
    //check to see if a false start has occurred.
    if ((digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
      digitalWrite (40, HIGH); 
      startTime = millis;// Green LED turns on and starts race. Remains on for 3 seconds.
      //Timer A and Timer B need to start.
      delay(2000);
      digitalWrite (40, LOW);
    }
    else
    {
      //A false start.
      digitalWrite(41, HIGH); // Blue LED turns on for 1/2 second
      delay(3000);
      digitalWrite(41, LOW);
    }
  }
}


[code]
elapsedTimeA = (startTime - finishTimeA);

That's right.

   finishTimeA = millis;

That's wrong, as are all of your uses of millis. They should be millis()

Thank you.

Yes you are right. Young children would not be able to read milli seconds so I need a way to make it into minutes, seconds, tenths of seconds, hundredths of seconds????

I need a way to make it into minutes, seconds, tenths of seconds, hundredths of seconds????

A clue or two.

void setup()
{
  Serial.begin(115200);
  unsigned long elapsedTime = 1234;
  int milliSeconds = elapsedTime % 1000;
  int seconds = elapsedTime / 1000;
  Serial.print(seconds);
  Serial.println(" second(s)");
  Serial.print(milliSeconds);
  Serial.println(" millisecond(s)");
}

void loop()
{
}

I appreciate the clue or two. :slight_smile: Have not attempted to put it in the code until I get everything working as it should.
The following is working.

  1. When the green light goes on, the millis is updated correctly in the startTime variable.
  2. When the end race break beam sensor is activated millis is updated into the finishTime variable.
    Not sure.
    When I serial print the elapsedTimeA variable it starts off with a 0. When I break the beam on the sensor I get a number so I assuming it is the elapsed time.
    What is not working is where I compare the two cars elapsed times to see who came 1st and 2nd. If I Serial.println(placeB); The value starts off with 0. No matter what order I break the sensors I still get a reading of 1. Have I coded the arguments correctly or is it the logic?
    code/
    //Checks if both cars have finished. If they have, the elapsed times are compared and which car came first and second is calculated.
 if ((digitalRead(32) == LOW) && (digitalRead(33) == LOW)) //pins for the break beam sensors
 {
   if ((elapsedTimeA < elapsedTimeB)) {
   placeA = 1;
   placeB = 2;

 }
 if ((elapsedTimeA > elapsedTimeB)) {
   placeA = 2;
   placeB = 1;
 }
 if ((elapsedTimeA == elapsedTimeB)) {
   placeA = 1;
   placeB = 1;
 }
 }

In the code snippet that you posted you are not calculating the elapsed times so they will still be at their previous value.

Also, the bulk of the code snippet will only be executed whilst both sensors are LOW. Is that going to happen in practice ? It seems to me that you would be better off noting the time when the beams become broken. To see how to do this look at the StateChangeDetection example in the IDE.

Here is the code with the calculations. Hope this is how I should do it. Also my way of thinking was that the scores and times would not be shown until both cars had finished the race, that is both sensors would be low. In the game, children are moving the cars by holding a handle with a magnet attached under a board. The cars are on top and have to negotiate a twisting and turning track routed in the board. Each car has its own identical lane. So they have to guide the car with a focus on muscle control. I will have a look at what you suggested re: noting the time the break beam was broken. Also I have said elapsedTimeA = (startTime - finishTimeA); should this be elapsedTimeA = (finishTimeA - startTime); ?

void loop() {
  Serial.println(placeB);
  
  //Checks (break beam sensors) to see if a car has finished the race and records time.
  if (digitalRead(32) == LOW) {
    finishTimeA = millis();
    elapsedTimeA = (startTime - finishTimeA);
    
  }
  if (digitalRead(33) == LOW) {
    finishTimeB = millis();
    elapsedTimeB = (startTime - finishTimeB);
    
  }
  //Checks if both cars have finished. If they have, the elapsed times are compared and which car came  first and second is calculated.
  if ((digitalRead(32) == LOW) && (digitalRead(33) == LOW)) 
  {
    if ((elapsedTimeA < elapsedTimeB)) {
    placeA = 1;
    placeB = 2;

  }
  if ((elapsedTimeA > elapsedTimeB)) {
    placeA = 2;
    placeB = 1;
  }
  if ((elapsedTimeA == elapsedTimeB)) {
    placeA = 1;
    placeB = 1;
  }
  }

I will have a look at what you suggested re: noting the time the break beam was broken.

If you don't do this then if a car that has finished is moved out of the beam then the test for both cars having finished will not work.

should this be elapsedTimeA = (finishTimeA - startTime); ?

Yes it should. By definition the finish time will always be larger than the start time.

I will look at the rest of the code in more detail later.

I appreciate the support. I have attached the full code. The children would not move the car off the finish line until the score/place was given. However I think a problem might be with this. Every time the code is compiled with the cars at the finish line the finishTimeA and finishTimeB woud be continuously updated? if (digitalRead(32) == LOW) {
finishTimeA = millis();
elapsedTimeA = (finishTimeA - startTime);
So I am thinking that when a car crosses the finish line its elapsed time needs to be stored and can not be changed until the reset button is pressed?

unsigned long startTime = millis();
unsigned long finishTimeA  = 0;
unsigned long finishTimeB = 0;
unsigned long elapsedTimeA = 0;
unsigned long elapsedTimeB = 0;
int placeA = 0;
int placeB = 0;
int sensorPins[] = {29, 30, 31, 32, 33};
int sPinCount = 5;
int ledPins[] = {34, 35, 36, 37, 38, 39, 40, 41};
int lPinCount = 8;

void setup() {
  // {
  // Serial.begin(115200);
  // unsigned long elapsedTime = 1234;
  //int milliSeconds = elapsedTime % 1000;
  //int seconds = elapsedTime / 1000;
  //Serial.print(seconds);
  //Serial.println(" second(s)");
  // Serial.print(milliSeconds);
  // Serial.println(" millisecond(s)");
  //}
  Serial.begin(9600);


  for (int thisPin = 0; thisPin < sPinCount; thisPin++) {
    pinMode(sensorPins[thisPin], INPUT_PULLUP);
  }

  for (int thisPin = 0; thisPin < lPinCount; thisPin++) {
    pinMode(ledPins[thisPin], OUTPUT);
  }

}

void loop() {
  Serial.println(elapsedTimeA);
  


  //When start button is pushed Checks to see if cars are in starting positions. If yes start the light sequence.
  if ((digitalRead (29) == LOW) && ( digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
    //musicPlayer.playFullFile ("sye00001.mp3");
    placeA = 0;
    placeB = 0;
    digitalWrite(34, HIGH);  // White Led on for 2.5 seconds
    delay(2500);
    digitalWrite(34, LOW);   // White LED turns off
    delay(500);
    digitalWrite(35, HIGH); // 1st Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(35, LOW);   // LED turns off
    delay(500);
    digitalWrite(36, HIGH); // 2nd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(36, LOW);   // LED turns off
    delay(500);
    digitalWrite(37, HIGH); // 3rd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(37, LOW);   // LED turns off
    delay(500);
    digitalWrite(38, HIGH); // 1st Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(38, LOW);   // LED turns off
    delay(500);
    digitalWrite(39, HIGH); // 2nd Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(39, LOW);   // LED turns off
    delay(500);
    //check to see if a false start has occurred.
    if ((digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
      digitalWrite (40, HIGH);
      startTime = millis();// Green LED turns on and starts race. Remains on for 3 seconds.
      //starting time is recorded
      delay(2000);
      digitalWrite (40, LOW);
    }
    else
    {
      //A false start.
      digitalWrite(41, HIGH); // Blue LED turns on for 3 seconds
      delay(3000);
      digitalWrite(41, LOW);
    }
  }
    //Checks (break beam sensors) to see if a car has finished the race and records time.
  if (digitalRead(32) == LOW) {
    finishTimeA = millis();
    elapsedTimeA = (finishTimeA - startTime);
    
  }
  if (digitalRead(33) == LOW) {
    finishTimeB = millis();
    elapsedTimeB = (finishTimeB - startTime);
    
  }
  //Checks if both cars have finished. If they have, the elapsed times are compared and which car came  first and second is calculated.
  if ((digitalRead(32) == LOW) && (digitalRead(33) == LOW)) 
  {
    if ((elapsedTimeA < elapsedTimeB)) {
    placeA = 1;
    placeB = 2;

  }
  if ((elapsedTimeA > elapsedTimeB)) {
    placeA = 2;
    placeB = 1;
  }
  if ((elapsedTimeA == elapsedTimeB)) {
    placeA = 1;
    placeB = 1;
  }
  }
}

:slight_smile: I had a go. I changed this
if (digitalRead(32) == LOW) {
finishTimeA = millis();
elapsedTimeA = (finishTimeA - startTime);
to this
if ((digitalRead(32) == LOW) && (finishTimeA == 0)) {
finishTimeA = millis();
elapsedTimeA = (finishTimeA - startTime);
So now I am getting either a 1 or a 2 depending on the order I block the finishing break beam sensors. I will keep testing to see if it is working for sure.
Now I will look at getting the time readings into seconds.
If I place and activate the code you sent me do I have to delete the
Serial.begin(9600); as in your code you have
Serial.begin(115200);
Here is the new code for your critique and perusal.

unsigned long startTime = millis();
unsigned long finishTimeA  = 0;
unsigned long finishTimeB = 0;
unsigned long elapsedTimeA = 0;
unsigned long elapsedTimeB = 0;
int placeA = 0;
int placeB = 0;
int sensorPins[] = {29, 30, 31, 32, 33};
int sPinCount = 5;
int ledPins[] = {34, 35, 36, 37, 38, 39, 40, 41};
int lPinCount = 8;

void setup() {
  // {
  // Serial.begin(115200);
  // unsigned long elapsedTime = 1234;
  //int milliSeconds = elapsedTime % 1000;
  //int seconds = elapsedTime / 1000;
  //Serial.print(seconds);
  //Serial.println(" second(s)");
  // Serial.print(milliSeconds);
  // Serial.println(" millisecond(s)");
  //}
  Serial.begin(9600);


  for (int thisPin = 0; thisPin < sPinCount; thisPin++) {
    pinMode(sensorPins[thisPin], INPUT_PULLUP);
  }

  for (int thisPin = 0; thisPin < lPinCount; thisPin++) {
    pinMode(ledPins[thisPin], OUTPUT);
  }

}

void loop() {
  Serial.println(placeA);



  //When start button is pushed Checks to see if cars are in starting positions. If yes start the light sequence.
  if ((digitalRead (29) == LOW) && ( digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
    //musicPlayer.playFullFile ("sye00001.mp3");
    placeA = 0;
    placeB = 0;
    finishTimeA  = 0;
    finishTimeB = 0;
    elapsedTimeA = 0;
    elapsedTimeB = 0;
    digitalWrite(34, HIGH);  // White Led on for 2.5 seconds
    delay(2500);
    digitalWrite(34, LOW);   // White LED turns off
    delay(500);
    digitalWrite(35, HIGH); // 1st Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(35, LOW);   // LED turns off
    delay(500);
    digitalWrite(36, HIGH); // 2nd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(36, LOW);   // LED turns off
    delay(500);
    digitalWrite(37, HIGH); // 3rd Red LED turns on for 1/2 second
    delay(500);
    digitalWrite(37, LOW);   // LED turns off
    delay(500);
    digitalWrite(38, HIGH); // 1st Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(38, LOW);   // LED turns off
    delay(500);
    digitalWrite(39, HIGH); // 2nd Yellow LED turns on for 1/2 second
    delay(500);
    digitalWrite(39, LOW);   // LED turns off
    delay(500);
    //check to see if a false start has occurred.
    if ((digitalRead (30) == LOW) && (digitalRead (31) == LOW)) {
      digitalWrite (40, HIGH);
      startTime = millis();// Green LED turns on and starts race. Remains on for 3 seconds.
      //starting time is recorded
      delay(2000);
      digitalWrite (40, LOW);
    }
    else
    {
      //A false start.
      digitalWrite(41, HIGH); // Blue LED turns on for 3 seconds
      delay(3000);
      digitalWrite(41, LOW);
    }
  }
  //Checks (break beam sensors) to see if a car has finished the race and records time.
  if ((digitalRead(32) == LOW) && (finishTimeA == 0)) {
    finishTimeA = millis();
    elapsedTimeA = (finishTimeA - startTime);

  }
  if ((digitalRead(33) == LOW) && (finishTimeB == 0)) {
    finishTimeB = millis();
    elapsedTimeB = (finishTimeB - startTime);

  }
  //Checks if both cars have finished. If they have, the elapsed times are compared and which car came  first and second is calculated.
  if ((digitalRead(32) == LOW) && (digitalRead(33) == LOW))
  {
    if ((elapsedTimeA < elapsedTimeB)) {
      placeA = 1;
      placeB = 2;

    }
    if ((elapsedTimeA > elapsedTimeB)) {
      placeA = 2;
      placeB = 1;
    }
    if ((elapsedTimeA == elapsedTimeB)) {
      placeA = 1;
      placeB = 1;
    }
  }
}

So I am thinking that when a car crosses the finish line its elapsed time needs to be stored and can not be changed until the reset button is pressed?

That is one good reason to use state change detection.

if ( (currentState != previousState) && (carIsAtFinish) )

You know that the car is at the finish and that it just arrived.

My first suggestion regarding your code would be to hive off the LED sequence code into a function and call it when required. This will not affect the functioning of the program but if you put the function at the end of the code it will be easier to read. At the present the code is overburdened by the multiple lines of digitalWrite() and delay(). Incidentally, there is almost certainly a better way to program the LED sequence.

I am hesitant to suggest making big changes, but it would probably be a good idea to completely restructure your program as a state machine. At any time the program is in one of several states, each of which you give a number (or name, but let's leave that for now). Using switch/case based on the current state the program executes only the code for the current state.

The states might be (but feel to free amend the list) :
0 waiting for start
1 flashing LEDs
2 test for false start and act if detected
3 race running, test for both cars finishing
4 display result
5 wait for restart

When the exit condition(s) for a state are satisfied, change the state number to the destination state and set any entry values such as current time etc. Next time through loop() the program will execute the code for the new state. Note that the program does not need to go through the states in any particular order. For instance, after detecting a false start (state 2 above) the state would be changed to 0 to await a restart.

I appreciate the time, effort and assistance you have put into thinking about the program. The term 'state machine' is totally new to my experience, though what you have said makes complete sense to me and would indeed be a better way to write the program. I know the Led blinking program is very clunky however if I was using an index approach
int ledPins[] = {2,3,4,5,6,7,8,9}; for(index = 0; index <= 7; index++)
{
pinMode(ledPins[index],OUTPUT);
for(index = 0; index <= 7; index++)
{
digitalWrite(ledPins[index], HIGH); // turn LED on
delay(delayTime); // pause to slow down
digitalWrite(ledPins[index], LOW); // turn LED off
}

I could not think of a way to check for false starts once the led sequence started. Like an interrupt to keep checking the states of the start sensors.
I would like to begin the journey of writing the new program however I would need a great deal of assistance.

I could not think of a way to check for false starts once the led sequence started.

So don't use a for loop. The loop() function does what it says and you can use that to your advantage

Some pseudo code

declare variables - use globals for simplicity
ledNum = 0  //index to ledPins array
save millis() value as startTime
give blinkInterval a value for the required delay (NOT delay())
set boolean showLeds to true

start of loop()
  if showLeds is true
    set currentTime to millis()
    if currentTime - startTime >= blinkInterval
      change the state of the LEDs
      increment ledNum
      copy currentTime to startTime
    end if
    
    if ledNum limit has been reached
      start race
    end if
    check false start and take appropriate action
  end if
end of loop()

You could also do this in a while loop and exit the loop when a false start is detected or the LED sequence is complete. If you put that in a function you could call it when required but be aware that until the while loop is exited the program will be able to do nothing else, which may be OK. You can see, I hope, how that use of the loop() function in this way would lend itself to being one state of a state machine. Depending what caused the state to change, end of sequence or false start, could take the program to the next appropriate state.

As to using a state machine, it seems that you can see the advantages but you will, of course, need to restructure the program, although much of the code already exists in your current program. Start by listing each possible state and giving them a unique number.

If you do decide to go down this route I will help as much as possible and there is plenty of other help available in this forum.

Thx. A good red and a few late nights ahead I think. Lucky I am on school holidays :slight_smile: The states you indicate in a previous post hit the nail on the head.

0 waiting for start
1 flashing LEDs
2 test for false start and act if detected
3 race running, test for both cars finishing
4 display elapsed time then finish position
5 wait for restart.

So step one is to declare all the global variables?