cancel
Showing results for 
Search instead for 
Did you mean: 

Debouncing

sne_123
Associate III

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

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

18 REPLIES 18

No.

JW

ETsai.1581
Associate

No.

Eric

Jack Peacock_2
Senior III

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

sne_123
Associate III

@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?

> .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_123
Associate III

The problem is debouncing is not working for rising edge.

@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?

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

> 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.