I wanted to reply to this thread with some minor improvements, but I don't see how. Maybe it's too old? Anyway, here is my code:
#define DEBOUNCE_MICROS 15000UL;
volatile unsigned long next_micros = 0UL;
volatile bool do_stuff = false;
void setup() {
attachInterrupt(0, InterruptHandler, RISING);
}
void loop() {
if (do_stuff) {
// do stuff here
do_stuff = false;
}
}
void InterruptHandler() {
if ((long)(micros() - next_micros) >= 0L) {
do_stuff = true;
next_micros = micros() + DEBOUNCE_MICROS;
}
}
I've seen a lot of bad examples out there on this subject. I'm posting this to improve the ratio of helpful to harmful ones.
Things this code does correctly, compared to a lot of the other stuff I've seen out there:
- No delays are used, so the arduino can still do other things during debouncing.
- delay() is not used inside the interrupt handler (which does not work).
- millis() is not used repeatedly inside the interrupt handler (which does not work).
- The code inside the interrupt handler is very short, as interrupt code should be general.
- This timing mechanism is simple yet immune to roll-over.
Note that if the stuff you need to do in response to the interrupt is very short and simple, you can do it directly in the interrupt instead of setting a flag and then doing it inside the main loop. However, the way I've shown it here is good practice and may save you some headaches down the road.
Ok, hope that helps someone.
Edit: I should mention that there are times when you definitely want to do everything inside the interrupt instead of doing it indirectly like above. An example would be when there is some other process in your code that is blocking loop() from iterating for long periods of time. Here's that version of the code too:
#define DEBOUNCE_MICROS 15000UL;
volatile unsigned long next_micros = 0UL;
void setup() {
attachInterrupt(0, InterruptHandler, RISING);
}
void loop() {
}
void InterruptHandler() {
if ((long)(micros() - next_micros) >= 0L) {
// do stuff here
next_micros = micros() + DEBOUNCE_MICROS;
}
}