Need coding help with a Photointerrupter

Hey all,

I have to make a door controlled by a photo interrupter. The door needs to open only after the photointerrupter is blocked for 4 seconds or more. The door will be open or close with the help of a motor which is connected to a relay module. So far the codes that I have tried only work when the photo interrupter is initially blocked with no regard to how long it is blocked. I am very new to Arduino coding, so any help is appreciated. Thank you. Attached is the code that I think should work.

const int PIRInterrupt = 2;
const int Relay = 8;
unsigned long startTime;
volatile byte relayState = LOW;

void setup() {
  pinMode(Relay, OUTPUT);
  digitalWrite(Relay, LOW); // Set relay initially OFF

  pinMode(PIRInterrupt, INPUT);

  Serial.begin(9600);
}

void loop() {
  if (digitalRead(PIRInterrupt) == LOW) {
    startTime = millis(); // Record the time when PIR sensor is blocked
    while (digitalRead(PIRInterrupt) == LOW && (millis() - startTime) <= 4000) {
      // Wait for 4 seconds while the PIR sensor is blocked
      // Do nothing during this time
    }
    if (digitalRead(PIRInterrupt) == LOW) {
      // If the PIR sensor is still blocked after 4 seconds,
      // then turn the relay ON
      digitalWrite(Relay, HIGH);
      relayState = HIGH;
      delay(2000);
      digitalWrite(Relay, LOW); // Turn the relay OFF
      relayState = LOW;
    }
  } else {
    digitalWrite(Relay, LOW); // Turn the relay OFF if no motion detected
    relayState = LOW;
  }
}

Try this (untested...) version:

const int P_PIR = 2;
const int P_RELAY = 8;
unsigned long tmrBlocked = 0;

void setup() {
  pinMode(P_RELAY, OUTPUT);
  digitalWrite(P_RELAY, LOW); // Set P_RELAY initially OFF

  pinMode(P_PIR, INPUT_PULLUP);

  Serial.begin(9600);
}

void loop() {
  bool Blocked = (digitalRead(P_PIR) == LOW);
  if (tmrBlocked == 0 && Blocked) {
    // If sensor detects an obstacle and it's the first time, set/start the timer
    tmrBlocked = millis();
    Serial.println("Starting timer...");
  } else {
    // If there is a timer active
    if (tmrBlocked > 0) {
      // if the obstacle is still there after 4 seconds
      if (millis() - tmrBlocked > 4000 && Blocked) {
        Serial.println("Activating relay!");
        // then turn the P_RELAY ON
        digitalWrite(P_RELAY, HIGH);
        delay(2000);
        // then turn the P_RELAY OFF
        digitalWrite(P_RELAY, LOW); 
        // Now wait for the Blocked to get away...
        Serial.println("Waiting for obstacle moving away...");
        while (digitalRead(P_PIR) == LOW) {
          delay(200);
        }
        Serial.println("Ok, done!");
        // Reset the timer
        tmrBlocked = 0;
      } else {
        // If the obstacle got away before the 4 seconds timeout, clear the timer
        if (millis() - tmrBlocked <= 4000 && !Blocked) {
          tmrBlocked = 0;
          Serial.println("Obstacle gone! Timer canceled.");
        }
      }
    }
  }
}

Please note "INPUT_PULLUP" and the relayState variable missing (there's no need of such variable, you can still digitalRead() the replay pin to get its state)...

PS: What is exactly a "photo interrupter" for you? In the sketch you call it "PIR" but a PIR is a "Passive Infrared Sensor", aka motion detector so I suppose you don't really mean a PIR, neither an infrared reflector detector (they're made for detect obstacles for short distance), than a real barrier sensor to be able to know if someone is between the IR transmitter and the sensor (with or without a reflective panel). Please always give complete information about the sensors (and cabling) you're using.

PS2: why don't you test your code using TinkerCad or WokWi? to make things easier, replace the sensor with a pushbutton, and the relay with a LED....

Always show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.

Please test it and report its behaviour here.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.