This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GPIOTE Interrupt doesn't catch button press

Hi all,

I am currently developing on the RIGADO BMD-300 (nRF52832) eval board. I have the following code setup to interrupt on a button press (aim is to have 9 buttons). I am storing the current state of the button in a single byte (m_custom_value). The idea is that all buttons are pulled-up so that start high. As the IN Sense is set to Toggle, i was assuming that when the button is pressed, i would get an interrupt and when the button is released i would get another interrupt. Ultimately, i would expect the button state to stay low (0) if i hold down the button and then change to high when i release the button. 

This seams to work, but not very well. I am not interrupting on every press and release. Can someone please tell me if there is a more robust way of doing this instead of polling the specific inputs and using lots of processing time?

Regards,

Zoran

void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{

    if (pin == GL1)
    {
        value[2] = value[2] ^ 0x01;
    }
    else if (pin == GL2)
    {
        value[2] = value[2] ^ 0x02;
    }
}

static void gpio_init(void)
{
    ret_code_t err_code;

    value[2] = 0xFF;

    if (!nrf_drv_gpiote_is_init())
    {
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    }

    nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(false);
    err_code = nrf_drv_gpiote_out_init(12, &out_config);
    APP_ERROR_CHECK(err_code);

    //Setup GL1 Input
    nrf_drv_gpiote_in_config_t in_config_GL1 = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
    in_config_GL1.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(GL1, &in_config_GL1, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(GL1, true);

    //Setup GL2 Input
    nrf_drv_gpiote_in_config_t in_config_GL2 = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
    in_config_GL2.pull = NRF_GPIO_PIN_PULLUP;

    err_code = nrf_drv_gpiote_in_init(GL2, &in_config_GL2, in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(GL2, true);
}

Parents Reply Children
  • Hi Einar,

    Thanks for the feedback. I have setup an output pin and toggled this in the in_pin_handler() event handler along with storing the state of the button as in the code above in value[] byte. I was observing the state of the output pin on an oscilloscope as i was pressing a momentary pushbutton connected to the input. With this setup i could frequently see that during the button press the interrupt would not capture the event (whether high to low (push down) or low to high (release button). 

    I am doing this in conjunction with sending the value of "value[]" over BLE. Do you think that BLE will conflict with the button interrupt priority?

  • Hi,

    You are right that the interrupt will be blocked by any higher priority interrupts (for instance from the SoftDevice). This would lead to a delay in the handling of the interrupt, but the only way you would lose an interrupt is if there are multiple interrupts while being blocked by a higher priority interrupt. This does not seem very likely though, as button presses are typically quite slow compared to the maximum block time for a SoftDevice interrupt (see Processor usage patterns and availability), except for a few special cases such as during flash erase operations.

    Do you have any other interrupt sources in your application? What is the interrupt priority for GPIOTE in your application (GPIOTE_CONFIG_IRQ_PRIORITY set in the projects sdk_config.h)?

    Br,

    Einar

  • Hi Einar,

    I did some further investigation. I used the pin_change_int example as this does not use the softdevice and updated the input button to a pin on the dev board that i have an external pushbutton connected to (pin P0.11). I discovered on the oscilloscope that the interrupt is catching the button press but because of the mechanical contact bounce, it is toggling the output multiple times. I then switched the input to one of the 4 buttons on the dev board and found this to work perfectly. After looking at the schematic for the dev board, each button has ESD protection. Would this be the main reason why the on-board buttons work correctly? if this is the case, i can definitely add this to my custom board.

    Also, when i tried to access these buttons in my BLE code (based on the ble_app_template), the code doesn't run (there is no advertising). I know that the ble_app_template uses button 1 to wake up and advertise, but why cant i access the other 3 buttons?

    Another question: What is the best approach to add buttons and outputs to a custom board with BLE? Is it to use the BSP module or this approach with my own interrupt handler?

    Thanks heaps for your support.

    Zoran

  • Btw, The interrupt priority in the sdk_config.h is set to 6

  • That explains it. You need to low pass filter the button (hardware debouncing) if you want a single interrupt for each button transition. If not you need to handle multiple rapid interrupts (due to switching noise), and debounce in software.

    I would say that the best approach is to filter the button signal as we do in the DK, as this limits the number of interrupts you have to handle in a short time. You could do software debouncing in addition to be sure, but you might not need it. I you want software debouncing you can for instance use the Button handling library.

Related