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

Button long press functionality using nrf52840

I'm using nrf52840  and SDK VR 15.0.0

I want to apply the long press button functionality and short press button functionality to change the screens in OLED SSD1306.

How can I perform that?

Thank you!

  • Hello,

    This is implemented as part of the bsp module, and you may see its implementation in SDK/components/libraries/bsp/bsp.c, specifically the bsp_button_event_handler function.

    /**@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);
        }
    }


    Based on this, you could either make a similar implementation yourself, or you may use the BSP module directly - this is up to you.

    Please let me know if anything still should be unclear, or if you have any other questions.

    Best regards,
    Karl

  • Thanks for your reply, Karl!

    From forums, I got to know about this bsp_button_event_handler.

    While calling this API how the argument " action " defined.

    ex: bsp_button_event_handler(12,2)

    12 means button_2 pin number

    2  means the BSP_BUTTON_ACTION_LONG_PUSH

    Is this the right way or any different approach for using that API please let me know sir !!

    Thank you

  • manoj97 said:
    Thanks for your reply, Karl!

    No problem at all, I am happy to help!

    manoj97 said:
    While calling this API how the argument " action " defined.

    Please have a look in the bsp.h file for this.
    The relevant parts for the definition of the different button actions(push, release, long_push) is found in the bsp.h, and included below:

    #define BSP_BUTTON_ACTION_PUSH      (APP_BUTTON_PUSH)    /**< Represents pushing a button. See @ref bsp_button_action_t. */
    #define BSP_BUTTON_ACTION_RELEASE   (APP_BUTTON_RELEASE) /**< Represents releasing a button. See @ref bsp_button_action_t. */
    #define BSP_BUTTON_ACTION_LONG_PUSH (2)                  /**< Represents pushing and holding a button for @ref BSP_LONG_PUSH_TIMEOUT_MS milliseconds. See also @ref bsp_button_action_t. */
    
    typedef struct
    {
        bsp_event_t push_event;      /**< The event to fire on regular button press. */
        bsp_event_t long_push_event; /**< The event to fire on long button press. */
        bsp_event_t release_event;   /**< The event to fire on button release. */
    } bsp_button_event_cfg_t;

     

    manoj97 said:
    Is this the right way or any different approach for using that API please let me know sir !!

    This would be a correct function call - but there would be little point to it if you had to call it manually. Please have a look at the bsp_event_to_button_action_assign function to see how you may connect a specific event to a button.
    If you would like to see an example of how you could configure and use the button functionality, please have a look at the bsp example, or for a bigger demonstration see the button functionality in the Blood Pressure example - for example if you are looking for the long_press action specifically, see how the Blood Pressure example implements long_push to disconnect from a BLE Connection.
    Here is the Button library API Reference, in case you have not seen it already.

    Best regards,
    Karl

  • Thanks for your reference really worth it!

    Those two examples 1) bsp_example 

                                      2) Blood pressure example is mainly dealing with the short press button function.

    but I required for the long-press key button.

    Actually the difficulty that I'm facing is I have to change the OLED screen when I long press and release the button for 10 sec / any secs, then the home screen has to come.

    For menu based screens, I'm using the "OLED task thread " with one button pressing there is no problem in it! 

    Problem is with the same button when I press for 10sec it has to go home screen  hope you got my point

    can you help with this?

  • manoj97 said:
    Thanks for your reference really worth it!

    I am glad you found it useful!

    manoj97 said:
    but I required for the long-press key button.

    Yes, as I mentioned in my previous comment you should have a look at the Blood Pressure example to see how you may implement more advanced button functionality(multiple configurations based on current BLE state) as well as long presses.

    manoj97 said:
    Actually the difficulty that I'm facing is I have to change the OLED screen when I long press and release the button for 10 sec / any secs, then the home screen has to come.

    The duration of a long press is 2 seconds by default, but you may change that in your own implementation - please see line 65 of bsp.h.

    If you are unsure of how you can connect an event to a certain action, let me draw up an example.
    Say that we would like an arbitrary "OLED_update()" function to be called every time we long-press a button from a non-sleep state, the following is one way we could go about implementing that:

    #define BTN_ID_OLED_UPDATE         0
    #define BTN_ACTION_OLED_UPDATE  BSP_BUTTON_ACTION_LONG_PUSH
    ..
    err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
    APP_ERROR_CHECK(err_code);
    ..
    err_code = bsp_event_to_button_action_assign(BTN_ID_OLED_UPDATE,
                                                 BTN_ACTION_OLED_UPDATE,
                                                 BSP_EVENT_KEY_0);
    RETURN_ON_ERROR_NOT_INVALID_PARAM(err_code);
    ..
    
    static void bsp_event_handler(bsp_event_t event)
    {
        ret_code_t err_code;
        
        switch (event)
        {
            case BSP_EVENT_KEY_0:
                OLED_update();
                break;
            ..
            default:
                break;
        }
    }
    
    


    The code written above is meant to illustrate the process of assigning a button event to a button press, and hopefully this will make the process more clear.
    Please do not just copy the code, but view it along side the blood pressure example for clarity.

    Please let me know if anything still should be unclear!

    Best regards,
    Karl

Related