Button Debounce routine
Posted: Tue Mar 02, 2021 6:19 pm
I implemented a debounce algorithm in my ESP32 code and would like to have some comments/ideas on the implementation. I am using 2 ESP32s (1 handles wifi while the other handles bluetooth classic). the wifi device has 3 inputs that change state with buttons and control 4 outputs which are interrupts to the bluetooth device. The interrupt routines for all inputs are simple and send a Freertos semaphore to a Freertos task which is designed to decide between a low-going glitch and an actual low button press. The Freertos tick frequency is set at 1000 Hz.
Important Note: For an ESP32, GPIO Inputs that are added to the underlying interrupt service driver become “shared interrupts” and will cause an interrupt to be generated for both a Negative Edge AND a Positive Edge (ANY EDGE). So, the code sees 2 interrupts for every button press/release regardless of the config setup. That’s just the way it is!!!!
wifi device code:
ISR:
TASK:
all of the interrupts generated by buttons follow the above logic. I am not sure if this will catch a single glitch caused by EMI or other perturbation. Please comment. Thanks…
Important Note: For an ESP32, GPIO Inputs that are added to the underlying interrupt service driver become “shared interrupts” and will cause an interrupt to be generated for both a Negative Edge AND a Positive Edge (ANY EDGE). So, the code sees 2 interrupts for every button press/release regardless of the config setup. That’s just the way it is!!!!
wifi device code:
ISR:
Code: Untitled.txt Select all
IRAM_ATTR static void ISR_Door_Sensor_Interrupt(void* arg)
{
/* disable the interrupt to try to eliminate the reciprocal edge interrupt */
gpio_intr_disable(door_sensor);
xSemaphoreGiveFromISR(gpio_door_sensor_semaphore, NULL);
}
Code: Untitled.txt Select all
static void TASK_Handle_GPIO_Door_Sensor_Interrupt(void* arg)
{
uint16_t door_history = 0b1111111111111111;
int check_count = 0;
int LOW = 0;
int HIGH = 1;
for(;;)
{
if(xSemaphoreTake(gpio_door_sensor_semaphore, portMAX_DELAY) == pdTRUE)
{
check_count = 0;
door_history = 0b1111111111111111;
while(check_count < 16)
{
door_history = door_history << 1;
door_history |= gpio_get_level(door_bell);
check_count += 1;
vTaskDelay(5 / portTICK_PERIOD_MS);
/* total debounce time 80 mSec + instruction processing time */
}
}
/* only looking at the last four reads */
if((door_history & 0b0000000000001111) == 0b0000000000000000).
{
TASK_Door_Handler(LOW);
}
else if((door_history & 0b0000000000001111) == 0b0000000000001111)
{
TASK_Door_Handler(HIGH);
}
/* Delay 1/2 second to eliminate the reciprocal interrupt (high-->low or low-->high)
vTaskDelay(500 / portTICK_PERIOD_MS);
gpio_intr_enable(door_sensor);
}
}