Pages: [1]   Go Down
Author Topic: debouncing an interrupt trigger  (Read 9265 times)
0 Members and 1 Guest are viewing this topic.
Brixton, London, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have a button, linked to pin 2 of my arduino, to execute my interrupt service routine. My ISR increments a variable, which lets the rest of my function know what its doing.

My problem is that my buttons are bouncing horribly (damnably cheap buttons were salvaged from old 80's VCR!) Is there any way to debounce this switch in software, without using the delay() command? I tried using the Debounce library with no success, I presume it operates using delay() as well ...

Thank you smiley
« Last Edit: October 09, 2008, 04:15:54 am by akgraphics » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 207
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could use an external RC combination to remove the de-bounce before it gets to the interrupt pin.

What does the rest of your code look like?  I ask because if it were me I'd use the millis() function to produce some code that operated every milli second and use a simple statemachine to handle the reading and de-bouncing of the switch.

Regards,

Mike
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

BigMike's idea is a good one.  Perhaps some variant like this would work?

Code:
void my_interrupt_handler()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    ... do your thing
  }
  last_interrupt_time = interrupt_time;
}

Mikal
« Last Edit: October 09, 2008, 10:46:22 am by mikalhart » Logged

Brixton, London, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Using millis worked perfectly, thanks guys!

The rest of the program controls the PWM output of the arduino on pins 9, 10 and 11, to an RGB LED.

Cheers!  smiley-grin
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 207
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm glad its all working.

However, I was actually thinking of doing that in the main loop, but as it is working, why not leave it there.

There is one problem - what happens when the value from millis() rolls over. I forget the numbers, but in older code the millis() function rolls over after about 9 hours. Currently the rollover occurs at about 50 days.

I think your button may stop working after the rollover. If your application won't be on for 50 days at a time this isn't a problem. If it will be then you may have a problem.

Regards,

Mike
Logged

Brixton, London, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think the battery for this project will last about 5 hours maximum given the number of LEDs it's powering.

BUT this millis() function returns the number of milliseconds elapsed from the beginning of the current function. If my ISR closes and re-opens, then won't the millis() function be reset, i.e. counting from the beginning when this particular instance of the ISR was called?
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Millis counts from the time the sketch starts running (its set to zero just before setup is called).
Logged

Brixton, London, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ahh, thanks for clearing that up smiley

So when millis() overflows, it resets back to zero, so that when the state machine checks against its previous state, a massive error value comes up.

It would be nice if a function could reset the millis() function back to zro (or for any other value, for that matter) so we could say:

val = millis();
if( val > 49 days) {
resetMillis();
}

Is this blue sky thinking, or could a function like this be implemented, feasibly?

The way my code works is that I could say:

val = millis();
if( val > 49 days) {
digitalWrite(resetPin, LOW);
delay(someArbitraryValue);
digitalWrite(resetPin,HIGH);
}

to reset the board, and then the millis() counter would be refreshed. For my particular product/toy, it doesn't matter so much if after 50 days of on-time, the product resets to its initial state.

Would that work around the problem? ...hypothetically? smiley
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A couple of salient points, AK:

Quote
So when millis() overflows, it resets back to zero, so that when the state machine checks against its previous state, a massive error value comes up.

Not necessarily.  If you use the subtraction operator - to compare the "new" time with the "previous" time, as I did in reply #2, the overflow is perfectly harmless.  This is because of the nature of unsigned arithmetic in C.  Let's say the "previous" value of millis() you captured was 0xFFFFFFFF.  10ms later you check millis() and it's value has "rolled over" to 9.  Well, good news!  In C unsigned arithmetic 9 - 0xFFFFFFFF is 10, exactly what you were expecting!

Secondly, there is already a tidy way to write the resetMillis() function you propose.  Unfortunately, it relies on undocumented system internals, so this (for now) only works in Arduino 0012:

Code:
void resetMillis()
{
  extern volatile unsigned long timer0_millis;
  timer0_millis = 0;
}

Mikal
« Last Edit: October 10, 2008, 10:36:29 am by mikalhart » Logged

Brixton, London, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 26
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow I love that! It's nice how the system works out like that. Cheers smiley
Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 4
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Me too! smiley

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 48
http://arduinors.net
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Guy, I suggest a timer interrupt library: http://www.arduino.cc/playground/Main/MsTimer2
Logged


Twin Cites, MN
Offline Offline
Jr. Member
**
Karma: 0
Posts: 50
100 Octane is more fun than 87!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was having very much the same problem with my button bouncing and producing very strange results as the interrrupt was being called over and over on the button bounces.  I tries Big Mike's idea with the code idea from mikalhart and it works great!  Thanks alot guys I'm glad I found this thread!!!
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Rafael,

  What do you propose with the timer interrupt library?

Fred
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello! Let's go back to 2008...

BigMike's idea is a good one, but not perfect...

Code:
void my_interrupt_handler()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    ... do your thing
  }
  last_interrupt_time = interrupt_time;
}

Let's imagine that an interrupt occurs every 150ms constantly for 15 seconds. In such situation the interrupt routine wouldn't do anything, am I right? This is because the line which updates the "last interrupt time" variable doesn't depend on the result of "if". If we put the "last_interrupt_time = interrupt_time;" under the "if", so that it updates the "last interrupt time" only when the interrupt is succesfull, the hypothetical button will be debounced for 200 ms - button's second state change after 300 ms will be succesfull.

Sorry for poor English.
Logged

Pages: [1]   Go Up
Jump to: