beam break for entry and exit

I have 2 sets of Banner IR beam transmitter and receiver. I need to know when a person enters a room, and when they exit. I will establish Beam A and beam B.
When beam A is interrupted and then beam B, it means a person has entered the room. In reverse, it means they have left.
Upon enter, a sound clip is played. Upon exit, nothing happens.
This all takes place indoors, and the beams are about 12 inches apart. I plan to have them set up around waist high so that the beam is broken once ( as opposed to leg height, which has the double break issue). This does not have to be accurate in that groups, or a person stopping in between the beams or other such exceptions do not need to be considered.

I do not need a counter. I have searched around for IR beam break, IR tripwire, laser tripwire and so on. I am not asking for someone to write my code. I would like to be directed to examples so that I can customize to meet my needs. Or, if someone can point me in the direction of the logic needed to solve this.
Is it an issue of A + B = C, but B + A = D. I am having a weird time wrapping my head around the logic as it applies to the code.

I know it is simple and I can't find a solution because I am looking for a complex answer...so any direction or coaching or words of wisdom would be appreciated.

thanks

MY approach would be to record the time in milliseconds when beam A is broken and add 1 to a counter. Record the time in milliseconds when beam B is broken and add 1 to the counter.

When the counter = 2, compare the times and see which is higher. That tells you which one was broken last and that give you the direction. Then reset all times and counter.

Paul

Hi,

¿How close may two persons -that pass through A - B one after the other- be?; ¿May the time be so small that the whole system may be fooled?

Regards

vffgaston:
Hi,

¿How close may two persons -that pass through A - B one after the other- be?; ¿May the time be so small that the whole system may be fooled?

Regards

Very true, but that was not part of the specification.

Paul

That is correct Paul. I think I will create some code and then post it to see what you think. I think I will record the time with millis(), and if A > B then the person has entered. If B > A, do nothing. Reset timer to zero.

If I skip the counter altogether do you think that will be an issue ?

Thanks you.

Paul, I am including some code I wrote. I have not tested it, and it is not very elegant and it is redundant in the loop section. Specifically with the multiple if () statements....

I am sure there are issues, but if you could look at it and see if there is anything that is clearly boneheaded logic....

Thank You

unsigned long TimeA = 0; // timer for the first ir tripwire
unsigned long TimeB = 0; //timer for the second ir tripwire

int senA = 4;// first tripwire

int senB = 5;// second tripwire

int sound = 6;// relay that triggers a sound file on an MP3 sound module
int light = 7;// relay for a bank of LED can lights
void setup()
{
  pinMode(senA, INPUT);
  pinMode(senB, INPUT);

  pinMode(senA , INPUT_PULLUP);
  pinMode(senB , INPUT_PULLUP);

  pinMode(sound, OUTPUT);
  digitalWrite(sound, HIGH);// the relay boards turn on the relay when pulled LOW

    pinMode(light, OUTPUT);
  digitalWrite(light, HIGH);
}

