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

Generate Events Continuously With BSP While Holding a Button Down?

Hi, 

I'm trying to use the BSP functions to do the following. 

1. Detect three different button pressing types. First - singular quick press, Second - Long Press with Timeout (say 1 second), and Third - Continual Press with no Timeout

2. Quick press and long press to disconnect and sleep (I have been successful in this)

3. Continual Press to send data as long as a button is held down. (This is what I'm having trouble with)

I'm having some issues figuring out the third one to always send data while I'm pressing a button. All of the examples (from what I can tell) only generate a singular button press EVENT. In essence what I want to do I believe is as long as the button is held down, generate an event so it can be handled in the bsp_event_handler. 

/**@brief Function for handling events from the BSP module.
 *
 * @param[in]   event   Event generated when button is pressed.
 */
static void bsp_event_handler(bsp_event_t event)
{
    ret_code_t err_code;

    switch (event)
    {
        case BSP_EVENT_SLEEP:
            
            sleep_mode_enter();
            break; // BSP_EVENT_SLEEP

        case BSP_EVENT_DISCONNECT:
            err_code = sd_ble_gap_disconnect(m_conn_handle,
                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            if (err_code != NRF_ERROR_INVALID_STATE)
            {
                APP_ERROR_CHECK(err_code);
            }

            break; // BSP_EVENT_DISCONNECT

        case BSP_EVENT_KEY_0:
            
            printf("Continuously Send Data\n");

            break;
            
        default:
            break;
    }
}

In examining bsp.c I've identified a potential spot to try and modify but I'm not sure if it would work or how to do it without conflicting with the long button press (1 sec) indication. I think if I could somehow use a rolling counter and with a "constant_pushed_pin_no = pin_no" it may work. 

/**@brief Function for handling button events.
 *
 * @param[in]   pin_no          The pin number of the button pressed.
 * @param[in]   button_action   Action button.
 */
static void bsp_button_event_handler(uint8_t pin_no, uint8_t button_action)
{
    bsp_event_t        event  = BSP_EVENT_NOTHING;
    uint32_t           button = 0;
    uint32_t           err_code;
    static uint8_t     current_long_push_pin_no;              /**< Pin number of a currently pushed button, that could become a long push if held long enough. */
    static bsp_event_t release_event_at_push[BUTTONS_NUMBER]; /**< Array of what the release event of each button was last time it was pushed, so that no release event is sent if the event was bound after the push of the button. */

    button = bsp_board_pin_to_button_idx(pin_no);

    if (button < BUTTONS_NUMBER)
    {
        switch (button_action)
        {
            case APP_BUTTON_PUSH:
                event = m_events_list[button].push_event;
                if (m_events_list[button].long_push_event != BSP_EVENT_NOTHING)
                {
                    err_code = app_timer_start(m_bsp_button_tmr, APP_TIMER_TICKS(BSP_LONG_PUSH_TIMEOUT_MS), (void*)&current_long_push_pin_no);
                    if (err_code == NRF_SUCCESS)
                    {
                        current_long_push_pin_no = pin_no;
                    }
                }
                release_event_at_push[button] = m_events_list[button].release_event;
                break;

            case APP_BUTTON_RELEASE:
                (void)app_timer_stop(m_bsp_button_tmr);
                if (release_event_at_push[button] == m_events_list[button].release_event)
                {
                    event = m_events_list[button].release_event;
                }        
                break;
            case BSP_BUTTON_ACTION_LONG_PUSH:
                event = m_events_list[button].long_push_event;
        }
    }

    if ((event != BSP_EVENT_NOTHING) && (m_registered_callback != NULL))
    {
        m_registered_callback(event);
    }
}

Anyone have any ideas on how this could be approached?

Thanks!

  • Well, you only got two events to work with, pushed and released. I suggest you add a timer in the pushed event that times out after one second, that then periodically, like every 0.5seconds, check if the pin is still held in it's pushed state and if so, do the thing you want to do. 

    The BSP library is just intended to be used to run examples on the DK. In a real application, I would ditch the BSP in favor of the Button handling library (Button Handler, API). The BSP uses the button handling library as well, there's just a lot of abstraction on top of it. 

  • Darn, I was thinking that I could maybe modify the bsp.c to include another event (other than APP_BUTTON_PUSH and APP_BUTTON_RELEASE, etc which would be APP_BUTTON_HOLD. Not sure if that is feasible though.

    Do you think there is a way to use the Button Handling Library to trigger events continuously on a held button press? The only thing that caught my attention as a possible use was the following function within app_button.c, but I'm not sure how I could use that for generating continuous events by pressing and holding. 

    bool app_button_is_pushed(uint8_t button_id)
    {
        ASSERT(button_id <= m_button_count);
        ASSERT(mp_buttons != NULL);
    
        app_button_cfg_t const * p_btn = &mp_buttons[button_id];
        bool is_set = nrf_drv_gpiote_in_is_set(p_btn->pin_no);
    
        return !(is_set ^ (p_btn->active_state == APP_BUTTON_ACTIVE_HIGH));
    }
    #endif //NRF_MODULE_ENABLED(BUTTON)

    Thanks!

  • I suggest you start a timer on a pushed event, and in the timer callback you check if the button is still pressed with app_button_is_pushed. If so you call whatever function you want to periodically call then re-start the timer so that you create a non-blocking loop that periodically checks if the button is still pressed. 

Related