Arduino UNO Interrupt Code

Hi

Below is my Interrupt code using Arduino UNO. as written in the code I am triggering an interrupt on PIN 2 falling edge. Whenever pin 2 goes from High to Low ISR is executed making SENSflag 1 which will make PUMPpin HIGH for 1/2 a second. But what I am seeing is the Interrupt is triggering on both Rising edge and Falling edge of sense pin.
Please suggest what is wrong

#include "LowPower.h"
int SENSEpin = 2;
int PUMPpin = 12;
volatile int SENSEflag;

void setup()
{
pinMode(12,OUTPUT);
pinMode(2,INPUT);
digitalWrite (12, LOW);
attachInterrupt(digitalPinToInterrupt(SENSEpin),turnPUMPon,FALLING); //interrupt on falling edge of pin2
}

void loop()
{
if (SENSEflag = 1)
digitalWrite (12,HIGH);
delay(3000);
digitalWrite (12,LOW);
SENSEflag = 0;
LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF);
}

void turnPUMPon()
{
SENSEflag = 1;
}

Thanks
Santosh

if (SENSEflag = 1)Oops

Please remember to use code tags when posting code

double oops possibly (missing {} ?)

At least that.

Baby steps.

This

if (SENSEflag =1)
 digitalWrite (12,HIGH);
 delay(3000);
 digitalWrite (12,LOW);
 SENSEflag = 0;
 LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF);

should probably be like this

if (SENSEflag == 1) { // == in a test and {} to surround the code the test applies to
   digitalWrite (12,HIGH);
   elay(3000);
   digitalWrite (12,LOW);
   SENSEflag = 0;
   LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF); 
}

but I am not familiar with the LowPower library

...R

I corrected the loop...still triggers on both edges

void loop()
{
if (SENSEflag == 1)
{
digitalWrite (12, HIGH);
delay(2000);
digitalWrite (12, LOW);
SENSEflag = 0;
LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF);
}
}

Why no code tags, still?

If you are looking for a falling edge, try a pull up resistor (say 10K) :

pinMode(2,INPUT) ;

pinMode(2,INPUT_PULLUP) ;

Or is there an external one ?

Any bouncing happening on that pin?
How do you know for sure it’s happening at both front versus two consecutive falling fronts ?

@J-M-L I am using an IR senor module whose output(connected to UNO pin2) is high by default(5V) when an obstacle is close enough output goes LOW. So when I hold my hand in front of the sensor, output goes from HIGH to LOW so I am expecting the SNESEflag to set and turn on the PUMPpin for 2 seconds and then turn off the PUMPpin, which is happening as expected But while taking off my hand from the sensor the PUMPpin turns on again for 2 seconds and then turns off. Ideally while taking off my hand from the senior it's a LOW pulse being pulled to HIGH on UNO pin2(rising edge) in this case why is the PUMPpin is turning on?

Can you please provide a link to the proximity sensor you are using. Some of the low cost devices using lm393 comparators can have poor hysteresis control and are noisy.

You might want to try a capacitor between the digital output and ground to smooth the response.

One way to deal with the bounce (if that is the problem) is to disable the interrupt after the first trigger and only re-enable it when you are ready to to deal with the next one. That could be done like this

void turnPUMPon()
{
   SENSEflag = 1;
   EIMSK &= 0b11111110; // disable interrupt 0 (pin 2)
}
void loop()
{
  if (SENSEflag == 1)
  {
    digitalWrite (12, HIGH);
    delay(2000);
    digitalWrite (12, LOW);
    SENSEflag = 0;
    EIFR |= 0b00000001; // clear the interrupt flag for interrupt 0
    EIMSK |=  0b00000001; // enable interrupt 0
    LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF);
  }
}

...R

Or, even simpler:

boolean SENSEflag = false;

void turnPUMPon()
{
    if (!SENSEflag)
       SENSEflag = true;
}


void loop()
{
  if (SENSEflag)
  {
    digitalWrite (12, HIGH);
    delay(2000);
    digitalWrite (12, LOW);
    SENSEflag = false;
    LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF);
  }
}

Not sure what it is but then this is even simpler

 void turnPUMPon()
{
   SENSEflag = true;
}

No need to test if it’s false

——

Best would be to test if there is bouncing for sure before trying to address it I guess.

RayLivingston:
Or, even simpler:

I don't think that is sufficient to discard a debounce. The interrupt flag register will contain the flag for the bounce unless the register is cleared.

Or will the "bounce" flag waste itself by calling the ISR when SENSEflag is true?

...R

Some of these cheap PIR sensors retrigger themselves if there is any electrical activity in your circuit which is not immediately caused by the PIR itself.

The PIR triggers a the pump and a timer. When the timer expires, the pump switches off and I'm guessing that triggers the PIR once again.

In your code, you have to ignore any input from the PIR that happens within a certain period after the pump switches off. Try disabling the interrupt immediately it is triggered then, after the pump switches off, add another delay and re-enable the interrupt just before the sleep operation, in preparation for the next cycle. Try making that delay longer than the minimum retrigger time that is set (or you have set) on the PIR (which is surely longer than 2 seconds).

Further. How have you wired the pump ? Via a mosfet/transistor or directly to an Arduino pin ? Have you used a flyback diode which may also help to suppress any such noise.

I have found HC-SR505 particularly bad for unwanted retriggering. AM312 devices seem quite good.

Robin2:
I don't think that is sufficient to discard a debounce.

agreed my point was just to simplify further the code that was posted but I as I said I was unclear what this was for.

@6v6gt I am using an Infrared senor (link below) I directly connected the output of this sensor to pin2 of UNO

now my code looks like below. I tried all the suggestions mentioned here in the comments but still, the behaviour is the same while taking off my hand(sensor output goes from 0V-5V) then also the pump truns on

#include "LowPower.h"
int SENSEpin = 2;
int PUMPpin = 12;

volatile int SENSEflag;

void setup()
{
pinMode(12, OUTPUT);
pinMode(2, INPUT_PULLUP);
digitalWrite (12, LOW);
attachInterrupt(digitalPinToInterrupt(SENSEpin), turnPUMPon, FALLING);
}

void loop()
{
if (SENSEflag == 1)
{
digitalWrite (12, HIGH);
delay(2000);
digitalWrite (12, LOW);
SENSEflag = 0;
EIFR |= 0b00000001; // clear the interrupt flag for interrupt 0
EIMSK |= 0b00000001; // enable interrupt 0
LowPower.powerDown(SLEEP_FOREVER , ADC_OFF, BOD_OFF);
}
}

void turnPUMPon()
{
SENSEflag = 1;
}

IR sensor link
https://www.ebay.com/itm/5X-IR-Infrared-Obstacle-Avoidance-Sensor-Module-Adjustable-Distance-for-Arduino/192421238897?hash=item2ccd331871:g:1sMAAOSwI~taUyOc

Thanks
Santosh

Remind me - why are you using an interrupt?

Please remember to use code tags when posting code. I think I may have mentioned this before.

OK. It is a proximity sensor. I'm not sure that is very suitable for long term battery operation which, I guess, is the reason for using sleep mode.
But, anyway, try adding a delay after this block, say :

 digitalWrite (12, HIGH);
 delay(2000);
 digitalWrite (12, LOW);
 delay( 3000 ) ; // minimum repeat interval

If you still have a problem try increasing the delay marked minimum repeat interval to allow a longer stabilisation time.
If there is still a problem, disconnect the pump and switch on the on board led instead to see how it behaves.

Since you have named the pins, why not use their names e.g. PUMPpin instead of 12 ?