Hi everybody!

So recently i was working on a Project where i wanted to meassure the RPM of one of the Wheels on my Car, and from that calculate the Speed, keep track of the Driven distance etc. with an Arduino.
I wanted to use a Magnet and a Reed Switch to meassure the RPM, for that i needed to debouce the Signal from the Reed Switch, since i couldn't find any way to debouce a signal in interrupt functions that didn't require additional hardware for debouncing the signal on the Internet, here is how i debounced the Signal comming from the Reed Switch...

//Software debouncing in Interrupt, by Delphiño K.M.

long debouncing_time = 15; //Debouncing Time in Milliseconds
volatile unsigned long last_micros;

void setup() {
  attachInterrupt(0, debounceInterrupt, RISING);

void loop() {

void debounceInterrupt() {
  if((long)(micros() - last_micros) >= debouncing_time * 1000) {
    last_micros = micros();

void Interrupt() {
  //Do Something

You could also "Do Something" in the main function, instead of calling a second function that then does something, i just liked it better this way...

Note: I've only tried this on an Arduino Mega (ATmega1280), with Arduino 0022.
Also, this isn't a perfect solution, the interrupt function is stil called multiple times, the follwing calls, in the next 15ms are just ignored, but hey, it does the job, so screw it!

Well, thats about it, i hope this helps someone...

P.S. This is my first Instructable, so if you don't have anything nice to say, don't say anything at all, allthough corrections, improvements, etc. are of course allways welcome...
<p>I tried this code in combination with hardware debouncing like described in this article: http://www.ganssle.com/debouncing-pt2.htm When I keep the button pressed the interrupt is keep getting called. Why is this, when it is triggered on RISING edge? </p>
<p>Currently I switched to using an SR latch to toggle a state ON or OFF, but it requires 2 buttons. But I have not yet seen it fail and trigger multiple interrupts. And the interrupt routine now only requires 1 line: &quot;state = !state&quot; </p>
<p>On second thought, not happy with SR switch as the initial state of Q is unknown and can be either 1 or 0. Also I used 2 buttons and 2 interrupts. </p><p>I am now using a 555 in monostable mode (.5 sec output pulse width) which uses 1 button and is consistent when triggering a switch on RISING edge. I have not yet been able to trigger the interrupt multiple times.</p>
<p>Hello! I'm fighting with a 220V desktop light that introduce a big bounce in the net. My arduino is connected to the pc with the usb cable. The PC and the light are on the same source. I find a solution with a bouncing incremental variable that is confronted with a bounced tolerance. My project is different but this solution should be useful for projects that required long intervaled interrupt.</p><p>//#include &lt;Button.h&gt;<br>#include &lt;MaxMatrix.h&gt;<br>#include &lt;avr/pgmspace.h&gt;<br><br><br>const byte A[] = {<br> 4, 8, B1111110, B0010001, B0010001, B1111110 //A<br>};<br><br>const byte empty[] = {<br> 8, 8, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000 // all leds off<br>};<br><br>const byte full[] = {<br> 8, 8, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111, B11111111 // all leds on<br>};<br><br>const byte face[] = {<br> 8, 8, B00000000, B00000000, B00000000, B00011000, B00011000, B00000000, B00000000, B00000000, // ONE<br> 8, 8, B00000011, B00000011, B00000000, B00000000, B00000000, B00000000, B11000000, B11000000, // TWO <br> 8, 8, B11000000, B11000000, B00000000, B00011000, B00011000, B00000000, B00000011, B00000011, // THREE<br> 8, 8, B11000011, B11000011, B00000000, B00000000, B00000000, B00000000, B11000011, B11000011, // FOUR<br> 8, 8, B11000011, B11000011, B00000000, B00011000, B00011000, B00000000, B11000011, B11000011, // FIVE<br> 8, 8, B11011011, B11011011, B00000000, B11011011, B11011011, B00000000, B11011011, B11011011, // SIX<br><br> <br>};<br><br><br><br><br><br>int din_pin = 0; // atmega = PD0(RXD) = 0 | arduino mapping = pin 0<br>int load_pin = 1; // atmega = PD1(TXD) = 1 | arduino mapping = pin 1<br>int clock_pin = 2; // atmega = PD2(int0) = 2 | arduino mapping = pin 2<br><br>int interrupt_pin_real = 1; //atmega = PD3(int1) = 1 | arduino mapping = pin 3 (write the real one)<br>int interrupt_pin_mapped = 3;<br><br>int matrix_number = 4;<br><br>volatile int bounce_tol = 300; <br>volatile int bounce = 0;<br><br>int i = 0;<br><br>volatile int state = LOW;<br><br><br><br><br>MaxMatrix m(din_pin, load_pin, clock_pin, matrix_number);<br><br><br><br><br><br>void setup()<br>{<br> m.init();<br> m.setIntensity(15); // dot matix intensity 0-15<br> <br> <br> pinMode(din_pin,OUTPUT);<br> pinMode(load_pin,OUTPUT);<br> pinMode(clock_pin,OUTPUT);<br> <br> <br> <br> <br> attachInterrupt(interrupt_pin_real, state_changer, LOW);<br> <br> <br> <br>}<br><br>void state_changer(){<br> if(bounce &gt;= bounce_tol){<br> state = !state;<br> bounce = 0; <br> }<br> bounce++; <br>}<br><br>void magic_box(int sleep){<br> <br> int num_1 = random(6);<br> int num_2 = random(6);<br> int num_3 = random(6);<br> int num_4 = random(6);<br><br> <br> m.writeSprite(0, 0, &amp;face[num_1*10]);<br> m.writeSprite(8, 0, &amp;face[num_2*10]);<br> m.writeSprite(16, 0, &amp;face[num_3*10]);<br> m.writeSprite(24, 0, &amp;face[num_4*10]);<br> <br> delay(sleep);<br>}<br><br><br><br>void rolling(){<br><br> for(i=0;i&lt;=10;i++){<br> magic_box(50);<br> <br> }<br> <br> for(i=0;i&lt;=6;i++){<br> magic_box(200);<br> } <br> <br> for(i=0;i&lt;=2;i++){<br> magic_box(500);<br> <br> }<br> <br>}<br><br><br>void clear_matrix(){<br> m.writeSprite(0, 0, empty);<br> m.writeSprite(8, 0, empty);<br> m.writeSprite(16, 0, empty);<br> m.writeSprite(24, 0, empty); <br>}<br><br><br><br><br>void loop() {<br> <br> <br> <br> <br> //digitalWrite(interrupt_pin_mapped, HIGH); // no pull up needed<br> <br> <br> if(state == HIGH){<br> <br> if(bounce &lt; bounce_tol){ <br> rolling();<br> <br> state = LOW;<br> bounce = 0;<br> }<br> }<br><br>}</p>
<p>Thanks, this was a nice temporary alternative to hardware debouncing. <br>Probably not perfect, but it works well for simple push button stuff.</p>
<p>This is very simple and works quite well. Thank you for posting.<br><br>If anyone is looking to use this code with a push button, I would recommend setting the debouncing_time to &quot;150&quot;, potentially even slightly higher. Lower than this could still give you bouncing issues with certain buttons; I find it to be a happy medium between relatively fast button presses and errors.<br><br>That being said, 150 definitely wouldn't be suitable in a video game controller.</p>
<p>You are right, I've chosen 200ms to turn a blinking bike light on and off. Less than that would be unstable.</p><p>One thing to consider is that button bouncing should not happen in the first place, if there was an &quot;ideal&quot; button. So I guess for video games, and PC keyboards I guess, the electrical contact of the button must be better (or at least they perform hardware debouncing, while here we are doing software debouncing).</p><p>All in all, I found this instructable very instructive! And I don't think it is a big problem, as the OP says, in the function being called but ignored, I suppose every debouncing tutorial I've seen so far use the same technique, with some variations. But this one is very straightforward, and works exactely as expected!</p>
<p>There are two bugs here.</p><p>1. If the interrupt occurs just before micros() overflows, Interrupt() is not called, but should be. (last_micros is greater than micros(), giving a negative value that will not be larger than the debounce time.)</p><p>2. Calling micros() twice. It should be called once and the value stored in a local variable, before the expression is evaluated.</p><p>Also poor strategy to call another function from an ISR (which should get finish work fast) and hides the fact from another programmer that adding work in Interrupt() might be bad...</p>
<p>Oops, the first one is not a bug, because of the way C handles unsigned long arithmetic...</p>
cool, check out how I set up my bike speedometer, I used interrupts, but I found that I didn't need to debounce, maybe because the bike moves much slower and I was only checking the reed switch at 1ms intervals: <br />http://www.instructables.com/id/Arduino-Bike-Speedometer/
Sorry for the super late reply... :) <br>Hmm, maybe you had a better reed switch then i, mine really sucked! ;) <br>I'm a little confused about you using interrupts but only checking the reed switch at 1ms intervals, i mean if you were using interrupts you wouldn't be checking the reed switch in certain intervals, the whole point of an interrupt is for the Arduino to run a small part of code everytime something happens. Or were you using timer interrupts to check if the reed switch is closed at 1ms intervals? I guess that would explain why you didn't need to debounce. Your reed switch probably just bounced less than 1ms... :) <br> <br>Anyhow, thanks for your comment! ;)
yes, timer interrupts, and yes, you're probably right about the debouncing.

About This Instructable


12 favorites


More by delphino-999: Arduino: Software debouncing in interrupt function...
Add instructable to: