counting persons that pass with IR sensor

I am using a very simple IR sensor (www.velleman.eu/products/view/?id=349823) in order to count the amount of people that pass.
I used a piece of code, but with this it is not just counting each time the beam is interrupted, but keeps on counting while the beam is interrupted.

I have been searchiing the forums but i can;t seem to find a solution, although i think it is such a simple thing.
anybody can help?

willem

int pirPin = 2; //digital 2
int counter = 0;
int state;
int laststate = HIGH;

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

void loop(){
int state = digitalRead(pirPin);
if ( state != laststate) {

//was motion detected
counter=counter+1;
Serial.println(counter);
}

laststate = state;
delay(0);
}

although i think it is such a simple thing.

it is not simple, not very difficult, but far from trivial.

e.g. your sketch does also not

  • differentiate between people walking back and forth.
  • detecting 2 persons simultaneously
  • slow versus fast people

furthermore when posting code, please use CRTL-T in the IDE for autoformatting and use the # button to provide code tags

try this variation

void loop()
{
  int state = digitalRead(pirPin);
  if ( state != laststate) 
  {
     laststate = state;
     counter=counter+1;
     Serial.println(counter);
  }
}

Hi Rob,

thanks. It's my first post to the forum, so i am not yet at all used to the formalities.

e.g. your sketch does also not

  • differentiate between people walking back and forth.
  • detecting 2 persons simultaneously
  • slow versus fast people

-I don't mind about people walking back and forth, a passer by is a passer by
-detecting two people simultaneously is something for the future
-slow vs fast: as long as i can count them i am happy.

The problem remains with your adaptation to the code: it starts counting the moment the beam is interrupted, but it keeps on counting till the interruption is gone.

need to find a way to let it count only when the state changes, from HIGH to LOW, and stop counting until another state-change takes place.

The problem remains with your adaptation to the code: it starts counting the moment the beam is interrupted, but it keeps on counting till the interruption is gone.

if state reads HIGH lastState becomes HIGH too, and as long as state reads HIGH the code will not come in the if part again. (it does come in the if part when going from HIGH to LOW so it will probably double your counts)
==> unless you have noise on your line which changes state continuously...

try

void loop()
{
  int state = digitalRead(pirPin);
  Serial.println(state);
}

what does it do ?

At which distance the PIR switches from LOW -> HIGH ?
and back HIGH -> LOW ?
do you have a type id of the PIR ?
link to datasheet ?

or this one

int pirPin = 2; 
int counter = 0;
int laststate = HIGH;

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

void loop()
{
  int state = digitalRead(pirPin);
  if (laststate == LOW && state == HIGH) // only count on a LOW-> HIGH transition
  {
     count++;
     Serial.println(count);
  }
  laststate = state;  // remember last state
}

==> unless you have noise on your line which changes state continuously...

i tried your code
and yes, it continuesly changes state when the beam is interrupted.
the uninterrupted state is HIGH, when the beam is interrupted it bounces from HIGH to LOW, that's obviously why it keeps on counting.

the sensor is a velleman pem7d, it is a retroreflective IR sensor.
The URL doesn't seem to be directed to the product details, but to the velleman main website, so i'll quote the stats here:

nominal detection range: 7m
light source: IR LED
working temperature: -20°C to +50°C
power supply: DC 9-15V regulated (adapter included)
total current consumption: < 130mA
standby current: 25mA
IP rating: IP44
output: NPN output

I have found some code examples to get around the debounce, i'll try some of those.

OK, found a debounce code and it seems to work fine: counting each time the beam is interrupted.
probably need to tingle a bit with the delay times, but it seems to work sound.

thanks

//Debounce
//31mar10

//For http://sheepdogguides.com/arduino/
//               aht0bounce1.htm

//Note that processing of switch is "blocking"... nothing useful will
//  be done until switch is released... but there can be an action
//  which happens just after switch pressed.

const int Inp0=13;//connect a momentary switch
   //connected to GND to this pin
