IR Sensor counting more than once for a movement

Hi Team,

I am facing an issue with IR Sensor, I want to count the movement of people with IR and see the presence in a range with PIR Sensor. For every min the counts are posted to sever.

IR = Count on interrupt

However the issue is IR Sensor counting more than once for a movement 22 times / sometimes 80-100 counts.Please help what is that I am doing wrong.

int irSensorDigitalPin = D7;               // choose the input pin (for IR sensor)
   int inputPin = D8;               // choose the input pin (for PIR sensor)
 volatile int proximity = 0;
 volatile int irCounter = 0 ; 


void setup()
{
  Serial.begin(115200);
  delay(5000);
  Serial.println();
 pinMode(irSensorDigitalPin, INPUT_PULLUP); // declare ir as input
 pinMode(inputPin, INPUT_PULLUP); // declare pir as input
 attachInterrupt(digitalPinToInterrupt(irSensorDigitalPin), setPassThruCounter, RISING);
 attachInterrupt(digitalPinToInterrupt(inputPin), setNearByCounter, RISING);
}


ICACHE_RAM_ATTR void setPassThruCounter() {
  irCounter ++ ;

}

ICACHE_RAM_ATTR void setNearByCounter() {
proximity ++ ;

}

int getproximity() {
int prx = proximity;
proximity = 0;
return prx;
}

int getirCounter() {
//int irc = irCounter;
int irc=irCounter; 
irCounter = 0;
return irc;
}

void loop()
{
    if (millis() - lastMillis > 60000)
    {
      lastMillis = millis();
      noInterrupts();
      sendData();
      interrupts();
    }
  }

void sendData(void)
{
  DynamicJsonDocument jsonBuffer(JSON_OBJECT_SIZE(3) + 100);
  JsonObject root = jsonBuffer.to<JsonObject>();
  JsonObject state = root.createNestedObject("state");
  JsonObject state_reported = state.createNestedObject("reported");
  state_reported["loc"] = "DeviceID1";
 state_reported["prx"] =getproximity();
 state_reported["irc"] =getirCounter();
  Serial.printf("Sending  [%s]: ", MQTT_PUB_TOPIC);
  serializeJson(root, Serial);
  Serial.println();
  char shadow[measureJson(root) + 1];
  serializeJson(root, shadow, sizeof(shadow));
  if (!client.publish(MQTT_PUB_TOPIC, shadow, false))
    pubSubErr(client.state());
}

I am not sure why you are using interrupts. Unless they are really required then they are best avoided.
Start by writing some simple code that uses the sensor so that you fully understand how it works.
Put plenty of print statements in your code so that you can "see" what the code is doing when it executes.

i think using an ISR to count ir-sensor events is a good idea, especially since you have to do other things.

but you only need to disable interrupts (i.e. noInterrupt()/interrupt()) when you read the variable being incremented inside the ISRs (maube just one routine instead of getproximity() and getircounter()). you want interrupts to run while executing sendData()

Interrupts are useful but they are much harder to debug than simple polling. The OP at least needs to be able to use the sensor without interrupts before attempting to use them.

gcjr:
i think using an ISR to count ir-sensor events is a good idea, especially since you have to do other things.

but you only need to disable interrupts (i.e. noInterrupt()/interrupt()) when you read the variable being incremented inside the ISRs (maube just one routine instead of getproximity() and getircounter()). you want interrupts to run while executing sendData()

Hi Greg,

Thanks for the inputs, you are right. As per suggestion I moved interrupts to get method. However, I learned that I made 2 mistakes so I updated below methods 1. Input declared as Input_PullUp which capture small voltage change as well it seems so there were multiple increments. 2. ISR mode set to CHANGE and checking the HIGH/LOW in Set Methods to increment or not.

Thanks all for your commitment to the thread, it inspired me a lot !!

int irSensorDigitalPin = D7;               // choose the input pin (for IR sensor)
volatile int irCounter = 0 ;
volatile int irState = LOW;             // we start, assuming no motion detected
int inputPin = D8;               // choose the input pin (for PIR sensor)
volatile int proximity = 0;
volatile int pirState = LOW;  // we start, assuming no motion detected

void setup()
{
  Serial.begin(115200);
  delay(5000);
  Serial.println();
  Serial.println();

  pinMode(irSensorDigitalPin, INPUT); // declare ir as input
  pinMode(inputPin, INPUT); // declare pir as input
  attachInterrupt(digitalPinToInterrupt(irSensorDigitalPin), setPassThruCounter, CHANGE);
  attachInterrupt(digitalPinToInterrupt(inputPin), setNearByCounter, CHANGE);
}

ICACHE_RAM_ATTR void setPassThruCounter() {
  int val0 = 0;
  val0 = digitalRead(irSensorDigitalPin);  // read input value
  if (val0 == HIGH) {            // check if the input is HIGH
    //digitalWrite(ledPin, HIGH);  // turn LED ON
    if (irState == LOW) {
      // we have just turned on
      // Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      irState = HIGH;
      irCounter ++ ;
    }
  } else {
    //digitalWrite(ledPin, LOW); // turn LED OFF
    if (irState == HIGH) {
      // we have just turned of
      // Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      irState = LOW;
    }
  }
}

ICACHE_RAM_ATTR void setNearByCounter() {
  int val = 0;
  val = digitalRead(inputPin);  // read input value
  if (val == HIGH) {            // check if the input is HIGH
    //digitalWrite(ledPin, HIGH);  // turn LED ON
    if (pirState == LOW) {
      // we have just turned on
      // Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
      proximity++;
    }
  } else {
    //digitalWrite(ledPin, LOW); // turn LED OFF
    if (pirState == HIGH) {
      // we have just turned of
      // Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }

}

int getproximity() {
  noInterrupts();
  int prx = proximity;
  proximity = 0;
  interrupts();
  return prx;
}

int getirCounter() {
  noInterrupts();
  int irc = irCounter;
  irCounter = 0;
  interrupts();
  return irc;
}

void loop()
{
    if (millis() - lastMillis > 60000)
    {
      lastMillis = millis();
      sendData();
    }
 }

ardly,
i agree interrupts are more difficult to debug, but if you need to do a time consuming task while keeping track of events, then using interrupts seem unavoidable.

skesipeddi,
not sure confguring the interrupt for CHANGE makes sense. i've had problems myself, but hope to add hysterisis by passing the signal thru a 555 timer threshold/trigger so that the pin sees a distinct edge due to a significant voltage change.

gcjr:
ardly,
i agree interrupts are more difficult to debug, but if you need to do a time consuming task while keeping track of events, then using interrupts seem unavoidable.
...

If you have a lot of processing to do and you want to keep tabs on asynchronous events then interrupts are very useful. Look at the OPs loop() function though. It only does something every 60s. This is a bad use of interrupts, they add complexity when polling would be a much better solution.

but you can't poll while your doing that thing every 60s

bottom line is interrupts work. they may be more difficult to debug.

gcjr:
but you can't poll while your doing that thing every 60s

bottom line is interrupts work. they may be more difficult to debug.

Of course interrupts work, but he is trying to count the movement of people. This is a bad use of interrupts, pain with no gain.