Engineering project involving relay and proximity sensor

So i will start by just explaining what i am trying to do, I have a big grinder that grinds compression type springs, I have a vibrating bowl feeder that channels these thing in line one after another inside of a tube. I have a relay board where i will trigger two separate pneumatic solenoids to push forward and keeps the springs from falling out for the tube. I have an IR sensor and when it senses the next whole it cycles through telling the relays to open and close in a certain order.

My real problem is i want the sensor to read high for a couple of seconds. The way i have it now any little thing will trigger it, and what i got right now.... ot going to work. I will post what i have under

const int Lower = 5;
const int Spare = 6;
const int Upper = 7;
const int ir_sensor = 12;


void setup() {
  Serial.begin(9600);
  pinMode(Lower, OUTPUT);
  pinMode(Upper, OUTPUT);
  pinMode(Spare, OUTPUT);
  pinMode(ir_sensor, INPUT);
  digitalWrite(Lower, HIGH);
  digitalWrite(Upper, LOW);
  
}

void loop(){

int state = digitalRead(ir_sensor);
Serial.println(state);

if (state==HIGH){
  Serial.println("Hole Detected");
  digitalWrite(Upper, HIGH);
  delay(1000);
  digitalWrite(Lower, LOW);
  delay(3000);
  digitalWrite(Lower, HIGH);
  delay(1000);
  digitalWrite(Upper, LOW);
}
else {
  digitalWrite(Lower, HIGH);
  digitalWrite(Upper, LOW);
} 
}

i had tried something where i tried getting the current time with millis() and i figured there is probably an easier way to do this

unsigned long previousMillis = 0; //will store last time LED was blinked
const long period = 1000; // period at which to blink in ms

Suggest you only look at sensor changes in state, NOT when the sensor is true.

Us a state machine to generate your sequence, use a Flag to disable sensor until the sequence is over.

Don't use delay()s.

Hi there,

You could try something similar to a digital button debounce where you take a reading, wait a little while and then check the reading again and only register HIGH if both readings are HIGH. A simple implementation might look something like this:

byte pin = 12;
int debounceWait = 1000; //time (in ms) to wait before taking another reading
unsigned long debounceTimer = 0; 

void setup(){
    pinMode(pin, INPUT);
}

void loop(){
   bool firstReading = digitalRead(pin);
   if(millis() - debounceTimer > debounceWait){
      if(digitalRead(pin) == firstReading && firstReading){ //if the two readings are the same and are HIGH
          //Do something
      }
     debounceTimer = millis();
   }
}

However, if you want the IR sensor to read HIGH for the entire duration of the wait in order for the final output to count as HIGH, then I would suggest something like this:

byte pin = 12;
int minTimeHigh = 1000; //minimum time during which the pin must be high
unsigned long waitTimer = 0; 

void setup(){
    pinMode(pin, INPUT);
}

void loop(){
  if(!digitalRead(pin)) waitTimer = millis(); //whenever the sensor reads low, reset the waitTimer
  if(millis() - waitTimer > minTimeHigh){
    //do something
   }
}

I hope I've understood the requirements correctly and if so I hope this helps! Cheers!