const int Out0=12;//connect an LED and resistor
   //connected to GND to this pin.
   //LED is just for a "switch state" indicator
int counter;

void setup()
{
  Serial.begin(9600);
pinMode(Inp0,INPUT);
digitalWrite(Inp0,HIGH);//Yes... WRITE to the input pin...#
  //This causes the Arduino to "attach" an internal pull up
  //resistor to the input pin.
pinMode(Out0,OUTPUT);
digitalWrite(Out0,LOW);//Turn LED off to start with.
};

void loop()
{
if (digitalRead(Inp0)==LOW) {DealWithSwitchPress();};
};

void DealWithSwitchPress()
{
digitalWrite(Out0,HIGH);
delay(100);//Wait while closure-of-switch bounces pass
//
//Put here: Stuff to happen when switch closed
counter++;
Serial.println(counter);
//
while (digitalRead(Inp0)==LOW){;};//do nothing while waiting
digitalWrite(Out0,LOW);
delay(100);//Wait while opening-of-switch bounces pass
//
//Put here: Stuff to happen when switch finishes opening
//
}

are the multiple counts due to reflective differences? possibly due to variations in clothing texture or
folding? requiring the debounce and is the input a schmidt-trigger type?

Doc

as i said, i found a solution to the bouncing.
everthing working fine.

now i want to expand, i added a timer, so it returns the amount of pulses in the last 10 seconds
the code looks like this:

    #include <SimpleTimer.h>

    /*
     * SimpleTimerAlarmExample.pde
     *
     * Based on usage example for Time + TimeAlarm libraries
     *
     * A timer is called every 15 seconds
     * Another timer is called once only after 10 seconds
     * A third timer is called 10 times.
     *
     */
     

     
    // There must be one global SimpleTimer object.
    // More SimpleTimer objects can be created and run,
    // although there is little point in doing so.
    SimpleTimer timer;
    int counter;
    const int Inp0=2;
    // function to be called repeatedly
    void RepeatTask() {
      
      Serial.println(counter);
     Serial.println(); 
 counter =0;     
    }
     
   
     
    // print current arduino "uptime" on the serial port
    void DigitalClockDisplay() {
      int h,m,s;
      s = millis() / 1000;
      m = s / 60;
      h = s / 3600;
      s = s - m * 60;
      m = m - h * 60;
      Serial.print(h);
      printDigits(m);
      printDigits(s);
      Serial.println();
    }
     
    //
    // utility function for digital clock display:
    // prints preceding colon and leading 0
    //
    void printDigits(int digits) {
      Serial.print(":");
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }
     
    void setup() {
      Serial.begin(9600);
      pinMode(Inp0,INPUT);
      digitalWrite(Inp0,HIGH);
    
      // timed actions setup
      timer.setInterval(10000, DigitalClockDisplay);
      timer.setInterval(10000, RepeatTask);
    
    }
     
    void loop() {
      // this is where the "polling" occurs
      timer.run();
      if (digitalRead(Inp0)==LOW) {DealWithSwitchPress();}
    }

void DealWithSwitchPress()
{
timer.run();
delay(100);//Wait while closure-of-switch bounces pass
//
//Put here: Stuff to happen when switch closed
counter++;

//
while (digitalRead(Inp0)==LOW){
timer.run();};//do nothing while waiting

delay(100);//Wait while opening-of-switch bounces pass
//
//Put here: Stuff to happen when switch finishes opening
//
}

