How to know the activation order of 2 sensors [solved]

Hello all,

I have this project which use 2 IR sensors to count passing objects in two directions in front of it (see picture)..

I used many ways but no luck. The code below - which I used "millis()" is my approach to do that, but it is not reliable. it does not give the exact result.

I cant use "delay()" because there are another sensors working at the same time.

I tried to use "SimpleTimer" library.

the main problem is each sensor depends on the other sensor.

If the object is entering the room the "In" sensor will be activated and add 1 to "TOTAL" after that the "OUT" sensor will be activated and subtract 1 from "TOTAL" - and vice versa - ...

IS THERE ANY WAY TO SOLVE THIS ISSUE..

see the code:

int inPin = 4;
int outPin = 5;

int total = 0;
int first_floor = 0;

boolean sensorInPinTriggered = false;
unsigned long sensorInPinTime;
byte currStateInPin;
byte prevStateInPin = HIGH;

boolean sensorOutPinTriggered = false;
unsigned long sensorOutPinTime;
byte currStateOutPin;
byte prevStateOutPin = HIGH;

void setup() {
    Serial.begin(9600);
    pinMode(inPin, INPUT);
    pinMode(outPin, INPUT);
}

void loop() {
    currStateInPin = digitalRead(inPin);
    if (currStateInPin != prevStateInPin) {
        if (currStateInPin == LOW) {
            sensorInPinTriggered = true;
            sensorInPinTime = millis();
        }
    }
    prevStateInPin = currStateInPin;

    currStateOutPin = digitalRead(outPin);
    if (currStateOutPin != prevStateOutPin) {
        if (currStateOutPin == LOW) {
            sensorOutPinTriggered = true;
            sensorOutPinTime = millis();
        }
    }
    prevStateOutPin = currStateOutPin;

    if (sensorInPinTriggered == true) {
        if (sensorInPinTime < sensorOutPinTime) {
            total = total + 1;
            sensorInPinTriggered = false;
            sensorOutPinTriggered = false;
            printToSerial();
            sensorOutPinTime = millis();
            sensorInPinTime = sensorOutPinTime;
        }
    }
    
    if (sensorOutPinTriggered == true) {
        if (sensorInPinTime > sensorOutPinTime) {
            total = total - 1;
            first_floor = first_floor - 1;
            sensorInPinTriggered = false;
            sensorOutPinTriggered = false;
            printToSerial();
            sensorInPinTime = millis();
            sensorOutPinTime = sensorInPinTime;
        }
    }
}

void printToSerial() {
    Serial.print("Total number: ");
    Serial.println(total);
}

thanks..

SalGh:
...
the main problem is each sensor depends on the other sensor.

That is not the problem, that is the description of your system. Now what is your problem?

arduino_new:
That is not the problem, that is the description of your system. Now what is your problem?

With the code in question when object entering it compares the time and decide if it IN or OUT. But the time doesn't reset, so when leaving, it still comparing the new OUT sensor time With the old IN sensor time.

Another issue: when object entering (or leaving) it Add 1 to Total when IN sensor activated and Subtract 1 when OUT sensor activated although the object is entering.

I think this can be approach with on of these methods:
How I can mute one sensor when the other sensor activated for a specific time.
or,
Is there any other way when the two sensor activated in a specific range of time to know the order of activation.

Thanks..

Perhaps your problem is that your 2 sensors are placed too closely together; that when one person enters, both the sensors are triggered, then it would give incorrect result

loop() {
  if in has just become sensed (gone from low to high, or whatever)
    if the previous most recently sensed was an out, and
          the previous most recently sensed was sensed not more than 1 second ago, then
      we have an 'out' event. Decrement the counter.
    end
    note the fact that the most recently sensed is now 'in'
    note the current time as the most recently sensed time
  end

  if out has just become sensed (gone from low to high, or whatever)
    if the previous most recently sensed was an in, and
          the previous most recently sensed was sensed not more than 1 second ago, then
      we have an 'in' event. Increment the counter.
    end
    note the fact that the most recently sensed is now 'out'
    note the current time as the most recently sensed time
  end
}

arduino_new:
Perhaps your problem is that your 2 sensors are placed too closely together; that when one person enters, both the sensors are triggered, then it would give incorrect result

No, I tried with different distances between them, the results are usually the same.

