Timer Within Loop

Hello, I’m currently working on a game that measures reaction time after either a buzzer or LED light turns on through pressing buttons. While the code itself works I wish to add some stuff but have had trouble doing so.

Current code:

#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 7, 6, 5, 4); // SETUPS
int ledPin1 = 13;
int ledPin2 = 12;
int BUTTON1 = 3; // LEFT BUTTON
int BUTTON2 = 10; // RIGHT BUTTON
int BUTTON3 = 11; // MIDDLE BUTTON
int BUZZER = 2;
int long ranDelay = 0;
int sensorValue = 0;
float realTime;
void setup()
{
 Serial.begin(9600);      // MORE SETUPS
 pinMode(ledPin1, OUTPUT);
 pinMode(BUTTON1, INPUT);
 lcd.begin(32, 2);
 lcd.clear();
}
void loop(){
 Serial.println("");                                                      //STARTING THE GAME WITH BUTTON1
 Serial.println("");
 Serial.println("");
 Serial.println("Push left button to start the reaction minigame!");
 lcd.setCursor(0, 0);
 lcd.print("Push left button");
 lcd.setCursor(0, 1);
 lcd.print("to start playing!");

 while (digitalRead(BUTTON1)== 0){        // EVERYTHING AFTER ONLY RUNS AFTER BUTTON1 (LEFT BUTTON) IS PRESSED
 }
 Serial.println("");
 Serial.println("");
 Serial.println("");
 Serial.println("Get Ready..!");
 lcd.clear();
 lcd.print("Get Ready..!");
 lcd.setCursor(0, 1);
 delay(1000);
 Serial.println("Get Set..!");
 lcd.clear();
 lcd.print("Get Set..!");
 delay(1000);


int randompick = random(0, 1000);
if(randompick <= 500){               //LED WILL ACTIVATE IF RANDOM PICK IS BELOW 500

 ranDelay = random(1700, 2000);
 delay(ranDelay);
 Serial.println("React!");
 lcd.clear();
 lcd.print("React!");

 realTime = millis();
 digitalWrite(ledPin1, HIGH);

 while (digitalRead(BUTTON1)== 0) {     // WILL ONLY REACT IF BUTTON1 IS PRESSED, NOT 2

 }
 digitalWrite(ledPin1, LOW);
 Serial.println("Your time was");
 realTime = millis()-realTime;
 Serial.print(realTime/1000,2);     // REACTION CALCULATIONS
 Serial.println(" seconds!");
 lcd.clear();
 lcd.print("Your time was");
 lcd.setCursor(0, 1);
 lcd.print(realTime/1000,2);
 lcd.print(" seconds!");
// delay(4000);

while (digitalRead(BUTTON3) == 0){ // PRESS TO RESTART PROGRAM
}
}


else if(randompick > 500){            //BUZZER WILL ACTIVATE IF RANDOM PICK IS 1 
ranDelay = random(1700, 200);
 delay(ranDelay);
 Serial.println("React!");
 lcd.clear();
 lcd.print("React!");

 realTime = millis();
 tone(BUZZER, 300, 250);

while (digitalRead(BUTTON2)== 0) {  // WILL ONLY REACT IF BUTTON2 IS PRESSED, NOT B1

 }
 digitalWrite(ledPin1, LOW);
 Serial.println("Your time was");
 realTime = millis()-realTime;
 Serial.print(realTime/1000,2); // REACTION CALCULATIONS
 Serial.println(" seconds!");
 lcd.clear();
 lcd.print("Your time was");
 lcd.setCursor(0, 1);
 lcd.print(realTime/1000,2);
 lcd.print(" seconds!");
// delay(4000); 

while (digitalRead(BUTTON3) == 0){ // PRESS TO RESTART PROGRAM
}
}

}

If possible I wish to add the following in order to display the time that has passed after either the LED/Buzzer turn on with:

lcd.setCursor(0, 1);
lcd.print(millis()); //Adding this as is would print a static number which is my current issue

// At both: digitalWrite(ledPin1, HIGH); and  tone(BUZZER, 300, 250);

I would also like guidance on how to code a way for an incorrect button push to end the program and a time limit for the program as well.

Any formatting/inefficient code fixes would also be helpful. :slight_smile:

andyoz:
I would also like guidance on how to code a way for an incorrect button push to end the program and a time limit for the program as well.

Any formatting/inefficient code fixes would also be helpful. :slight_smile:

consider the following

  • getButton() returns whichever button was pressed allowing for wrong button
  • go() performs the test for whichever led/button is specified, avoiding redundant code
  • simulated LCD functions because my hardware doesn’t have an LCD, tone() dropped as well (no HW)
  • use of sub-functions and added whitespace makes the code easier to read
  • while there’s more lines of source, binary is smaller, 4896 vs 6112 bytes
#if 0
# include <LiquidCrystal.h>
#else
struct LiquidCrystal {
    LiquidCrystal (int a, int b, int c, int d, int e, int f)  {};
    void begin (int x, int y)  {};
    void clear (void)  {};
    void print (const char *s)  {};
    void print (float x, int dec)  {};
    void setCursor (int x, int y)  {};
};
#endif

LiquidCrystal lcd (9, 8, 7, 6, 5, 4); // SETUPS

enum { On = LOW, Off = HIGH };

int ledPin1 = 13;
int ledPin2 = 12;

#if 0
int BUTTON1 = 3; // LEFT BUTTON
int BUTTON2 = 10; // RIGHT BUTTON
int BUTTON3 = 11; // MIDDLE BUTTON
#else
# define  BUTTON1   A1  // LEFT BUTTON
# define  BUTTON2   A2  // RIGHT BUTTON
# define  BUTTON3   A3  // MIDDLE BUTTON
#endif

byte buttons [] = { BUTTON1, BUTTON2, BUTTON3 };

int BUZZER = 2;
int long ranDelay = 0;
int sensorValue = 0;
float realTime;

char s [80];

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);      // MORE SETUPS

    digitalWrite (ledPin1, Off);
    digitalWrite (ledPin2, Off);

    pinMode (ledPin1, OUTPUT);
    pinMode (ledPin2, OUTPUT);

    pinMode (BUTTON1, INPUT_PULLUP);
    pinMode (BUTTON2, INPUT_PULLUP);
    pinMode (BUTTON3, INPUT_PULLUP);

    lcd.begin (32, 2);
    lcd.clear ();
}

// -----------------------------------------------------------------------------
void
disp (
    const char* s0,
    const char* s1 )
{
    sprintf (s, "%s %s", s0, s1);
    Serial.println (s);

    lcd.setCursor (0, 0);
    lcd.print     (s0);
    lcd.setCursor (0, 1);
    lcd.print     (s1);
}

// -----------------------------------------------------------------------------
int
getButton (void)
{
    while (true)
        for (byte i = 0; i < sizeof(buttons); i++)  {
            if (On == digitalRead (buttons [i]))
                return buttons [i];
        }
}

// -----------------------------------------------------------------------------
void
go (
    int led,
    int button )
{
    sprintf (s, "%s: led %d, button %d", __func__, led, button);
    Serial.println (s);

    ranDelay = random (1700, 2000);
    delay (ranDelay);

    disp ("React!", NULL);
    unsigned long msec = millis ();
    digitalWrite (led, On);

    int but = getButton ();

    msec = millis () - msec;
    digitalWrite (led, Off);

    if (but == button)  {        
        char s [20];
        sprintf (s, "%6ld msec", msec);
        disp("Your time was", s);
    }
    else
        disp("wrong button", NULL);

    disp ("Push right button", "to restart game");
    while (digitalRead (BUTTON3) == Off)
        ;
}

// -----------------------------------------------------------------------------
void loop (){
    disp ("Push left button", "to start playing!");

    // EVERYTHING AFTER ONLY RUNS AFTER BUTTON1 (LEFT BUTTON) IS PRESSED
    while (digitalRead (BUTTON1)== Off)
        ;

    disp ("Get Ready..!", NULL);
    delay (1000);

    disp ("Get Set..!", NULL);
    delay (1000);

    //LED WILL ACTIVATE IF RANDOM PICK IS BELOW 500
    int randompick = random (0, 1000);

    if (randompick <= 500)
        go (ledPin1, BUTTON1);
    else
        go (ledPin2, BUTTON2);
}