that works fine, but then i want to add a second sensor, i just expanded the code to this:

    #include <SimpleTimer.h>

    /*
     * SimpleTimerAlarmExample.pde
     *
     * Based on usage example for Time + TimeAlarm libraries
     *
     * A timer is called every 15 seconds
     * Another timer is called once only after 10 seconds
     * A third timer is called 10 times.
     *
     */
     

     
    // There must be one global SimpleTimer object.
    // More SimpleTimer objects can be created and run,
    // although there is little point in doing so.
    SimpleTimer timer;
    int counter1;
    int counter2;
    const int Inp1=2; //counter input
    const int Inp2=3;
    // function to be called repeatedly
    void RepeatTask() {
      Serial.print("counter 1: ");
      Serial.println(counter1);
      Serial.print("counter 2: ");
      Serial.println(counter2);
       Serial.println();
       counter1 = 0;
       counter2 = 0;     
    }
     
    
     
    // print current arduino "uptime" on the serial port
    void DigitalClockDisplay() {
      int h,m,s;
      s = millis() / 1000;
      m = s / 60;
      h = s / 3600;
      s = s - m * 60;
      m = m - h * 60;
      Serial.print(h);
      printDigits(m);
      printDigits(s);
      Serial.println();
    }
     
    //
    // utility function for digital clock display:
    // prints preceding colon and leading 0
    //
    void printDigits(int digits) {
      Serial.print(":");
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }
     
    void setup() {
      Serial.begin(9600);
      pinMode(Inp1,INPUT);
      digitalWrite(Inp1,HIGH);
      pinMode(Inp2,INPUT);
      digitalWrite(Inp2,HIGH);
     
      // timed actions setup
      timer.setInterval(10000, DigitalClockDisplay);
      timer.setInterval(10000, RepeatTask);
     
      
      
    }
     
    void loop() {
      // this is where the "polling" occurs
      timer.run();
      if (digitalRead(Inp1)==LOW) {DealWithSwitchPress1();}
      if (digitalRead(Inp2)==LOW) {DealWithSwitchPress2();}
    }

void DealWithSwitchPress1()
{
timer.run();
delay(100);//Wait while closure-of-switch bounces pass
//
//Put here: Stuff to happen when switch closed
counter1++;

//
while (digitalRead(Inp1)==LOW){
timer.run();};//do nothing while waiting

delay(100);//Wait while opening-of-switch bounces pass
//
//Put here: Stuff to happen when switch finishes opening
//
}


void DealWithSwitchPress2()
{
timer.run();
delay(100);//Wait while closure-of-switch bounces pass
//
//Put here: Stuff to happen when switch closed
counter2++;

//
while (digitalRead(Inp2)==LOW){
timer.run();};//do nothing while waiting

delay(100);//Wait while opening-of-switch bounces pass
//
//Put here: Stuff to happen when switch finishes opening
//
}

And then it counts irregularly, either the first or the second sensor.
I think it has to do with the delay in the debouncing: the moment it is in de debouncing loop of the first sensor, it doesn't get input of the second one.
I am right? and what can i do about it?

BTW: same sensor, same range.

one more time, hopefully there is somebody who can help me.

think it has to do with the delay in the debouncing: the moment it is in de debouncing loop of the first sensor, it doesn't get input of the second one.
I am right?

I was not right: it is of course the "while" function
once one sensor is LOW, the code tells it to wait and do nothing, so it also doesn't detect if the second sensor goes low.

this is a problem since i want both sensors to work on different spots at the same time

can anybody help me?

pls post the circuit diagram for this project

@Priyankavenkat - this thread is almost three years old. I think that they may well have found their solution by now.

dannable:
@Priyankavenkat - this thread is almost three years old. I think that they may well have found their solution by now.

Hmmmmm, my take on Priyankavenkat's awakening of this old thread is that s/he is looking for the solution, for re-use.

I may be wrong, that does happen 8)

That crossed my mind too, but I doubt that the OP is still active on the forum regardless.

Hey This code below works perfectly for me.

int in_pin=7;
int state;
LastStatetate=HIGH;
c=0;

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

void loop()
{
state = digitalRead(in_pin);
if (state==HIGH && LastState==HIGH)
{
LastStatetate=LOW;
stateerial.println( ++c);
}
else if (state==LOW)
LastStatetate=HIGH;
}

Hello. You could use an IF statement to detect when it has gone from low-High and then High to low and count one! Too simple.

@willemB -

just change your line 16 to read the following.

counter=counter+state;

and delete line which says the following.

laststate = state;

I