Debouncing of an Interrupting Device to prevent Multiple Triggering - how?

Then, I can simply do the following: (There is no need of # directive.)

pinMode(2, INPUT_PULLUP);

But, why have I been prompted to do like this: #define INT0 2? It is due to the presence of the symbolic name INT0 as an interrupt source in the data sheets (Fig-1).

int0
Figure-1:

That is known as, "doubling down".

1 Like
void ISRINT0()
{
  const int DEBOUNCE_INTERVAL = 20;
  static unsigned long lastActivation = millis();
  if (millis() - lastActivation >= DEBOUNCE_INTERVAL)
  {
   flag = true;
   lastActivation = millis();
  }
}
1 Like

...of one particular processor out of possibly hundreds that run this platform...

Imagine the following:

#define INTSRC 3
. . .
  pinMode(INTSRC, INPUT_PULLUP);
. . .
  attachInterrupt(digitalPinToInterrupt(2), ISR, LOW); 

Do you teach this approach to your students?

I will try your codes tomorrow Inshallah! Now, in my country it is 2:46 by the morning; myself being an aged man should go to bed. Thank you for the help and participation.

I teach those things to the students which they like not the stuff that I like.

One can certainly trigger on the leading edge of the change if one ignores any bouncing that occurs afterwards. So there is no need to wait for the contacts to settle. IMHO the best approach to handling pushbuttons is to have a timer interrupt and poll the pushbuttons within that roughly every 10ms. For most AVR based Arduinos, the existing library has taken the timer 0 overflow interrupt for timing (like implementing micros() and millis()) uses, but a compare interrupt can be used to make an additional "systick" interrupt (note that it can be interfered with by PWM). So for instance:

  // Configure timer/counter interrupt
  OCR0A = 128;
  TIMSK0 |= (1 << OCIE0A); // Enable the interrupt

in the setup function and then add the ISR:

ISR(TIMER0_COMPA_vect) { // Interrupt occurs every 1.024ms
  static byte count;  // Only execute every 10.24ms
  if (count > 0) {
    count--;
  } else {
    count = 10;
/* DO THE POLLING HERE */
  }
}

Then the polling for an active low pushbutton on, say, digital pin 2 would be:

static bool last_button2 = HIGH;
bool button2 = digitalRead(2);
if (button2 == LOW && last_button2 == HIGH) {
    /* TAKE ACTION -- BUTTON JUST PRESSED */
}
last_button2 = button2;
1 Like

Now that we finally see your code, I'm wondering what you hope to achieve by waggling the built-in pullup resistor on pin 4 on and off.

Edit: The whole post-edit of the original post gets a little tedious.

[quote="GolamMostafa, post:1, topic:899538"]

void ISRINT0()
{
  static unsigned long debounceTimer = 0;
  if (millis() - debounceTimer >= 10)
  {
    debounceTimer = millis();
    flag = true;
  }
}
1 Like

@anon57585045 and similarly @johnwasser, nice ISR implementation.

And I have used periodic regular polling after @almytom's technique.

It is easier for me to follow code that doesn't. Get interrupted. So if I can, I set aside interrupts.

I do something like (snippet, sry) at the top of the loop(), where with care it gets way enough attention.


# define BOUNCET	25	// milliseconds of ignorance
static unsigned char state = 1;		// input starts high

	if (millis() - bounceTimer > BOUNCET) {
		unsigned char button = digitalRead(INPIN);

		if (state != button) {
			bounceTimer = millis();
			state = button;
			if (state) actUp = 1;   // flag button became unpressed
			else actDown = 1;      // or pressed
		}
	}

which should be written better so every button wouldn't need all that code; I am either too lazy or unskilled to bother trying. Actually prolly both. :expressionless:

Same idea. THX.

a7

I agree. I think the reason for using interrupts in this case, is as an educational demonstration.

1 Like

Dear Posters,

I am proud and greatly honored to receive very high quality reactions/suggestions on my post from almost all the veteran members of the Forum. I will go through each of the posts with humble care and academic/practical enthusiams. I will let you know my findings and will ask for clarification if needed. There are so many good ideas in your posts being presented in the form of codes/texts, which I would never know should I not make the post because of sighness or lack of courage!

The issue that I have wished to understand is this:
The ISR (3 times blinking of LED1 at 500 ms interval) is being executed in the loop() function. As the blinking of LED1 is in progress using a for() loop, the MCU is again interrupted due to bouncing of the interrupting device (the K1). As a result, the MCU jumps to the ISR, sets the flag (which is already set = true) and comes back to within for() loop of the loop() function. Becasue, the index value of the for() has not changed, the interrupt process should be ending after 3 blinks; instead, there are more than 3 blinks -- 4 or 5 or even more. I have wanted to understanad the true cause of this phenomenon and then implement appropriate remedy to this undesired behavior of the interrupt process without changing the hardware setup.

Thank you again for your sportive participation.

GM

Because flag is set to false in the loop function after the flashing is completed, something is setting it to true after those 3 seconds in order for it to continue flashing. I don't know what type of switch you are using, but it is extremely unlikely that the contact would still be bouncing after 3 seconds, which would point to some flaw in the switch hardware.

But there is problem with your code. The attachInterrupt function should specify FALLING and not LOW. LOW will cause repeating interrupts and should only be used if the condition causing the low level is removed in the interrupt routine.

That point is @GolamMostafa ignoring for a long time now.
Level interrupts are only viable if the source can be controlled by the ISR,
but @GolamMostafa does not want to install a high voltage user remover.

These important clues have come only now and I remember my experinece with 8259 chip (Interrupt Priority Controller) where we used to apply the above-mentioned tricks to clear the LOW-level sustaining trigger signal to avoid multiple interrupts to 8085/8086.

Honestly speaking, I had not been ignoring your idea; rather, I was trying to understand, actually, what was going on.:slight_smile:

This is (Fig-1) how I am going to implement your above idea in order to demonstarte that the allowable LOW level trigger mode (Fig-2) could still be used to generate non-multiple interrupts for the MCU.

7474
Figure-1:


Figure-2:

No. I told you the same a couple of days ago, in the original thread of this "LOW is great" thread.

Reply #14

I remember and admit; but, I had difficulties to relate those with the issue of my Post-1 of the current thread. It could be, myself being a non-native, that I did not perceive the intelligence being conveyed.