While loop not working?

Hey, i am trying to make a device that you activate by pressing a button, then it creates a random delay, and you have to wait for this random amount of time, and when it has passed, either a led or a buzzer will go off (also randomly chosen), then you have to click again, and then it will tell you your reaction time based on two millis() timers. But i seem to have a problem on the very very last step, everything is working, but when the led or buzzer goes off, it just jumps straight past my while loop, doesent wait for a button click, it just jumps back to the beginning.
So i am either trying to make it so that it will get stuck in my while loop, or so that it will wait for a button press, before telling me my reaction time and going back to the beginning.
Any advice please??

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int buzzerPin = 6;
const int buttonPin = 7;
const int ledPin = 8;
unsigned long int counter = 0;
unsigned long int reaction = 0;
int randomDelay = 0;
int randomVal1 = 0;
unsigned long int realReaction = 0;
int buttonState = 0;
int looper = 0;

void setup() {
randomSeed(analogRead(0));
lcd.begin(16, 2);
pinMode(6, OUTPUT);
pinMode(7, INPUT);
pinMode(8, OUTPUT);
}



void loop() {
introduction();
buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) {
    randomVal1 = random(0, 100);
    randomDelay = random(3000, 10000);
    lcd.setCursor(0, 0);
    lcd.print("Tap when you    ");
    lcd.setCursor(0, 1);
    lcd.print("notice sound/led");
    delay(randomDelay);
    reaction = millis();
    buzzerOrLed();
    buttonState = digitalRead(buttonPin);
    while (looper == 0) {
      lcd.setCursor(0, 0);
      lcd.print("Tap when you    ");
      lcd.setCursor(0, 1);
      lcd.print("notice sound/led");
      buttonState = digitalRead(buttonPin);
        if (buttonState == HIGH) {
          looper++;
          counter = millis();
          realReaction = (reaction - counter);
          lcd.setCursor(0, 0);
          lcd.print("                ");
          lcd.setCursor(0, 0);
          lcd.print(realReaction);
          lcd.setCursor(0, 1);
          lcd.print("                ");
        }
     }
  }
}

void introduction() {
  lcd.setCursor(0, 0);
  lcd.print("Press the button");
  lcd.setCursor(0, 1);
  lcd.print("to start test   ");
}

void buzzerOrLed() {
  if (randomVal1 > 53) {
  digitalWrite(ledPin, HIGH);
  delay(200);
  digitalWrite(ledPin, LOW);
  } else {
  tone(buzzerPin, 800);
  delay(200);
  noTone(buzzerPin);
  }
}

Three things:

  • Do not look at the level of a switch, look at when a switch changes state.

  • Avoid using while( ) loops as if they were a plague.

  • Only use delay( ) for very very short intervals, or not at all.

1 Like

Ive sat at this for a very long time now, tried switching from ifs to for to while loops, but nothing changes it, it just feels like it ignores it and just jumps over it

as I see it, the first time the program enters to the loop, and then it starts to jump over it, because the loop condition is not met

BTW, how is your switch wired ?

its connected from 5v to ground through a resistor, with a wire going from the same rail as the resistor from the switch to pin 7 on the arduino

Why do you think the program should wait for button click? I don't see anything like in your program... Could you point the line in the code where the program stops before button press?

Yes,
if (buttonState == HIGH) {
randomVal1 = random(0, 100);
randomDelay = random(3000, 10000);
lcd.setCursor(0, 0);
lcd.print("Tap when you ");
lcd.setCursor(0, 1);
lcd.print("notice sound/led");
delay(randomDelay);
reaction = millis();
buzzerOrLed();
buttonState = digitalRead(buttonPin);
while (looper == 0) {
lcd.setCursor(0, 0);
lcd.print("Tap when you ");
lcd.setCursor(0, 1);
lcd.print("notice sound/led");
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
looper++;
counter = millis();
realReaction = (reaction - counter);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(realReaction);
lcd.setCursor(0, 1);
lcd.print(" ");
}
}
}
}

the second buzzorled is finished it just skips over the part i made thick text, no matter when i press the button

because after second buzzorled variable looper doesn't equal 0
and condition

while (looper == 0)

doesn't match

Hi,
I made some changes to your code:

unsigned long int counter = 0;
unsigned long int reaction = 0;
I changed to
unsigned long counter = 0;
unsigned long reaction = 0;

I commented out this line: // buttonState = digitalRead(buttonPin);

Added a delay of 5000, (5 secs). to view the reaction value on the LCD.
Modify the calculation of:
realReaction = (reaction - counter);
for
realReaction = (counter - reaction);
because the value in the previous format was negative.

I added the line: looper = 0;
to reset the looper every "round".

see how it turned out and test if it's what you need.
The delay I set to visualize can be changed to smaller values.

#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
const int buzzerPin = 6;
const int buttonPin = 7;
const int ledPin = 8;
unsigned long  counter = 0;
unsigned long  reaction = 0;
int randomDelay = 0;
int randomVal1 = 0;
unsigned long  realReaction = 0;
int buttonState = 0;
int looper = 0;

void setup() {
randomSeed(analogRead(0));
lcd.begin(16, 2);
pinMode(6, OUTPUT);
pinMode(7, INPUT);
pinMode(8, OUTPUT);
}
void loop() {
introduction();
buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH) {
    randomVal1 = random(0, 100);
    randomDelay = random(300, 1000);
    lcd.setCursor(0, 0);
    lcd.print("Tap when you    ");
    lcd.setCursor(0, 1);
    lcd.print("notice sound/led");
    delay(randomDelay);
    reaction = millis();
    buzzerOrLed();
    //buttonState = digitalRead(buttonPin);
    while(looper == 0) {
      lcd.setCursor(0, 0);
      lcd.print("Tap when you    ");
      lcd.setCursor(0, 1);
      lcd.print("notice sound/led");
      buttonState = digitalRead(buttonPin);
        if (buttonState == HIGH) {
          looper++;
          counter = millis();
          realReaction = (counter - reaction);
          lcd.setCursor(0, 0);
          lcd.print("                ");
          lcd.setCursor(0, 0);
          lcd.print(realReaction);
          lcd.setCursor(0, 1);
          lcd.print("                ");
        }
     }
     delay(5000);
  }
  looper = 0;
}

void introduction() {
  lcd.setCursor(0, 0);
  lcd.print("Press the button");
  lcd.setCursor(0, 1);
  lcd.print("to start test   ");
}

void buzzerOrLed() {
  if (randomVal1 > 53) {
  digitalWrite(ledPin, HIGH);
  delay(200);
  digitalWrite(ledPin, LOW);
  } else {
  tone(buzzerPin, 800);
  delay(200);
  noTone(buzzerPin);
  }
}

PS: Sorry.
Hi,
To make it faster just for testing I modified the delay calculation parameters.

but i set it to 0 when i declared it

Well now it sort of works, it does give me a reaction time
im going to se if i can change it a little bit and se if i can get it working how i inteded it to, but thank you

you increment it in code, but never decrement again.

ooooh right, thats ture

Hi,
To make it faster just for testing I modified the delay calculation parameters.

Yeah i noticed, it works perfectly now, but i dont fully understand what change made it work

Hi,
The main change was the inclusion of the line: looper = 0;

looper =0; and delay(5000); at the end of loop()

Ahh i see thanks

Yeah i think i get it now