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

How to implement long press and short press for nrf5832(using 17.02 sdk and nrf5.0 sdk for mesh.... telling for reference) , i want to store scene when long press one button and recall scene when short press.

Hi,

 I want to store scene when long press one button and recall scene when short press. I have done some changes but not able to achieve it, i am not sure if i should use " bsp_event_to_button_action_assign" or "bsp_button_event_handler" for detecting long press and short press and then perform the scene store and scene recall operation.

I am attaching the implementation, correct me where i am wrong to achieve desired result. Can anyone help me in solving this issue on high priority?

in main.c

#include "bsp.h" // added for long and short press

#ifndef BSP_SIMPLE
static bsp_event_callback_t m_registered_callback = NULL;
static bsp_button_event_cfg_t m_events_list[BUTTONS_NUMBER] = {{BSP_EVENT_NOTHING, BSP_EVENT_NOTHING}};
APP_TIMER_DEF(m_bsp_button_tmr);
#endif // BSP_SIMPLE
#define BSP_LONG_PUSH_TIMEOUT_MS 1000

/ added for button long and short press

/**@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. */


// added for scene

uint32_t status = NRF_SUCCESS;
static scene_store_params_t store_params = {.scene_number = 1 };
static scene_recall_params_t recall_params = {0};
static scene_delete_params_t delete_params = {0};

model_transition_t transition_params_scene =
{
.delay_ms = APP_SCENE_DELAY_MS,
.transition_time_ms = APP_SCENE_TRANSITION_TIME_MS
};

// recall_params.scene_number = store_params.scene_number;
delete_params.scene_number = store_params.scene_number;


// button = bsp_board_pin_to_button_idx(pin_no);

// if (button < BUTTONS_NUMBER)
// {
switch (button_action)
{
case APP_BUTTON_PUSH:
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"in bsp short press event handler button 4 pressed \n");
event = m_events_list[button].push_event;
if (m_events_list[button].long_push_event != BSP_EVENT_NOTHING)
{
// short press will recall the scene
//added for scene

// scene 1
/*
static scene_store_params_t store_params = {.scene_number = 1 };
static scene_recall_params_t recall_params = {0};
recall_params.scene_number = store_params.scene_number;
*/
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,
"Sending msg: Scene Recall: Scene number: %d Tid: %d Trans time: %d ms Delay: %d ms\n",
recall_params.scene_number, recall_params.tid, transition_params_scene.transition_time_ms,
transition_params_scene.delay_ms);
status = scene_client_recall(&m_clients_scene[client], &recall_params, &transition_params_scene);
recall_params.tid++;

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;

// added for storing scene when long press
/*
__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,
"Sending msg: Scene Store: Scene number: %d\n", store_params.scene_number);
status = scene_client_store(&m_clients_scene[client], &store_params);

*/

}

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

static void button_handler(uint_32 button_number)

{

case 4: 

bsp_button_event_handler(15,2);

}

Thanks & Regards,

