Trouble reading and resetting photoresistor value

So I want to build a little game which I found online, where you "blind a cyclops" by shining a laser on a photoresistor. To blind the cyclops you have to shine the laser on the photoresistor consistently for 2 seconds, then the LED (eye) goes out.
I'm having trouble with the loop though, the version that I'm uploading is the most working that I have. But the trouble that I have is that the while statement freezes the reading of the photoresistor, so whenever you shine the laser on the photoresistor, it keeps reading that value for 2 seconds, when it triggers the Write LED LOW and waits for 5 seconds.

The behaviour that I would expect is:

  • if statement reads once, triggers the start point for reading, which is the basis for the 2 second delay
  • the while loop continuously reads the photoValue, triggers when it reads > 1010 for 2 seconds but falls out when it doesn't.

Where am I going wrong?

/*  Blind the cyclops!
 *  Het doel van dit spel is om de photoresistor te raken met de laserstraal en zo de cycloop te verblinden. Als de taak geslaagd is dooft de LED boven het hoofd van de cycloop.
 *  Als het oog van de ene cycloop verblind is kan er nog een tweede oog aan toegevoegd worden om de puzzel te vermoeilijken. Daarbij kan bijvoorbeeld een specifieke tijd ingesteld
 *  worden waarbinnen de twee triggers af moeten gaan. De ogen van de cyclopen kunnen namelijk herstellen!
 */

const int laserPin = 12;     // define laser pin
const int ledPin = 13;      // define LED pin
const int photoPin = A0;    // define analog photoresistor pin

int photoValue = 0;         // initialize photoresistor
int photoStart = 0;         // define starting time when laser hits photoresistor
int photoEnd = 0;           // define end time when laser leaves photoresistor

unsigned long tijd;

void setup() {
  pinMode(laserPin, OUTPUT);    // define laser pin as output
  pinMode(ledPin, OUTPUT);      // define led pin as output
  Serial.begin(9600);           // start communication with serial monitor
}

void loop(){

  photoValue = analogRead(photoPin);      // read value from photoresistor
  
  tijd = millis();
  
  digitalWrite(laserPin, HIGH);             // initialize the laser beam
//  Serial.println(photoValue);             // print the value from the photoresistor (only for calibration purposes)
     
  if (photoValue > 1010){                   // if the laser beam hits the photoresistor, set the start value to the current millis value
    photoStart = millis();
       
    while(photoValue > 1010){               // check whether the laser beam is triggering the photoresistor. Adapt equation to calibration value. While the laser beam is hitting the photoresistor, this loop will run.

      Serial.println(photoValue);
      if (millis() - photoStart > 2000){    // if the laser beam has been on the target for more than 2 seconds, trigger the LED
      digitalWrite(ledPin, LOW);            // kill the LED
      delay(5000);                          // wait 5 seconds
      photoValue = 0;                       // write photoValue to 0 to reset the loop
      }     
    }
  }
  else if (photoValue < 1000){              // reset the LED
    digitalWrite(ledPin,HIGH);
  }
}
  if (photoValue > 1010){                   // if the laser beam hits the photoresistor, set the start value to the current millis value
    photoStart = millis();
       
    while(photoValue > 1010){               // check whether the laser beam is triggering the photoresistor. Adapt equation to calibration value. While the laser beam is hitting the photoresistor, this loop will run.

      Serial.println(photoValue);
      if (millis() - photoStart > 2000){    // if the laser beam has been on the target for more than 2 seconds, trigger the LED
      digitalWrite(ledPin, LOW);            // kill the LED
      delay(5000);                          // wait 5 seconds
      photoValue = 0;                       // write photoValue to 0 to reset the loop
      }     
    }
  }

That code part is executed if photoValue is greater than 1010. You later enter a while loop that runs as long as photoValue is greater than 1010. Inside that loop the only way to change photoValue is when the timeout is reached.

You forgot the read the value often enough. The variable isn't updating if you don't actively do it.

So I've noticed that inside the if condition the photoValue is read continuously. I tried to do it without the while loop (just the if-statement), but that doesn't work because it sets the photostart = millis() continuously as well. So you never get a time difference.

I tried adding a photoValue; statement inside the while loop but that didn't work.

I can't place your suggestion right now. Why doesn't the while loop exit when the condition is untrue? Namely when I remove the laser from the photoresistor. That's the point of a while loop right?

What's the point of the if just before the while of the same condition?

I think you can simplify all of it just by using timing variables.
Start a timer once it is 'hit', reset timer when it no longer 'hits', check if timer makes it to >2000ms and respond accordingly.

The thought behind the if statement was to trigger the starting point for the measurement, once. After that it would enter a while loop to check whether the 2 seconds has passed. Unfortunately my logic is off.

I've tried several options but all are failing, could someone assist me with some code?

I tried adding a photoValue; statement inside the while loop but that didn't work.

I guess that's the error you make: photoValue is not a statement, it's simply a variable. The value of the variable does only change if you put some code in that assigns something. In your case it's the assignment

photoValue = analogRead(photoPin);

that does change that variable. analogRead() is a function that converts the voltage at the specified pin into a digital number and returns that number. Without calling that function you won't get a new voltage value into your variable.

So I chose a different solution. Instead of using exact time with all the trouble that was attached to it I decided to use a simple increment counter that counts to 50. Less exact but for the purpose of the game it doesn't matter.

This loop counts val to 50 while the laser beam triggers the photoresistor. When the laser beam doesn't, val falls back to 0. When it reaches 50, the cyclops is blinded, i.e. the LED is killed.

/*  Blind the cyclops!
    Het doel van dit spel is om de photoresistor te raken met de laserstraal en zo de cycloop te verblinden. Als de taak geslaagd is dooft de LED boven het hoofd van de cycloop.
    Als het oog van de ene cycloop verblind is kan er nog een tweede oog aan toegevoegd worden om de puzzel te vermoeilijken. Daarbij kan bijvoorbeeld een specifieke tijd ingesteld
    worden waarbinnen de twee triggers af moeten gaan. De ogen van de cyclopen kunnen namelijk herstellen!
*/

const int laserPin = 12;     // define laser pin
const int ledPin = 13;      // define LED pin
const int photoPin = A0;    // define analog photoresistor pin

int photoValue = 0;         // initialize photoresistor
long photoStart = 0;        // define starting time when laser hits photoresistor
int val = 0;
int blinded = 0;

void setup() {
  pinMode(laserPin, OUTPUT);    // define laser pin as output
  pinMode(ledPin, OUTPUT);      // define led pin as output
  Serial.begin(9600);           // start communication with serial monitor
}

void loop() {

  photoValue = analogRead(photoPin);      // read value from photoresistor

  if (blinded != true){
    
    digitalWrite(ledPin, HIGH);
    digitalWrite(laserPin, HIGH);       // initialize the laser beam
  
    if (photoValue > 995) {             // check whether the laser beam is triggering the photoresistor. Adapt equation to calibration value. 
      val++;                            // if it is, start incrementing val by 1
      Serial.print("Val count is");
      Serial.println(val);
      if (val == 50){                   // when val reaches 50, kill the cyclops
        blinded = true;
        digitalWrite(ledPin,LOW);
        digitalWrite(laserPin, LOW);    // kill the laser for safety purposes
        Serial.print("You have blinded the cyclops");                  
        }
      }
    else {                              // if the laser beam stops triggering the photoresistor before val reaches 50, reset val
      val = 0;
      }
    }
  else {                                // if blinded is true, wait 5 seconds before resetting the game
    delay(5000);
    blinded = false;    
    }
  }