EEVblog® Electronics Community Forum
Electronics => Microcontrollers => Topic started by: parasbhanot on February 13, 2016, 04:50:01 am
-
Hello everyone ,
I am trying to implement external interrupt using push button in my project But the only problem is when i press the button the interrupt routine is fired several times . i have tried to disable interrupt in interrupt routine using detachInterrupt function but the problem still exist. i have tested the following code in both arduino uno and arduino leonardo. So i don`t think that something is wrong with my arduino hardware.
:(
void setup() {
pinMode (2,INPUT_PULLUP); // turn on pull-up resistors
attachInterrupt(digitalPinToInterrupt(2), INT0_ISR, FALLING);
Serial.begin(9600);
}
void loop() {
}
void INT0_ISR()
{
Serial.println("interrup fired");
// detachInterrupt(digitalPinToInterrupt(2));
// delay (100);
}
I was watching Jeremy blum`s video on youtube in which he used RC circuit with Schmitt trigger to hardware de-bounce the push button.But i am not sure if it the most efficient way to solve this problem.
Is there any alternative ?
Can I de-bounce this push button in interrupt routine ?
https://www.youtube.com/watch?v=CRJUdf5TTQQ (https://www.youtube.com/watch?v=CRJUdf5TTQQ)
Thanks in advance
-
Have you tried simply using the delay() in the interrupt routine (without the detach statement) , and increasing the value until it stops bouncing? I don't know if this will work and I'm too lazy at the moment to try it myself... :-\
The standard way is to do it in hardware though, as shown in the video or in this instructable (pretty much the same thing):
http://www.instructables.com/id/Arduino-Push-Switch-Debouncing-Interrupts/ (http://www.instructables.com/id/Arduino-Push-Switch-Debouncing-Interrupts/)
-
yes i have tried delay function but it still does not work as expected.
-
It is not recommended to solve it this way. Buttons are pushed by slow humans and handling doesn't require any interrupts. Using an interrupt for push buttons will make your code execution less predictable because you cannot predict how much time is spent in the ISR. When buttons wear out more and more time is spent in the interrupt - starving your program and changing its behavior possibly to a point of failure.
Usually buttons are scanned in the main loop and debounced in software (detect a downstate for 10-20 ms) or in hardware (R-C).
Hope it helps,
Marc
-
:popcorn:
I am aware that buttons are generally processed in main loop but In my main project i am trying to wake up arduino on button press . So i am out of options here.
-
Look at this and take it from there:
http://donalmorrissey.blogspot.com/2010/04/putting-arduino-diecimila-to-sleep.html (http://donalmorrissey.blogspot.com/2010/04/putting-arduino-diecimila-to-sleep.html)
-
:popcorn:
I am aware that buttons are generally processed in main loop but In my main project i am trying to wake up arduino on button press . So i am out of options here.
In that case you only need to enable the external interrupt just before you put the arduino to sleep (clear any pending interrupt before enabling though). In the interrupt handler, disable interrupts and then then start polling the button(s) in your main loop again.
-
:)
donalmorrissey`s blog was very helpful.
Problem solved.
Thank you everyone .
-
"When i press the button the interrupt routine is fired several times . "
Because your interrupt is edge triggered, there is really no solution to your problem within your framework.
Hardware denouncing is an option, or scanning (activated in the isr) is another.
BTW, no point in disabling the interrupt in the isr as it is done automatically.
-
void INT0_ISR()
{
Serial.println("interrup fired");
// detachInterrupt(digitalPinToInterrupt(2));
// delay (100);
}
2 things:
- You'd want to detachInterrupt() first thing when entering the ISR... your serial.println() is a relatively long process that gives enough time for your switch to bounce and retrigger the interrupt before getting to the next statement.
- As specified in the arduino doc, delay() does not do work in an ISR.
-
-
You'd want to detachInterrupt() first thing when entering the ISR
That seems to be the standard operating procedure for the arduino crowd, and is an absolute idiocy.
-
:)
donalmorrissey`s blog was very helpful.
Problem solved.
Thank you everyone .
Captain Kirk: What happened to the horse?
Dr McCoy: It's dead Jim.
-
:popcorn:
This is my final code (without sleep)
int pin2 = 2;
static int flag = 0;
void pin2Interrupt(void)
{
detachInterrupt(0);
flag = 1;
}
void setup()
{
// Serial.println is used just for debugging purposes
Serial.begin(9600);
pinMode(pin2, INPUT_PULLUP);
attachInterrupt(0, pin2Interrupt, LOW);
Serial.println("Initialisation complete.");
}
void loop()
{
if (flag == 1)
{
Serial.println("interrupt fired ");
flag = 0;
delay(200);
attachInterrupt(0, pin2Interrupt, LOW);
}
else {
// main code
}
}
And this is my final code (with sleep)
#include <avr/sleep.h>
#include <avr/power.h>
int pin2 = 2;
void pin2Interrupt(void)
{
detachInterrupt(0);
}
void enterSleep(void)
{
attachInterrupt(0, pin2Interrupt, LOW);
delay(100);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
sleep_disable();
}
void setup()
{
Serial.begin(9600);
pinMode(pin2, INPUT_PULLUP);
Serial.println("Initialisation complete.");
enterSleep();
}
void loop()
{
delay(1000);
Serial.println("interrupt fired ");
enterSleep();
}
-
static volatile int flag = 0; // volatile because var is accessed by both loop and isr.
-
ok, thanks