Unexpected Behavior with GPIO_INT_EDGE_BOTH Interrupt on Button Release in nRF Connect SDK

I'm encountering an issue with the use of the GPIO interrupt type GPIO_INT_EDGE_BOTH on a GPIO connected to a button. When pressed, the button pulls the GPIO to GND, and when released, it sets it to VDD. Searching online, I found that others have faced the same issue, but I couldn't find a clear explanation or a well-thought-out solution.

The problem is that when the button is pressed, the callback function is called as expected, providing the correct GPIO value. However, when the button is released, the callback function is called twice: first, it reports the previous GPIO value, and only afterward does it provide the correct value. I simplified my code to isolate the issue (nRF Connect SDK 2.6.1):

static const struct gpio_dt_spec signalTouch = GPIO_DT_SPEC_GET(DT_NODELABEL(touch_mcu), gpios);
static struct gpio_callback signalTouchCbData;

gpio_pin_configure_dt(&signalTouch, GPIO_INPUT) < 0);

if (gpio_pin_interrupt_configure_dt(&signalTouch, GPIO_INT_EDGE_BOTH) != 0) {
    return;
}

gpio_init_callback(&signalTouchCbData, Signal_Touch_Changed_Callback, BIT(signalTouch.pin));
gpio_add_callback(signalTouch.port, &signalTouchCbData);

static void Signal_Touch_Changed_Callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
    int touchState;

    touchState = gpio_pin_get_dt(&signalTouch);
    LOG_WRN("touchState: %d at %lld", touchState, k_uptime_get());
}

The code produces the following output:

00> [00:00:10.980,895] <wrn> app: touchState: 1 at 10980  <--- button pressed
00> [00:00:12.531,433] <wrn> app: touchState: 1 at 12531  <--- button released
00> [00:00:12.531,585] <wrn> app: touchState: 0 at 12531
00> [00:00:18.167,999] <wrn> app: touchState: 1 at 18167  <--- button pressed
00> [00:00:20.063,323] <wrn> app: touchState: 1 at 20063  <--- button released
00> [00:00:20.063,476] <wrn> app: touchState: 0 at 20063

What is causing this issue?

Parents
  • Hello,

    What you are seeing is probably a bounce. It is however, a little bit strange if it is consistent in the pattern that you are seeing. Is it always like that, or is it a coincidence that you always get one touchState 1 before the touchState 0 in your log? 

    Either way, I would say that a small debounce would do the trick here. You can introduce a small delay before you read the pin state. You can see an example on how this is done in the dk_buttons_and_leds.c in NCS (ncs\nrf\lib\dk_buttons_and_leds\dk_buttons_and_leds.c), where they use k_work_reschedule to scan the buttons 1ms later. 

    Alternatively, you can do something like this, and use a timer to check that the button was held for at least some time, to rule out the bounce signals:

    3175.long_press_v2.zip

    Here the "debounce" is set to 10 seconds, so that is really more of a long press detection. But if you set it to something like 100ms or 50ms, it would act more like a debounce.

    Another alternative is to add some passive components (capacitor) close to the button pin, so that the signal doesn't bounce as much when the button is being pressed. 

    Best regards,

    Edvin

Reply
  • Hello,

    What you are seeing is probably a bounce. It is however, a little bit strange if it is consistent in the pattern that you are seeing. Is it always like that, or is it a coincidence that you always get one touchState 1 before the touchState 0 in your log? 

    Either way, I would say that a small debounce would do the trick here. You can introduce a small delay before you read the pin state. You can see an example on how this is done in the dk_buttons_and_leds.c in NCS (ncs\nrf\lib\dk_buttons_and_leds\dk_buttons_and_leds.c), where they use k_work_reschedule to scan the buttons 1ms later. 

    Alternatively, you can do something like this, and use a timer to check that the button was held for at least some time, to rule out the bounce signals:

    3175.long_press_v2.zip

    Here the "debounce" is set to 10 seconds, so that is really more of a long press detection. But if you set it to something like 100ms or 50ms, it would act more like a debounce.

    Another alternative is to add some passive components (capacitor) close to the button pin, so that the signal doesn't bounce as much when the button is being pressed. 

    Best regards,

    Edvin

Children
Related