Skip to main content
Visitor II
November 25, 2019
Solved

Debouncing

  • November 25, 2019
  • 12 replies
  • 21187 views

Can anyone help me with debounce code in C for Rising and falling edge interrupt??

    This topic has been closed for replies.
    Best answer by waclawek.jan

    As the first thing, forget about the EXTI interrupt, and *never* use it again, when it comes to mechanical switches.

    Perform the sampling based on a timer, or timer-controlled process (either in timer interrupt, or based on flag set in timer interrupt, or any other mechanism ensuring you will do it regularly but not too often). You want to sample once in a few milliseconds, and you want to sample a few times - say four to twelve - basically for the duration of bouncing of the switch. Have a variable with several states controlling your process - "stable 0", "bouncing 1", "stable 1", "bouncing 0" - and then the transition between "bouncing x" to "stable x" is the "output edge" upon which you perform the action you want to do when the button is pressed/released.

    You also have to work more to remove the input noise, as Ozone said above.

    JW

    12 replies

    Super User
    November 25, 2019

    No.

    JW

    Visitor II
    November 25, 2019

    No.

    Eric

    Visitor II
    November 25, 2019

    If you have noticed a lack of enthusiasm in answering your question it may be that you are asking the classical "how high is up?" question. What are you debouncing? A radar return, a pushbutton, the S-wave from a nuclear detonation? What's the frequency of the bounce? What's the expected duration? How do you define stable and unstable states? What circuit elements are used to filter and dampen oscillations?

    Try searching on "sliding window" debounce routines. Or read your textbook for this homework assignment. Hint: both edges of an interrupt tell you the signal is changing state. A debounced status should tell you when there is no change of state. What's the common factor as you integrate the signal across the time domain (i.e. the sliding window)?

    Some advice: don't fall for the simple fixed delay solution. There is always an edge case where this fails. A skilled embedded programmer won't go to the dark side....

    Jack Peacock

    Visitor II
    April 17, 2024

    @Jack Peacock_2 How about configuring a gpio interrupt to be triggered for both edges,

    let's say, if I consider rising edge to be first & next falling edge to be second edge.

    Declare one byte volatile variable, out of which only first 2 bits, bit-0 & bit-1 will be used as: bit-0 set on first interrupt (I assume key pressed), bit-1 set on second interrupt (I assume key released), once I get the value 0x03 in this variable, I may generate a s/w interrupt or an event or push 1 in a queue reserved to detect pin status change, lets call it a key event.

    Process whatever upon this key event & clear the variable

    Do I still need to make logic for debouncing? or this can be done utilizing available gpio configuration.

    It is my intuition that key cannot be released until it is pressed. So, I consider first interrupt as key pressed & second as key released.

    I would appreciate you response...

    sne_123Author
    Visitor II
    November 26, 2019

    @Community member​ 

    Sir I am debouncing one switch. I have used one debounce mechanism but I feel its not working properly or maybe I am doing some mistake . I am using STM32F103 .The problem occurs when, for example, near the device occurs a spike caused for example by a closing of a 220vac contact (not connected to device nor even to the microcontroller).

    In few words, a spark (220VAC contact closure ) leads to trigger the interrupt on the MCU. interrupt should not be generated becuase of 220VAC contact closure.

    the debounce routine which I am using is as follows:-

    Unbounce count is set to 20.

    int PB0Pressed (void) {

     static int PB0KeyCount = 0, PB0KeyPressed = 0;

     if (PB0KeyPressed) {

      if (!((GPIOB->IDR & PB0) == 0 )) {       // Check if S1 is not pressed

       if (PB0KeyCount < UNBOUNCE_CNT) PB0KeyCount++;

       else {

        PB0KeyPressed = 0;

        PB0KeyCount = 0;   

       }

      }

     }

     else {

      if (((GPIOB->IDR & PB0) == 0 )) {       // Check if S1 is pressed

       if (PB0KeyCount < UNBOUNCE_CNT) PB0KeyCount++;

       else {

        PB0KeyPressed = 1;

        PB0KeyCount = 0;

    return (1);

       }

      }

     }

     return (0);

    }

     void EXTI0_IRQHandler(void)

    {

    if(!PB0Pressed())

    {

    for(int i=0;i< 5000000;i++){}

    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == RESET)

    {

    //HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);

    //..printf("RELAY 1 OFF\n\r");

    relay1_on_flag1 = 1;

    GPRS_HttpPost_relay();

    }

    else

    if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == SET) 

    {

    //HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_SET);

    //..printf("RELAY 1 ON\n\r");

    relay1_on_flag1 = 0;

    GPRS_HttpPost_relay();

    }

    }

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

    HAL_NVIC_ClearPendingIRQ(EXTI0_IRQn);

    }

    and the GPIO configuration is as follows:-

     GPIO_InitTypeDef GPIO_InitStruct;

     /* GPIO Ports Clock Enable */

     __HAL_RCC_GPIOC_CLK_ENABLE();

     __HAL_RCC_GPIOD_CLK_ENABLE();

     __HAL_RCC_GPIOA_CLK_ENABLE();

     __HAL_RCC_GPIOB_CLK_ENABLE();

     GPIO_InitStruct.Pin = GPIO_PIN_0;

     GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;

     GPIO_InitStruct.Pull = GPIO_PULLUP;

     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

      HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 1);

      HAL_NVIC_EnableIRQ(EXTI0_IRQn);

    Is there any mistake in my code?

    Explorer
    November 26, 2019

    > .The problem occurs when, for example, near the device occurs a spike caused for example by a closing of a 220vac contact (not connected to device nor even to the microcontroller).

    > In few words, a spark (220VAC contact closure ) leads to trigger the interrupt on the MCU. interrupt should not be generated becuase of 220VAC contact closure.

    You do not have a debounce problem, but an EMI / hardware problem. If you cannot differ switch state transitions from interspersed EMI, you are screwed.

    Either add filters to said disruptive mains switches, or increase the current through the debounced switch (i.e. by smaller pull-up/pull-down resistors) to increase the SNR (signal-to-noise ratio).

    sne_123Author
    Visitor II
    November 26, 2019

    @Ozone​ We tried with Pi (CLC) filter , RC filter, shielding to eliminate noise from EMI/EMC. Our device includes lot of wiring as it is a prototype. So we are not able to eliminate the noise through hardware.

      Is there any way we can control it through software?

    sne_123Author
    Visitor II
    November 26, 2019

    The problem is debouncing is not working for rising edge.

    Super User
    November 26, 2019

    As the first thing, forget about the EXTI interrupt, and *never* use it again, when it comes to mechanical switches.

    Perform the sampling based on a timer, or timer-controlled process (either in timer interrupt, or based on flag set in timer interrupt, or any other mechanism ensuring you will do it regularly but not too often). You want to sample once in a few milliseconds, and you want to sample a few times - say four to twelve - basically for the duration of bouncing of the switch. Have a variable with several states controlling your process - "stable 0", "bouncing 1", "stable 1", "bouncing 0" - and then the transition between "bouncing x" to "stable x" is the "output edge" upon which you perform the action you want to do when the button is pressed/released.

    You also have to work more to remove the input noise, as Ozone said above.

    JW

    Explorer
    November 26, 2019

    > As the first thing, forget about the EXTI interrupt, and *never* use it again, when it comes to mechanical switches.

    I tend to agree.

    With EXTI interrupts, it is hard to keep track of the timing. And you are supposed to know the timing of your switches, i.e. how long it bounces, and when the state is stable. Polling a GPIO once in a while (every 10ms) is easier ans simpler.

    > Our device includes lot of wiring as it is a prototype. So we are not able to eliminate the noise through hardware.

    You can try to replace the cable to the switch with a shielded one, or at least a cable twisted with a ground wire.

    ST Employee
    November 26, 2019

    My favorite article about debouncing. It contains both hardware and software solutions.

    Hopefully, it will help.

    http://www.ganssle.com/debouncing.htm

    Super User
    November 26, 2019

    THIS ^ Jack Ganssle's columns should be required reading for every hardware or firmware engineer.

    Visitor II
    November 26, 2019

    Get a main loop 50msec flag set regularly, one set, clear it and scan your key like a "stoboscopic" view.

    Increase the counter when it's pressed, clear it when released. Consider it pressed after 3 increments = 50x3=150msec triple check.

    Of course, you can keep counting up and send key level events (first pressed, repeated press, pressed 5 seconds, etc...)

    sne_123Author
    Visitor II
    November 27, 2019

    Thank you everyone for your help. I solved the issue. :)

    sne_123Author
    Visitor II
    December 6, 2019

    Thank you all for answering.. I have solved the issue... :) created a debounce check using time check of 10ms as well as kept a check for previous states.