Order of Code Execution

Hello,
I am trying to make a reaction time tester and have it be two players for a class project, but when button 2 is released before button 1, it displays that player 1 won with the difference in time being around 3 milliseconds. I think this is because it runs the first while statement before it goes to the second, but how would I fix it?

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int LEDR = 6; // Red Led pin 6
int LEDB = 7; // Blue Led pin 7
int LEDGr = 8; // Green Led pin 8
int Button1=10;
int Button2=9;
int COLOR;
int PSE; // variable pause 
int TME; // Time
int RTME1=0; // Reaction Time
int RTME2=0;

void setup()
{
lcd.begin(16, 2);
pinMode(LEDR, OUTPUT);
pinMode(LEDB, OUTPUT);
pinMode(LEDGr, OUTPUT);
pinMode(Button1, INPUT);
pinMode(Button2, INPUT);
digitalWrite(LEDR, HIGH); // All lights are switched "on".
digitalWrite(LEDB, HIGH);
digitalWrite(LEDGr, HIGH);
}

void loop()
{
lcd.clear(); // Clear screen.
lcd.print("Hold Button to");
lcd.setCursor(0,1); // move to second line.
lcd.print("start.");
while (digitalRead(Button1)==LOW && digitalRead(Button2)==LOW) // The test does not start until the button is pushed (and held down).
{tone(13,1200,30);
delay(1400);
noTone(13);
}
RTME1=0;
RTME2=0;

lcd.clear();
digitalWrite(LEDR, LOW); // switch off the "start"light.
digitalWrite(LEDB, LOW);
digitalWrite(LEDGr, LOW);
randomSeed(analogRead(0)); //Random noise from pin 0
COLOR = random(1,4); // Generate a random color.
PSE=random(500,1200); // Select a random pause between the lights (to increase the surprise effect).


while (COLOR!=1 && digitalRead(Button1)==HIGH && digitalRead(Button2)==HIGH)// This loop is repeated while color is Green or Blue AND button is held down.
{
digitalWrite(LEDGr, LOW);
digitalWrite(LEDB, LOW);
delay(PSE);
randomSeed(analogRead(0));
PSE=random(750,1200); // Select a random pause between the lights (to increase the surprise effect).

if (COLOR == 2)
{digitalWrite(LEDGr, HIGH);}
if (COLOR == 3)
{digitalWrite(LEDB, HIGH);}
delay(PSE);
randomSeed(analogRead(0));
COLOR = random(1,4);  // Select a random color.
}


if (COLOR == 1 && digitalRead(Button1)==HIGH && digitalRead(Button2)==HIGH)// This loop is executed if the color is red.
{
digitalWrite(LEDGr, LOW);
digitalWrite(LEDB, LOW);
delay(PSE);
TME=millis(); // Time since this program has started (so Blue or Green loop included).
digitalWrite(LEDR, HIGH);

while (digitalRead(Button1)==HIGH)// This loop runs until you have released the button, hence the reaction time.
{delay(1);}
lcd.display();
RTME1=millis()-TME; // Time since Led is Red, hence reaction time.
lcd.print("Doc:");
lcd.print(RTME1);

while (digitalRead(Button2)==HIGH)
{delay(1);}
lcd.display();
RTME2=millis()-TME; // Time since Led is Red, hence reaction time.
lcd.setCursor(0,1);
lcd.print("McQueen:");
lcd.print(RTME2);

}

if (RTME1<RTME2)
{
  delay(3000);
  lcd.clear();
  lcd.print("Winner: Doc");
  lcd.setCursor(0,1);
  lcd.print ("Time:");
  lcd.print (RTME1);
}

if (RTME2<RTME1)
{
  delay(3000);
  lcd.clear();
  lcd.print("Winner: McQueen");
  lcd.setCursor(0,1);
  lcd.print("Time:");
  lcd.print(RTME2);
}

if (COLOR != 1) // This step is executed if the color is NOT red but the Push button was released (wrong action). 
{
lcd.print("Released too");
lcd.setCursor(0,1); // move to second line.
lcd.print("soon !!!");
tone(13,3000,1500);
delay(500);
noTone(13);
}


while (digitalRead(Button1)==LOW && digitalRead(Button2)==LOW) // The test does not re-start until the button is pushed once.
{delay(10);}

digitalWrite(LEDR, HIGH); // Resets all lights to begin again.
digitalWrite(LEDB, HIGH);
digitalWrite(LEDGr, HIGH);
lcd.clear();
lcd.print("Hold Button to");
lcd.setCursor(0,1);
lcd.print("start.");
int Time=0;
delay(1000);
}

:disappointed:

Please let that garbage disappear.

Oh. Wow. You did that twice.

How are the buttons wired?

To implement a reasonably random seed, tell the user to push and release the button, while the code rapidly increments a variable. Reaction times vary enough that this works well.

1 Like

You can't wait for button1 to be pressed and then start waiting for button2 to be pressed. You have to check for both of them and then determine which was pressed first only after they both have been pressed. Something like this

    bool done = false;
    // This loop runs until you have released the button, hence the reaction time.
    while ( !done ) {
      if ( digitalRead(Button1) == LOW) {
        // button pressed, record reaction time if not done already
        // if RTM1 is zero, we need to record it for the first time
        if ( RTME1 != 0 ) {
          RTME1 = millis() - TME; // Time since Led is Red, hence reaction time.
          lcd.display();
          lcd.print("Doc:");
          lcd.print(RTME1);
        }
      }

      if (digitalRead(Button2) == LOW) {
        if ( RTME2 != 0 ) {
          RTME2 = millis() - TME; // Time since Led is Red, hence reaction time.
          lcd.display();
          lcd.setCursor(0, 1);
          lcd.print("McQueen:");
          lcd.print(RTME2);
        }
      }

      // check to see if we are done - both reaction times are not zero
      if ( RTME1 && RTME2 ) {
        done = true;
      }
    }
    delay(3000);
    lcd.clear();
    
    if (RTME1 < RTME2) {
      lcd.print("Winner: Doc");
      lcd.setCursor(0, 1);
      lcd.print ("Time:");
      lcd.print (RTME1);
    }

    else if (RTME2 < RTME1) {
      lcd.print("Winner: McQueen");
      lcd.setCursor(0, 1);
      lcd.print("Time:");
      lcd.print(RTME2);
    }
    else {
      lcd.print("It is a tie");
      lcd.setCursor(0, 1);
      lcd.print("Time:");
      lcd.print(RTME2);
    }
2 Likes

Two near identical topics:

Both closed pending an explanation from the OPs.