BLOG > Tutorial 10 for Arduino: Interrupts + Debouncing

This video was featured on Hackaday.com on 3/8/2011
This tutorial was featured on the official Arduino blog on 3/9/2011

Interrupts are an extremely useful, yet often feared element of microprocessors.  Interrupts allow you to run a program, while still being able to react to asynchronous input from the outside world.  On many platforms they can be confusing to implement, but the arduino makes it easy!  In this week’s episode, I’ll show you how to use a hardware-debounced button to activate a hardware interrupt on the arduino.  I’d suggest you go check out episode 2, where I initially introduced button debouncing, if you haven’t already.  I won’t be covering timer interrupts in this episode, since I recently wrote an extensive blog post about using them.  Enjoy the video!

EDIT: You can find a great run-down of debouncing techniques and problems here: http://www.ganssle.com/debouncing.htm (Thanks Jope)

 

You can download the files associated with this episode here:

GNU GPL License Distributed under the GNU General Public (Open-Source) License.
Please Attribute and Share-Alike.

150 comments

  1. I would like a suggestion on execution of an interrupt only on the condition that the value change is retained for like 10 seconds. I would like to know if the hardware and software solutions/

  2. Dear mr Blum,

    Your Schmitt trigger debounce sketch is very helpfull for me.
    My question is: can this sketch be changed in a single state switch. (When the switch is pressed, the pinled is on and when released it is off). And yes, how?

    Greetings,

    Erik

  3. hi i am using intrupts with in intrupts while i am doing it i am experiencing different problems
    1) the code suddenly stops to function
    2) when ever interrupt is called with in an interrupt i cannot predict the behavior

    1. That’s because you can’t do interrupts within interrupts. If you think of it like a hierarchy, interrupts are pretty much at the top of the totem pole. When an interrupt happens, it takes almost top priority. If you put another interrupt within an interrupt, your Arduino gets confused since they both have the same level of priority, and thinks well, which one should I be doing? This interrupt, or that interrupt? And that’s why you have unpredictable behavior. A simple example is you can’t use the delay() within an interrupt. You will get unpredictable results, ranging from the whole Arduino just hanging to weird results like it does one thing but not another. Your interrupts should be as short as possible, because everything else is being put on hold until your interrupt completes. If you’re trying to do an interrupt within an interrupt, then you need to find another way to do whatever it is you’re doing. Chances are, there is a better way to do it.

  4. Hi Jeremy,

    Great tutorials, great work.. no words.. learned a lot thankyou.

    I am working on building a kind of pressure sensor to trigger a flow in java code.
    I cant figure out what is the best way to recive that trigger, I want to send “true” as long as the pressure is above some value (like a button).

    Thanks,
    Guv

  5. Dear Mr. Blum

    Can i make pushbutton for clock input?for example 4026?
    so everytime i press the button it will give the clock falling edge input,without arduino it works because it just a simple seven segment counter, but now the problem is i want to add arduino+xbee so i can wirelessly input the clock with button. I want to make a wireless scoreboard :)
    Great tutorial anyway ,it really helps, thanks you :D

    Regards,

    Anasthasia

    PS : sorry for my bad english, it’s not my native language
    i’m a beginner :)

  6. hey Jeremy.. I am new with the arduino board. Im am designing a parking lot with two floors. with four parking space each. the problem is i have created both floors separately. When I try to put it together my program doesn’t work. I have also used two interrupts for my arduino uno board so that the user can choose the floor they want to park but the spot will be chosen automatically. my problem is im not sure how to write the coding for two separate interrupts in my program. Can u help me?

  7. Hi Jeremy,

    Love the videos use them for refernce all the time if working on something new with the arduino. My question is, can a interrupt pin be defined as a normal button and an interrupt? For example:

    int buttonTwo = 2; // pin 2
    int buttonInt = 0; //pin 2

    void loop()
    {
    noInterrupts();
    // code that would use buttonTwo
    Interrupts();
    // code that would involve buttonInt
    }

    Thanks

  8. Hi Jeremy, please tell me the time constant, if you use a key to shorten a capacitor. Is it allowed?
    Current should be very, very high. So that it is possible to make a damage or to reset the Arduino?

      1. Hi,

        I think he asked about button connected to capacitor.
        When U push the button it will connect capacitor + to the ground.
        What about current? It will be huge.

        1. Yes, theoretically if the capacitor discharges into zero ohms then you get infinite current. Practically, though, there is internal resistance in the cap; and the wires themselves will have some small resistance. If you model the resistance of the cap and the wires as one ohm, then when you close the switch you have a one ohm resistor across a 10 uF cap. Time constant equals 1*10e-6 = 10 us. It takes five time constants to completely discharge the cap, i.e. 50 us.

          When you close the switch you have five volts discharging into 1 ohm = 5A. After one time constant this current drops by 63%, i.e. to 1.8A, and so on. After 5 time constants (50us) the current is zero. Most small circuit wiring can handle this current for this duration. Additionally, and probably more important than the 1 ohm resistance of the circuit, is the inductance. The inductance of the wiring and the capacitor plates will limit any current surge (dI/dt) that can flow in the circuit. Shorting a small capacitor charged to 5V is probably not going to burn out any but the teeniest, tiniest wires.

          1. Or just put a 10 ohm resistor in series with the capacitor. Current goes way down, time constant minimally affected.

            But since we are talking small caps anyway, and low voltages, who cares? It will work just fine for decades.

  9. huh,

    when i add the capacitor this circuit got a delay on it.
    When I press my button it does exactly what it needs to do,
    but fast paces get lost in -what i expect- is the discharging of the capacitor???
    needs like several 100’s of milliseconds…?

  10. Hi Jerry,

    Very Nice and useful tutorial and thank you very much. I need your help in the following:-

    Currently I am using a Rotary switch to select a sine wave source from multiple Sine wave sources.

    I want to move to soft switch(s) instead of the current mechanical switch in other word Micro controller based. Since this is not just a logical voltage output (like transistor output or straightforward) and hence having difficulty to design.

    Requesting your help in this regard?

    Thanks in advance,
    Pradip3

  11. Hi Jeremy, maybe you help me ;)

    There is the code:

    #include
    #include

    void toggle()
    {
    detachInterrupt(0);

    //Message to send:
    const char *msg = “ALERT!”;
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx(); // We wait to finish sending the message
    // delay(1000);We wait to send the message again
    }

    void setup()
    {
    pinMode(2, INPUT);
    vw_set_ptt_inverted(true); // Required by the RF module
    vw_setup(2000); // bps connection speed
    vw_set_tx_pin(3); // Arduino pin to connect the receiver data pin

    }

    void loop()
    {

    attachInterrupt(0,toggle,RISING);
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
    }

    Arduino awaits for HIGH signal on INT0, wakes up and sends the message via rfm12b. After that it should come back to sleep mode.

    The problem is that is stucks at interrupt looop(toggle). I can see it with current measuring: it starts with 0.1uA, after the HIGH comes it awakes up, but never coming back to sleep even if the pin2 is low. Do you know where could be thie problem? I was trying also with HIGH and Change as an interrupt parameters, but without positive results.

    Regards,
    Jakub

    1. Thanks for this – It maybe exactly what I was looking for, saves asking Jeremy another question!

      Now to find a 200uF capacitor!

      thx again
      Jon

  12. Hi Jeremy

    Bit late but I wanted to point out that the addition of a switch across the capacitor does not incur a time constant of RC as you indicate

    It is effectively short circuit and therefor R=0 or as close as to be irrelevant

    It is the recovery back to a logic 1 that is relevant here and this is based on the time constant RC

    your circuit is correct, just the description is a little off, once the cap is discharged (Almost instant) it does not get back to a logic one right away (RC time constant) and therefor de-bounces using the hysteresis of the Schmidt trigger IC. As i Said, circuit is good, just correcting the description

    Good tutorial

    Thanks

    Peter

  13. Interrupts within interrupts are not viable. You CAN have multiple interrupt sources, e.g. a pin interrupt and a timer interrupt. Different interrupt sources have different ‘priority’ and are handled according to that priority. Check out the ATMEL data sheet for the device you are using. If you are using an Arduino Uno check out the ATmega328 data sheet, specifically sections 7.1, 7.5 and 12. Section 12 describes all the interrupts and their priorities. If you plan to use multiple interrupt sources be aware that it can get very complicated. All I can say is, “Good luck!”

    Kevin H.

  14. How should I probe further to develop an idea of my own? Where can I find the relevant material(as in algorithms, hardware designs etc) for the same?

    Thank you for all your guidance!

  15. how would you use the interupt function if you are using two switches. one to control speed of the fan and the other to switch power on and off.

  16. how to get the interupt function to work if you are using two switches. one to control speed of the fan and the other to switch power on and off.
    i need help with this code:

    int switchPin = 2; //interrupt 0
    int motorPin = 9;
    int offPin=3; //interrupt 1
    boolean lastButton = LOW;
    boolean currentButton = LOW;
    boolean lastButton2 = LOW;
    boolean currentButton2 = LOW;
    volatile boolean motorOn = false;

    int motorLevel = 82;

    void setup()
    {
    pinMode(switchPin, INPUT); //set button as input
    pinMode(offPin, INPUT); //set button as input
    pinMode(motorPin, OUTPUT); // set motor as output
    attachInterrupt (1,powerbutton,CHANGE);

    }

    boolean debounce(boolean last)
    {
    boolean current = digitalRead(switchPin);
    if (last != current)
    {
    delay(10);
    current = digitalRead(switchPin);
    }
    return current;
    }

    boolean speedup(boolean last2)
    {
    boolean current = digitalRead(offPin);
    if (last2 != current)
    {
    delay(10);
    current = digitalRead(offPin);
    }
    return current;
    }

    void loop()
    {
    // speedup off the fan
    currentButton2 = speedup(lastButton2);
    if (lastButton2 == LOW && currentButton2 == HIGH)
    {

    motorLevel = motorLevel + 82;

    }

    lastButton2 = currentButton2;
    if (motorLevel > 255) motorLevel = 82;

    analogWrite(motorPin,motorLevel);
    }

    void powerbutton()
    {
    currentButton = debounce(lastButton);
    if (lastButton == LOW && currentButton == HIGH)
    {
    motorOn = ! motorOn;

    }

    lastButton = currentButton;

    digitalWrite(motorPin,motorOn);
    }

  17. Hi, Jeremy
    I’d like to know what hardware do you use
    I’m interested in schimtt’s trigger especially.

    Thanks, Vladimir

  18. Is this necessary to use Schmmit-triger ecc for the button or a small capacitor to make it low is ok? (to use FALLING)

  19. Hi Jeremy,

    Thanks for the awesome video tutorial, works great.
    I’d like to know how you would implement hardware debounce if you have multiple switches connected to a single interrupt pin.
    Is this possiable?

    Regards,
    Jaun

    1. Why would you want to connect multiple switches to the same interrupt pin? You wouldn’t be able to tell which one is being pressed.

      1. Thank for the reply.
        The Idea was to save some pins on the ATMega328 chip, so I could connect multiple switches to a analog pin with different resistors on them and then calculate which button was pressed by looking at the reading on the analog pin.

        I Then do some custom interrupt settings to enable interrupts on analog pins.
        cli(); // switch interrupts off while messing with their settings
        PCICR =0x02; // Enable PCINT1 interrupt
        PCMSK1 = 0b00000111;
        sei(); // turn interrupts back on

        But having said all that the best would probably be to use something like a MCP23017 that supports interrupts or will that not work.

      2. Perhaps think of limit switches at each end of a CNC axis. If the X-axis is increasing and we hit a limit switch, we know we have exceeded the allowable size of the X-axis. If we are decreasing our X-axis value and hit a limit switch, then we have returned to zero. As the number of interrupts is limited, it makes sense to minimize their usage.

  20. Hi Mr Blum
    Thanks for this example about interrupts but I do think it is mainly just an example and not enough of a tutorial about WHY and HOW are interrupts needed. You mention it is better with them but perhaps you could give more explanations there. An example is not a good demonstration, it is just an illustration. So, I have understood how you do it in this very case but still would have an enormously hard time on any other cases.
    In short, here are a few questions which might help:
    – More cases where interrupts are needed and WHY so
    – Explanation of the syntax of the interrupt
    – Some interrupts are provided by the Arduino hardware, some are not: what is the global rule behind those ?

    Thanks and also your book is indeed a gret help !

  21. Hardware-debouncing can be done easier. Use the internal pullup-resistor and let the button connect to ground. A parallel capacity of 200nF parallel to the button does the trick for most pushbutton types.

    Some code for testing the debouncing on interrupt 0:

    /*
    Debouncing Test for Interrupt 0 Button
    The button connects Pin 2 to Ground,
    Parallel to the button, a capacity of 200 nF is attached.
    Achim Berg, 2014-07-17
    */

    volatile int count = 0;
    int lastCount = 0;

    // the setup routine runs once when you press reset:
    void setup() {
    // initialize serial communication at 9600 bits per second:
    Serial.begin(9600);

    //Pin 2 fires Interrupt 0
    pinMode(2, INPUT_PULLUP);
    attachInterrupt(0, countUp, FALLING);
    }

    void countUp()
    {
    count++;
    }

    // the loop routine runs over and over again forever:
    void loop()
    {
    if(count != lastCount)
    {
    if (count > lastCount + 1)
    {
    // we have bouncing:
    Serial.print(count);
    Serial.print(“–>”);
    Serial.println(count – lastCount);
    }
    else
    {
    // no bouncing
    Serial.println(count);
    }
    lastCount = count;
    }
    delay(1); // delay in between reads for stability
    }

  22. Hi Jeremy,

    great video! How would i customize the circuit to work with an Arduino Due which has 3.3 V logic level and not 5 V like the Uno?

    Thanks,

    Robert

  23. Hello, I am interested in attempting to use a switch with my Arduino to change between two sketches to control the output of an LED strip. I am looking to have the Arduino flash the LEDs according to sound input from a microphone (aka Sound Reactive), then using a button press (or presses), change to fade. My question: is this possible, and what is the best way to go about implimenting this in the Arduino?

  24. Can you give a link to the specific inverting schmitt trigger you used? I’m trying to find it in on DigiKey but there are so many products.

    Thanks

    1. A 74HC14 or 74LS14 in a DIP package should be fine. the HC device is CMOS so it uses very little power but is sensitive to ESD. The LS device uses more power but is insensitive to ESD. You’ll need a five volt power supply for these. There are 3.3 volt solutions but you’d have to hunt around for them. DigiKey should have the HC or LS devices. Good luck. Kevin H.

  25. Could the same button be used to trigger different interrupt functions depending on when in the loop the button push is detected?
    or is there a way of doing something like this?

    many thanks, James

  26. Hi jeremy, I have an problem that I want to discharge a capacitor used in CDI(Capacitor Discharge Ignition) without handling circuit live.
    I am searching for the discharger which can discharge the capacitor without get in contact with capacitor leads.
    Can you help me with it.

  27. Hi,
    I am trying to work with arduino timer1 interrupts to make an led blink every bit on an 8 bit number, depending on whether its a 1 or 0. However, im trying to make a basic blinking program, and it does not seem to be working.
    #include “TimerOne.h”
    bool val=0;

    void setup()
    {
    pinMode(13, OUTPUT);
    Timer1.initialize(500000); // initialize timer1, and set a 1/2 second period
    // setup pwm on pin 9, 50% duty cycle
    Timer1.attachInterrupt(callback); // attaches callback() as a timer overflow interrupt
    }

    void callback()
    {
    val=1;
    }

    void loop()
    {
    digitalWrite(13,val);
    while(!val);
    val=0;

    }

    The LED doesnt blink at all! Any help would be appreceitated!
    thanks!

  28. Jeremy,
    Could you you possibly show / say how you would wire a 2-pin momentary push-button (using internal Pull-ups) to the Schmitt Trigger? I have successfully followed your tutorial with the 3-pin pushbutton but cant figure the 2-pin button out!

    I currently have 1 side of my 2-pin push-button to ground and the other side directly to Pin 2 of my Arduino UNO using the internal pull-up (HIGH/LOW state determined through an interrupt) but am getting bouncing.

    Many Thanks.
    Jon

    1. Jon,

      Contact me at my email address and I’ll send you a schematic of how you’d hook up a switch to the input of the Schmitt-Trigger to avoid bouncing.

      Kevin H.
      [email protected]

  29. hello I am very beignner with arduino
    I need a code to trigger my laser externally, so i tried with arduino code but it is not working as i need
    My laser is a 50hz laser so it will fire 50 flashes in 1 second so i need to convert it to 1 time in 1 second. the code i have tried is here

    nt led = 13;
    int pin1 = 12;
    int flashlamp = 2;
    int val = 0;
    int counter = 0;
    void setup() {
    // put your setup code here, to run once:

    pinMode(led, OUTPUT);
    pinMode(pin1, OUTPUT);
    pinMode(flashlamp, INPUT);
    Serial.begin(9600);
    }

    void loop() {
    // put your main code here, to run repeatedly:
    val = digitalRead(flashlamp);
    if (val == HIGH){
    digitalWrite(led, HIGH);
    counter = 1;
    }
    else{
    digitalWrite(led, LOW);

    }
    {
    counter = counter + 1;

    }
    if (counter == 50)
    {digitalWrite(pin1, HIGH);
    }
    else
    {
    digitalWrite(pin1, LOW);
    }

    }

  30. Actually, you are off a little on your capacitor-resistor explanation.

    As soon as you push the button, the capacitor will instantly short to ground through the switch (0 ohms x 10uF= a time constant of 0. When you release the switch, the capacitor will start to charge and at some point exceed the threshold of the Schmitt trigger.

    But you were close…

  31. Jeremy- How can I get the Arduino to program itself and save me some time for more Facebook stuff? I want to just give it a random switch location and a random relay and LED and then have the Arduino know automatically what I want it to do.

    I really need help with this one!

    I love your videos. Congrats on being a EE. We need to stick together if we are going to take over the world…

  32. Jeremy how do we use a 4*4 matrix keypad inside an ISR.
    I mean after interrupt occurs i want to use my keypad to take input in my ISR using Arduino Uno.
    Please help.

  33. Hey Im making a arduino robot car controlled by laptop using bluetooth module HC 05. But im not able to get my head around this problem. How do i make my car move only till the key is pressed on the keyboard and stop as soon as i release the key. Any suggestions???

  34. Excellent tutorial!
    But not perfect. The hardware debouncing schema needs to be corrected. One more resistor (say 1K) is obligatory for discharging the capacitor thru the button. Otherwise:
    1) Huge discharge current pulses and button bouncing may generate some undesirable signals or extra interrupts the program is not designed to process.
    2) short-circuit the capacitor (thru the button) is not safe

  35. Hello,
    I am use of Interrupt codes like this:
    const byte ledPin = 13;
    const byte interruptPin = 6““““““`;
    //volatile byte state = LOW;

    unsigned long sCount = 0;

    void setup() {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
    pinMode(interruptPin, INPUT_PULLUP);
    attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
    // attachInterrupt(interruptPin, blink, RISING);
    }

    void loop() {
    // digitalWrite(ledPin, state);
    Serial.println(sCount);
    }

    void blink() {
    sCount++;

    But the incoming pulses to Arduino Due,can not to get well by it and the numbers in serial monitor,some time can`t be increased and another time it increase more than of incoming pulses.
    My sending pulses to arduino is variable and minimum 1 pulse per second to Maximum 80 pulses per second.
    It comes from an high voltage spark light,by optoisolator ic.
    But in counter code sketch in arduino,it works very well and without any mistake .
    It seems Interrupt codes is very sensitive for noises,i don`t know why…?
    Please advice me on this.
    Regards,
    Hamid

  36. Hi I have a situation where I need to activate three relays individually based on the analog inputs. But here when I tried with one sensor and activation of the relay it is working. And when I tried with 3 relays and 3 sensors I am not able to proceed with this . If u have any such code for activating 3 or more relays based on the interrupt I kindly request you to send the code.

  37. Hi I am trying to control a robot with a 5 channel radio control. Using inchangeint.h on my Arduino Uno example program it constantly gives me a reading slow I haven’t change the stick position and when I do it shows that I have changed and appears changing all the time. Also when one stick has moved I want to stop other sticks from interrupting until the used stick has returned to original position.

  38. Hey Jeremy,
    Great work with your tutorials.
    Can you please upload a sketch of this circuit?

  39. Alternate Links to Official Online Gambling Internet sites
    Now in an all-sophisticated era, everyone can access the internet very easily.
    Up to now many online games that can be enjoyed by everyone, one example is internet gambling games.
    With the appointment of betting that used to be only on land, now an online system has made it quite simple for many betting players to route their hobbies in the world of gambling online.

Leave a Reply to Jeremy Blum Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Advertisement