Ekta

  • Hi Ekta, 
    When you post code, please use Insert ->Code. It's really hard to read the code without the indents. 

    I'm not sure how you implement your code with bsp_button_event_handler() isn't it a function defined inside bsp.c ? 

    Please try to study the library and implement the long press handling inside a NRF5 SDK example first before you bring them to the mesh application. 

    If you are working on mesh application, another option is to modify the simple_hal.c to detect long press and short press. 

    In the current implementation we use this to detect a press: 

    static void button_event_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        for (uint32_t i = 0; i < ARRAY_SIZE(m_buttons_list); i++)
        {
            if (pin == m_buttons_list[i])
            {
                /* Check that the event was generated by a button press, and reject if it's too soon (debounce).
                 */
                if (TIMER_DIFF(m_last_button_press, timer_now()) > HAL_BUTTON_PRESS_DEBOUNCE_INTERVAL)
                {
                    m_last_button_press = timer_now();
                    m_button_handler_cb(i);
                }
            }
        }
    }

    You would need to implement a bit more to detect when the TIMER_DIFF(m_last_button_press, timer_now()) is longer than HAL_BUTTON_PRESS_DEBOUNCE_INTERVAL and shorter than HAL_BUTTON_PRESS_LONG_PRESS_INTERVAL then it's a short press. 
    If it's longer than HAL_BUTTON_PRESS_LONG_PRESS_INTERVAL  then it's a long press. 

    You need to define HAL_BUTTON_PRESS_LONG_PRESS_INTERVAL  according to what you want to be long press and what you want to be short press. 

    In addition, you would need to add a flag into the call back m_button_handler_cb() to tell if it's a long press or short press. 

  • Hi Hung,

    Thank you so much for replying, i never got reply for any of the questions i have posted on devzone, so thank you for responding. I will make sure i will insert the code properly.

    1) I want to use application layer as i wanted to perform certain operation with short and long press. I want to store scene with long press and recall scene with short press, so if i modify simple_hal.c, will i be able to perform these operations and how, can you attach code for that?

    2) bsp_button_event_handler() is there in bsp.c, but i am not sure how to use that for my application and the case that i mentioned i.e, to store and recall scenes by long press and short press respectively. Can you bit elaborate and attach code for that?

    3) i did not understand when you say implement with NRF5 SDK first then bring to mesh application, can you please help me in understanding that? Actually this is on high priority so right now can not explore much of the options, wanted to implement for the scenario i mentioned.

    4) What shall i change in simple_hal.c for the desired output.

    It will be really helpful if you can help me in getting desired result ASAP.

    Thanks & Regards,

    Ekta

  • I'm not sure how you implemented bsp into main.c. What I want to explain is that you can study the bsp module in a BLE application in the nRF5 SDK, not mesh application. In mesh application we use the simple_hal.c for handling button. 

    If you want to get something working without much change, I would suggest to follow my suggestion on modifying simple_hal.c

    You need to study the button_event_handler() and understand how it work, after that you need to modify 

     if (TIMER_DIFF(m_last_button_press, timer_now()) > HAL_BUTTON_PRESS_DEBOUNCE_INTERVAL)

    To detect if it's a long press or it's short press. The current implementation only detect if it's pressing longer than HAL_BUTTON_PRESS_DEBOUNCE_INTERVAL or not. 

  • Hi Hung,

    Thank you for your response.

    1) If i make changes in button_event_handler of simple_hal.c, can i use the scene functionality functions, i mean the scene store and scene recall functions as they are in the mesh application. I need to use the app_scene.c and scene_client.c file functions for my implementation of long and short press as i want to store scene by long press and recall scene by short press. 

    2) or should i create button event handler in main.c file for this operation, but as button press is being handled in simple_hal.c file i am not sure how to achieve this means, how to implement button event handler of simple_hal.c in main.c 

    3) I was thinking of implementing in main.c file, can we implement by calling APIs( like bsp_button_event_handler) for long and short press in main.c file as i want to use scene functionality, i am not sure if i can implement changes for scene store and scene recall in simple_hal.c

    4) Please can you help me in achieving this functionality of storing scene by long press and recalling scene by short press. As, i am not able to understand how should i detect and implement long and short press. As per my requirement I want to use button 4, if i am pressing button 4 then with long press of button 4 i want  to store scene and with short press of button 4 i want to recall the scene. How to do that?

    Thanks & Regards,

    Ekta

  • Hi Hung,

    I have implemented this part of code in simple_hal.c in button_event_handler function and added this " #define HAL_BUTTON_PRESS_LONG_PRESS_INTERVAL SEC_TO_MS (5) in file "simple_hal.h".

    static void button_event_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        for (uint32_t i = 0; i < ARRAY_SIZE(m_buttons_list); i++)
        {
    
            if (pin == m_buttons_list[i])
            {
              
                if (  HAL_BUTTON_PRESS_DEBOUNCE_INTERVAL < TIMER_DIFF(m_last_button_press, timer_now()) < HAL_BUTTON_PRESS_LONG_PRESS_INTERVAL )
                {
                    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO," Long press for 5 sec \n");
                    m_last_button_press = timer_now();
                    m_button_handler_cb(i);
                }
    
                else 
                {
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO," short press for \n");
                }
                
    
                /* Check that the event was generated by a button press, and reject if it's too soon (debounce).
                 */
                 
                 /*
                if ( TIMER_DIFF(m_last_button_press, timer_now()) > HAL_BUTTON_PRESS_DEBOUNCE_INTERVAL)
                {
                    m_last_button_press = timer_now();
                    m_button_handler_cb(i);
                }  */
    
            }
        }
    }
    

    Getting error when i debug the code as " <t:     183249>, app_error_weak.c,   96, Softdevice assert: 151332:0". Can you help me in resolving this issue and implementing long and short press for two functionalities.

    Thanks & Regards,

    Ekta

Related