lets assume this scenario:
Object entering the room. it passes in front of "IN sensor" than it passes in front of OUT sensor. The Total increases by 1.
Now, after 5 seconds, the Object is leaving, so,it passes in front of OUT sensor the Total INCREASES by 1.
(because it compare the time of this sensor with the time of IN sensor when the object entered at first)
and when it complete passing in front of IN sensor it subtract 1 from Total.
and it happening again when object trying to enter again.

Thank you..

Or it could be this scenario:

A person enters the room. The OUT sensor detected it first, it decreases the Total = -1; Then the IN sensor is triggered next, it increases the Total = 0. Now you have a person in the room but the Total is saying 0.

This, of course, assumes that the sensors are both triggered when a person enters (or leaves). And I think this is your primary problem.

arduino_new:
Or it could be this scenario:

A person enters the room. The OUT sensor detected it first, it decreases the Total = -1; Then the IN sensor is triggered next, it increases the Total = 0. Now you have a person in the room but the Total is saying 0.

This, of course, assumes that the sensors are both triggered when a person enters (or leaves). And I think this is your primary problem.

No.... In the code I provided in the first post, I avoided this problem by calculating the activation times of sensors. That is not the problem...

the solution provided by @PaulMurrayCbr looks promising. I'm coding it now..

PaulMurrayCbr:

loop() {

if in has just become sensed (gone from low to high, or whatever)
    if the previous most recently sensed was an out, and
          the previous most recently sensed was sensed not more than 1 second ago, then
      we have an 'out' event. Decrement the counter.
    end
    note the fact that the most recently sensed is now 'in'
    note the current time as the most recently sensed time
  end
.
.
}

thanks

SalGh:
the solution provided by @PaulMurrayCbr looks promising. I'm coding it now..

Let us know if it works for you, and perhaps also put [solved] in the title of the thread.

Note the need for the "if the sensor has just become sensed" logic. Without it, the logic will oscillate when both beams are blocked, which always happens when a person is walking through.

Hello All,

All thanks go to @PaulMurrayCbr for his approach, it works like charm.

I changed the location of the sensors to mach their position relating to the room (see the picture):

pro_002.png

Still there are two downgrades:

  1. If two objects enter at the same time range, it gives wrong result.
  2. If an object triggers the 2 sensors at the same time. the reading gives wrong result.

And here's the code:

int outPin = 4;
int inPin = 5;

int total = 0;

byte inSensor;
byte outSensor;

int timeDiff;
int inSensorTime;
int outSensorTime;

int lastSensed = 0;
static int lastSensedIn = 101;
static int lastSensedOut = 102;

void setup()
{
    Serial.begin(9600);
    pinMode(inPin, INPUT);
    pinMode(outPin, INPUT);
}

void loop()
{
    inSensor = digitalRead(inPin);
    outSensor = digitalRead(outPin);

    if (inSensor == LOW)          // IR sensor: when activated become LOW.
    { 
        inSensorTime = millis();          // record sensor activated time.
        if (lastSensed == lastSensedOut)
        {
            timeDiff = inSensorTime - outSensorTime;         // calculate activation time difference.
            if (secToNow < 500)         // time range here = 0.5 second
            {
                total = total + 1;
                printToSerial();
            }
        }
        lastSensed = lastSensedIn;           // assign last sensed sensor to inSensor.
    }
    if (outSensor == LOW)
    {
        outSensorTime = millis();
        if (lastSensed == lastSensedIn)
        {
            timeDiff = outSensorTime - inSensorTime;
            if (secToNow < 500)
            {
                total = total - 1;
                printToSerial();
            }
        }
        lastSensed = lastSensedOut;           // assign last sensed sensor to outSensor.
    }
}

thanks again...

pro_002.png

Think of something like this:

inSensor = digitalRead(inPin);
outSensor = digitalRead(outPin);
sensorState = 2 * inSensor + outSensor;

If someone goes out, the sensorState sequence will be:
0->2->3->1->0,
coming in will be,
0->1->3->2->0, go from there. :grin: :cold_sweat:
Make inSensor and outSensor booleans and sensorState a byte type, don't have HW to try it myself.

SalGh:
Still there are to downgrades:

  1. If two objects enter at the same time range, it gives wrong result.
  2. If an object triggers the 2 sensors at the same time. the reading gives wrong result.

And this is why places that need to count people have a turnstile, or some other way of making people slow down and pass one at a time.