Trouble with flags tripping all at once insetead of individually

Problem:
I'm using an IR sensor. Once I break the IR sensor's beam with my finger, all my flags trigger sequentially (1, 2, 3, etc.) without stopping instead of tripping one at a time, each time the IR beam is broken.
Screenshot 2021-07-03 215212

I want it to work where "Flag 1" trips once I break the IR beam the first time.
"Flag 2" trips once I break the IR beam the second time.
"Flag 3" trips once I break the IR beam the third time.
"IR_Sensor_Sequence_2_Complete" trips once all the other 3 flags trip successfully.

I've tried nesting my if statements within each-other, using a return command between each if statement, tried using parentheses around the boolean flag variables in the if statements, every combination in between that I can think of, etc.
I'm not exactly sure where I've gone wrong here. Anyone have any advice? (Not looking for someone to write the code for me) Just point me in the right direction please.

Hardware Used:

Sketch:

const int IR_Sensor_Pin = 4;  //Sets the IR sensor pin to digital pin 4

int IR_Sensor_State = 0;  //Variable to determine if the IR sensor beam is broken or not

bool IR_Sensor_Flag_2 = false;  //Flag to help me troubleshoot
bool IR_Sensor_Flag_3 = false;  //Flag to help me troubleshoot
bool IR_Sensor_Sequence_2_Complete = false;  //Flag to help me troubleshoot


void setup()
{
  Serial.begin(115200);  //Baud rate
  pinMode(IR_Sensor_Pin, INPUT);  //Sets the IR sensor pin as an input
  digitalWrite(IR_Sensor_Pin, HIGH); //Turn on the internal pullup resistor
  delay(10);
}

void loop()
{
  IR_Sensor_State = digitalRead(IR_Sensor_Pin);  //Read the state of the IR sensor beam

  if (IR_Sensor_State == LOW)  //Check if the sensor beam is broken. If it is, the sensorState is LOW:
  {
    Serial.println("*****IR SENSOR - FLAG #1*****");  //Flag to help me troubleshoot
    Serial.println();  //Print a blank line for spacing
    IR_Sensor_Flag_2 = true;  //Flag to help me troubleshoot
    delay(1000);  //Pause for 1 second
  }

  if (IR_Sensor_State == LOW && IR_Sensor_Flag_2 == true)  //Recheck the IR sensor beam but only if the "IR_Sensor_Flag_2" is true
  {
    Serial.println("*****IR SENSOR - FLAG #2*****");  //Flag to help me troubleshoot
    Serial.println();  //Print a blank line for spacing
    IR_Sensor_Flag_2 = false;  //Disable "IR_Sensor_Flag_2"
    IR_Sensor_Flag_3 = true;  //Enable "IR_Sensor_Flag_3"
    delay(1000);  //Pause for 1 second
  }

  if (IR_Sensor_State == LOW && IR_Sensor_Flag_3 == true)  //Recheck the IR sensor beam once again but only if the "IR_Sensor_Flag_3" is true
  {
    Serial.println("*****IR SENSOR - FLAG #3*****");  //Flag to help me troubleshoot
    Serial.println();  //Print a blank line for spacing
    IR_Sensor_Flag_3 = false;  //Disable "IR_Sensor_Flag_2"
    IR_Sensor_Sequence_2_Complete = true;  //Enable "IR_Sensor_Flag_3"
    delay(1000);  //Pause for 1 second
  }

  if (IR_Sensor_Sequence_2_Complete == true)  //This statement will only run once the IR sensor has been broken and checked 3 separate times
  {
    Serial.println("*****IR SENSOR - SEQUENCE 2 COMPLETE*****");  //Flag to help me troubleshoot
    Serial.println();  //Print a blank line for spacing
    IR_Sensor_Sequence_2_Complete = false;  //Disable the "IR_Sensor_Flag_Sequence_2_Complete"
  }
}

Anyone have any advice? (Not looking for someone to write the code for me) Just point me in the right direction please.

You need to manage the IR sensor for a state change, not the read state. It's similar to the state change example in the IDE examples.

See if these suggestions get you started.

//add a new variable
int Last_IR_Sensor_State = 0;
int IR_Sensor_State = 0;  //Variable to determine if the IR sensor beam is broken or not 

Then at start of loop

Last_IR_Sensor_State = IR_Sensor_State;//transfer state to last state
IR_Sensor_State = digitalRead(IR_Sensor_Pin);  //Read the new state of the IR sensor beam
 if(IR_Sensor_State == LOW and LastIR_SensorState == HIGH)//beam became broken
 { //start counting for flags}
1 Like

Thank you @cattledog

Ooooh, I see what you're talking about looking at the "State Change" example.

@cattledog you also taught me that I can use "and" instead of "&&". Cool, thanks!

There more "alternative operators".
If you think it makes the code more understandable they are good to use. Experienced coders don't typically use them.

I think that beginners are less likely to make a mistake using the logical "and" (&&) alternative. We see lots of postings on the board with the mistaken use of & (bitand) instead of &&.

Programmer: I finished that thing I'm working on.

%:include <iostream>
 
struct X
<%
    compl X() <%%> // destructor
    X() <%%>
    X(const X bitand) = delete; // copy constructor
 
    bool operator not_eq(const X bitand other)
    <%
       return this not_eq bitand other;
    %>
%>;
 
int main(int argc, char* argv<::>) 
<%
    // lambda with reference-capture:
    auto greet = <:bitand:>(const char* name)
    <%
        std::cout << "Hello " << name
                  << " from " << argv<:0:> << '\n';
    %>;
 
    if (argc > 1 and argv<:1:> not_eq nullptr) <%
        greet(argv<:1:>);
    %> else <%
        greet("Anon");
    %>
%>

Manager: you're fired.

a7