void loop()
{
  if (digitalRead(senA) == LOW)   //  if you enter the room, you will trip the A sensor first. When you leave, you trip the B sensor first
  {
TimeA = millis();
  }
    if (digitalRead(senB) == LOW)
  {
TimeB = millis();
  }

  if( TimeA > TimeB)
  {
    digitalWrite(sound, LOW);
     digitalWrite(light, LOW);
  }
else
{
      digitalWrite(sound, HIGH);
     digitalWrite(light, HIGH);
}
  if( TimeA < TimeB)
  {
    digitalWrite(sound, HIGH);
     digitalWrite(light, HIGH);
  }
else
{
      digitalWrite(sound, HIGH);
     digitalWrite(light, HIGH);
}
}
void loop()
{
  if (digitalRead(senA) == LOW)   //  if you enter the room, you will trip the A sensor first. When you leave, you trip the B sensor first
  {
TimeA = millis();
  }
    if (digitalRead(senB) == LOW)
  {
TimeB = millis();
  }

Those two digitalReads take place at most a couple of microseconds apart.

furmanrobot:
That is correct Paul. I think I will create some code and then post it to see what you think. I think I will record the time with millis(), and if A > B then the person has entered. If B > A, do nothing. Reset timer to zero.

If I skip the counter altogether do you think that will be an issue ?

Thanks you.

The counter tells you both beams have been broken.

Paul

furmanrobot:
Paul, I am including some code I wrote. I have not tested it, and it is not very elegant and it is redundant in the loop section. Specifically with the multiple if () statements....

I am sure there are issues, but if you could look at it and see if there is anything that is clearly boneheaded logic....

Thank You

unsigned long TimeA = 0; // timer for the first ir tripwire

unsigned long TimeB = 0; //timer for the second ir tripwire

int senA = 4;// first tripwire

int senB = 5;// second tripwire

int sound = 6;// relay that triggers a sound file on an MP3 sound module
int light = 7;// relay for a bank of LED can lights
void setup()
{
  pinMode(senA, INPUT);
  pinMode(senB, INPUT);

pinMode(senA , INPUT_PULLUP);
  pinMode(senB , INPUT_PULLUP);

pinMode(sound, OUTPUT);
  digitalWrite(sound, HIGH);// the relay boards turn on the relay when pulled LOW

pinMode(light, OUTPUT);
  digitalWrite(light, HIGH);
}

void loop()
{
  if (digitalRead(senA) == LOW)  //  if you enter the room, you will trip the A sensor first. When you leave, you trip the B sensor first
  {
TimeA = millis();
  }
    if (digitalRead(senB) == LOW)
  {
TimeB = millis();
  }

if( TimeA > TimeB)
  {
    digitalWrite(sound, LOW);
    digitalWrite(light, LOW);
  }
else
{
      digitalWrite(sound, HIGH);
    digitalWrite(light, HIGH);
}
  if( TimeA < TimeB)
  {
    digitalWrite(sound, HIGH);
    digitalWrite(light, HIGH);
  }
else
{
      digitalWrite(sound, HIGH);
    digitalWrite(light, HIGH);
}
}

You only read the sensors if the count is less than 2. Do the compare of times only when the is = 2.

Paul

My concern about the timer is that having the comparison happen when the counter is = to 2 is tricky, as the sensors are milliseconds apart. It would almost need to be if(counter > 1 && counter < 3). Does that seem a little awkeward?

Am I loosing anything by just comparing all of the time and not just when both sensors have been triggered ? Does the condition of both being triggered need to be a variable ?
Or is it sufficient to just to have A > B ? The chances of someone just triggering A and not B, or triggering B and not A is unlikely, if not impossible.

I don't know. Looks like I will have to set it up and test ! Oh well. The boss may have an issue with that use of time, but it is a matter of it working...and not !

thanks

Out of curiosity, is there another approach to the logic ?

furmanrobot:
Out of curiosity, is there another approach to the logic ?

Your initial premise was: I have 2 sets of Banner IR beam transmitter and receiver. I need to know when a person enters a room, and when they exit.

You tell me if there is other logic to do this. You can only tell what happened when both beams have been broken. The order of breaking is kind of important in determining which direction the person is moving. That is only known if we can determine which beam was broken last.

Paul

furmanrobot:
Out of curiosity, is there another approach to the logic ?

Seems like a quadrature sort of thing.

You will have to add some kind of timeout: the second beam must be broken within a certain time of the first, or it gets ignored.

This to allow for someone to break one beam, but not continuing in the second. Without such a time limit you may get very strange effects.

I would record the latest time a beam gets broken (not is broken!) and if the difference between the two is smaller than say 500 ms we just detected a passage. So something like this:

unsigned long beamATime = 0;
bool beamAStatus = HIGH;
unsigned long beamBTime = 0;
bool beamBStatus = HIGH;
bool breakDetected  = false;
unsigned int timeout = 500;

void loop() {

  // Read the beam status, and record when it was last broken.
  if (digitalRead(beamAPin) == LOW && beamAStatus == HIGH) {
    beamAStatus = LOW;
    beamATime = millis();
    breakDetected = true;
  }
  else {
    beamAStatus = HIGH;
  }
  if (digitalRead(beamBPin) == LOW && beamBStatus == HIGH) {
    beamBStatus = LOW;
    beamBTime = millis();
    breakDetected = true;
  }
  else {
    beamBStatus = HIGH;
  }

  // See if we have motion in one direction or the other.
  if (breakDetected) {
    breakDetected = false;
    if (beamATime - beamBTime < timeout) {
      // Movement from B to A.
    }
    else if (beamBTime - beamATime < timeout) {
      // Movement from A to B.
    }
  }
}

Paul, I obviously mean zero disrespect. When I am working on code, and therefor a mode of logic, I tend to become myopic and as such will miss other opportunities of expression. I am slowly discovering perception through logic and coding. The latter not just a list of commands.

Anyway, I was just looking to see if there was alternative ways to skin this cat. I will continue to use this way and I will post the results when I have assembled the whole thing. Thank you for your brain.

Dougp,

You are correct is say that it "Seems like a quadrature sort of thing.

I checked out your link. I have looked at encoders before, but I have never combed through the code.

Could you possibly direct me to a page that has the code to read a rotary encoder and is commented in great detail ? I would like to see if I can adapt that solution to my issue....as long as it is "simple".

Thank You

Your beams are so far apart that you can not guarantee them to be broken at the same time: it is very well possible for the first beam to make again before the second breaks. That is a major difference with a quadrature encoder, where the pattern can be guaranteed.

furmanrobot:
Paul, I obviously mean zero disrespect. When I am working on code, and therefor a mode of logic, I tend to become myopic and as such will miss other opportunities of expression. I am slowly discovering perception through logic and coding. The latter not just a list of commands.

Anyway, I was just looking to see if there was alternative ways to skin this cat. I will continue to use this way and I will post the results when I have assembled the whole thing. Thank you for your brain.

No offense taken at all. Your system is so easy to test, I would expect you to have several iterations of design and programming so you can determine which is best.

Paul

Thanks for this thread.

I was after doing the same thing, to turn my bathroom (HUE) light on and off, I have been using a PIR attached to an esp8266 as my trigger and then just a timer ....

I have two IR receiver sensors set right next to each other, on the door frame, so they are only about 1cm apart, and so I only need one emitter on the other side of the frame, but rather than polling I have the sensor pins as interrupts which set a boolean flag "true" when broken and saves the time of each 'falling interrupt.

In my loop I then just use the following logic

void loop() {
if(bathbreak && landingbreak) { // somebody is passing thru'

//reset them

bathbreak = false;
landingbreak = false;

//Which direction were they going in?

if(landingtime < bathtime) {
//going in turn light on
switchLight(1, true); //function that talks to HUE hub
} else {
//going out turn light off
switchLight(1, false);
}
}
}

The initial test code - minus HUE stuff and networking - just turning on the boards LED is as follows

// TEST IR Beams to replace PIR in bathroom (which is off the Landing ...)

int bathpin = 2; //define interrupt pins Bathroom side
int landingpin = 3; // Landing side

// The variables shared between the ISR's are volatile.
volatile bool bathbreak = false;
volatile bool landingbreak = false;
volatile unsigned long bathtime = 0;
volatile unsigned long landingtime = 0;

void setup() {
pinMode(13, OUTPUT); //set pin 13 (board LED) as output for testing

//interrupts set up when beams are broken

attachInterrupt(digitalPinToInterrupt(bathpin), bathbeam, FALLING);
attachInterrupt(digitalPinToInterrupt(landingpin), landingbeam, FALLING);

}
void loop() {
if(bathbreak && landingbreak) {
//reset them
bathbreak = false;
landingbreak = false;
if(landingtime < bathtime) {
//going in
digitalWrite(13, HIGH);
} else {
//going out
digitalWrite(13, LOW);
}
}
}

void bathbeam() {
//ISR function
bathbreak = true;
bathtime = millis();
}
void landingbeam() {
//ISR function
landingbreak = true;
landingtime = millis();
}

There is an issue, that if you break the beaks (light on) and then retreat without entering the bathroom the light will stay on as it won't see you leave ... I could test for this, but I tend not to stand in the doorway and change my mind when I am going to the bathroom so I can live with that ... it also doesn't handle a second person joining you in the bathroom and then leaving so leaving you in the dark ...

Hope this helps somebody else searching / exploring this scenario ...

I like the Interrupts as the next stage is to be constantly polling humidity in the main loop for an extraction fan function.

Pete