Need Help ! Using two IR sensors to control LED

Hello Community !

I am stuck with one project. Having two IR sensor(NPN NO) to control the LED.
When sensor1 triggers it should turn on LED for 5 seconds. If sensor2 doesn't triggers within 5 seconds it should turn off LED. If sensor2 trigger and gives LOW output within 5 seconds then it should remain LED on untill sensor2 stops giving LOW output.
After that when sensor1 stops giving output and again gives LOW output it should start loop again.

I have tried below code but no success as newbie.

int sensor1 = 3;
int sensor2 = 4;
int led = 7;

void setup() {
  // put your setup code here, to run once:
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(led, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  int Reading1 = digitalRead(sensor1);
  int Reading2 = digitalRead(sensor2);

  if (Reading1 == LOW && Reading2 !=LOW) {
    digitalWrite(led, HIGH);
    delay(5000);
  } else {
    digitalWrite(led, LOW);
  }
    if (Reading1 == LOW && Reading2 ==LOW) {
    digitalWrite(led, HIGH);
    } else {
      digitalWrite(led,LOW);
    }


Please help !!!!!!!

the delay stops program execution for 5 seconds so any changes in sensor2 etc are not detected until the 5 seconds is over
look at using millis()

2 Likes

Thanks for helping I will try millis and tell how it run

is not sufficient.

There is a fundamental difference between using delay()
and
using non-blocking timing based on milis().

In my experience it is very important to re-direct newcomers in their thinking to avoid that the newcomer sees a delay()-similar thing in millis().

This misconception of thinking millis() is a delay() similar thing makes it very hard to understand how non-bocking timing based on millis() works
because the code does not fit to what delay() is.

So the introduction to non-blocking timing becomes much easier to understand if this fundamental difference is explained first and with an everyday example.

best regards Stefan

Make a smaller project where the first IR sensor turns the LED ON (and stays on), and the second IR sensor turns the LED OFF (and stays off).

Next, learn about millis() and combine millis() with the first project starting with the LED OFF, then with the IR sensor, turning the LED ON for five seconds, then back OFF.

Do the same with the second IR Sensor, starting with the LED ON, turning it LED OFF, wait five seconds, the turn the LED ON.

Then, add the rest of your project, with missed triggers.

const int sensorPin1 = 2; // Replace with your actual pin numbers
const int sensorPin2 = 3;
const int ledPin = 13;

unsigned long sensor1StartTime = 0;
unsigned long sensor2StartTime = 0;
const unsigned long ledDuration = 5000; // 5 seconds

enum State {
  IDLE,
  SENSOR1_TRIGGERED,
  SENSOR2_TRIGGERED
};

State currentState = IDLE;

void setup() {
  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int sensor1Reading = digitalRead(sensorPin1);
  int sensor2Reading = digitalRead(sensorPin2);

  switch (currentState) {
    case IDLE:
      if (sensor1Reading == LOW) {
        sensor1StartTime = millis();
        digitalWrite(ledPin, HIGH);
        currentState = SENSOR1_TRIGGERED;
      }
      break;

    case SENSOR1_TRIGGERED:
      if (sensor2Reading == LOW) {
        sensor2StartTime = millis();
        currentState = SENSOR2_TRIGGERED;
      } else if (millis() - sensor1StartTime >= ledDuration) {
        digitalWrite(ledPin, LOW);
        currentState = IDLE;
      }
      break;

    case SENSOR2_TRIGGERED:
      if (sensor2Reading == HIGH) {
        currentState = SENSOR1_TRIGGERED;
        if (millis() - sensor1StartTime >= ledDuration) {
          digitalWrite(ledPin, LOW);
        }
      } else if (millis() - sensor2StartTime >= ledDuration) {
        currentState = IDLE;
        digitalWrite(ledPin, LOW);
      }
      break;
  }
}

I have tried this code but LED remains on due to sensor1 giving output

I’ve occasionally found that I needed to think hard what I really meant by ‘triggered’. Whether it’s a button being pressed or a fox interrupting my IR sensor, the distinction between ‘has just been triggered’ and ‘is being triggered’ has been important.

it is "being triggered". I am using this project on a thread unwinding machine.

If there is bobbin in place sensor1 is being triggered untill bobbing has been removed. and sensor2 checks if thread is passing through hole or not.

If there is bobbin sensor1 is being triggered so it will on LED for 5 second, within this 5 second if sensor2 is being triggered keep the LED on untill sensor2 stops giving output.
Then when the bobbin which was placed removed and placing other bobbin (sensor will be stops giving output and gives output again) whole cycle will be run again,

So the simply LED should on from Sensor1 signal and off from sensor2.

int sensor1 = 3;
int sensor2 = 4;
int led = 7;
unsigned long timer;

void setup() {
  pinMode(sensor1, INPUT);
  pinMode(sensor2, INPUT);
  pinMode(led, OUTPUT);
}

void loop() {
  int Reading1 = digitalRead(sensor1);
  int Reading2 = digitalRead(sensor2);

  if (Reading1 == LOW) {
    digitalWrite(led, HIGH);
    timer = millis();
    while ((millis() - timer) < 5000) {
      Reading2 = digitalRead(sensor2);
      if (Reading2 == LOW) {
        while (Reading2 == LOW) {
          Reading2 = digitalRead(sensor2);
        }
        break;
      }
    }
    digitalWrite(led, LOW);
  }
}

Jusy a thought: perhaps you need to change the state to IDLE when the bobbin is in transit.

this while may cause a watchdog timer reset, e.g. on a ESP32
also would cause problems if other tasks were to be carried out in parallel with testing the two sensor input s
would this work

void loop() {
  static unsigned long timer1=0;
  int Reading1 = digitalRead(sensor1);
  int Reading2 = digitalRead(sensor2);
  if (timer1==0 && Reading1 == LOW) {
    digitalWrite(led, HIGH);
    timer1 = millis();
     }
  if(millis()-timer1 >= 5000  && Reading2 == HIGH) {
    timer1=0;
    digitalWrite(led, LOW);
  }
}

EDIT: works OK on a UNO

modified you SENSOR1_TRIGGERED state

const int sensorPin1 = 2; // Replace with your actual pin numbers
const int sensorPin2 = 3;

const int ledPin = 13;

unsigned long sensor1StartTime = 0;
const unsigned long ledDuration = 5000; // 5 seconds

enum State {
    IDLE,
    SENSOR1_TRIGGERED,
    SENSOR2_TRIGGERED
};

State currentState = IDLE;

void loop() {
    int sensor1Reading = digitalRead(sensorPin1);
    int sensor2Reading = digitalRead(sensorPin2);

    switch (currentState) {
    case IDLE:
        if (sensor1Reading == LOW) {
            sensor1StartTime = millis ();
            digitalWrite(ledPin, HIGH);
            currentState = SENSOR1_TRIGGERED;
        }
        break;

    case SENSOR1_TRIGGERED:
        if (sensor2Reading == LOW) {
            delay (20);         // debounce
            currentState = SENSOR2_TRIGGERED;
        }
        else if (millis() - sensor1StartTime >= ledDuration) {
            digitalWrite(ledPin, LOW);
            currentState = IDLE;
        }
        break;

    case SENSOR2_TRIGGERED:
        if (sensor2Reading == HIGH) {
            currentState = IDLE;
            digitalWrite(ledPin, LOW);
        }
        break;
    }
}

void setup()
{
    Serial.begin (9600);

    pinMode(sensorPin1, INPUT);
    pinMode(sensorPin2, INPUT);
    pinMode(ledPin, OUTPUT);
}

SENSOR1_TRIGGERED and SENSOR2_TRIGGERED are really events (stimuli) not states. SENSOR1_TRIGGERED is really the Timed state and SENSOR2_TRIGGERED is kinda an Override state

But in reply to my post #7 the OP said it was a state.

IOW that state would last as long as the sensor reading was low. (Presumably because the IR Tx/Rx beam was being interrupted.)

just commenting on how the states are named

You have two accounts?

You have two accounts?

for under cover work :grinning:

1 Like

That must be a much more sensitive IR pair than the cheap ones I've played with. Does it reliably detect such a thin target?

Are you simulating with a couple of simple buttons, or are you actually testing with the IR pairs?

Hello heetpatel7744

consider this small example:

const int sensorPin1 = 2; // Replace with your actual pin numbers
const int sensorPin2 = 3;
const int ledPin = 13;
const unsigned long ledDuration = 5000; // 5 seconds
enum ButtonState {Off, On};
struct TIMER
{
  uint32_t duration;
  uint8_t   control;
  uint32_t now;
};
TIMER timeMonitor {ledDuration, LOW, 0};

void setup() {
  pinMode(sensorPin1, INPUT);
  pinMode(sensorPin2, INPUT);
  pinMode(ledPin, OUTPUT);
}
void loop()
{
  uint32_t timeNow = millis();
  if ((digitalRead(sensorPin1) && digitalRead(ledPin) ? LOW : HIGH) == On)
  {
    timeMonitor.control = HIGH;
    timeMonitor.now = timeNow;
    digitalWrite(ledPin, HIGH);
  }
  if (timeNow - timeMonitor.now >= timeMonitor.duration && timeMonitor.control)
  {
    timeMonitor.control = LOW;
    digitalWrite(ledPin, LOW);
  }
  digitalWrite(ledPin, timeMonitor.control || digitalRead(sensorPin2));
}

hth

in the test of the program in post 12 (which worked correctly) I use a shield with buttons