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

app_button_is_pushed() just working with NRF_LOG_INFO() before it

Hi,

I want to see if a button is pressed. But the function app_button_is_pushed() is not working corectly. I am using the s132 in the ble_app_blinky peripheral example. Except the folowing Code the example is unchanged.

int main(void)
{
    // Initialize.
    log_init();
    leds_init();
    timers_init();
    buttons_init();
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

    // Start execution.
    NRF_LOG_INFO("Blinky example started.");
    //advertising_start();
		int a=0;
    // Enter main loop.
    for (;;)
    {
			NRF_LOG_INFO("This makes it work");
			
			if(app_button_is_pushed(0)&&a==0)
			{
				a=1;
				NRF_LOG_INFO("Advertising Started");
				advertising_start();
			}
        idle_state_handle();
    }
}

When I leave the NRF_LOG_INFO("This makes it work") out the code doesn't work when I push the button. If I have the NRF_LOG_INFO in the code like in the example above it works. Additionaly if I debug the session it is working like it should, with or without the NRF_LOG_INFO.

I am a bit confused. Why does it work with the log printed and not without it and what change does the NRF_LOG_INFO make to the Code to work?

Parents
  • Hi.

    There are two things that results in your issue.

    1.

    The buttons are only enabled once you have connected to a device in the ble_app_blinky example.

    If you look at line 395 in the function static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context), you can see that the buttons are enabled by:

                err_code = app_button_enable();
                APP_ERROR_CHECK(err_code);

    And since you're not advertising before you press a button, there is nothing to connect to first. So you have to enable the buttons another place in your code.

    2.

    There is a button event handler inplemented in the ble_app_blinky example.

    #define LEDBUTTON_BUTTON                BSP_BUTTON_0                            /**< Button that will trigger the notification event with the LED Button Service */
    
    /**@brief Function for handling events from the button handler module.
     *
     * @param[in] pin_no        The pin that the event applies to.
     * @param[in] button_action The button action (press/release).
     */
    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }
    

    So, any clicking on Button 1 will place you inside this handler, and run the code inside.

    So too sum up, you need to make sure that the buttons are enabled, and either place the code you wish to execute inside the button event handler or remove it.

    - Andreas

  • Hey,

    thank you for the fast response. I forgot to mention that the Button I use is not Button1 it is Button 4. I initialised it in the button_init shown in the following code. I know that Button1 is for the handler, that is why I made a seperate initialisation with BUTTON4.

    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler}
        };
    		static app_button_cfg_t button[]=
    		{
    				{BUTTON_4,false,BUTTON_PULL,NULL}
    		};
    
    		
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
    		
    		APP_ERROR_CHECK(err_code);
    		
    		err_code	= app_button_init(button, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    }

  • Hi.

    I'm a bit unsure on what you tried to do in that code snippet.

    You have to use BSP_BUTTON_3, not BUTTON_4. And also use the button event handler, like this:

    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler},
            {BSP_BUTTON_3,false,BUTTON_PULL,button_event_handler}
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    }

    And add a case to the button event handler, like this:

    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
            case BSP_BUTTON_3:
                NRF_LOG_INFO("test");
                //DO SOMETHING
                //FOR EXAMPLE, START ADVERTISING
                advertising_start();
                NRF_LOG_INFO("Advertising Started");
                break;
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }

    Hope this helps.

    - Andreas

Reply
  • Hi.

    I'm a bit unsure on what you tried to do in that code snippet.

    You have to use BSP_BUTTON_3, not BUTTON_4. And also use the button event handler, like this:

    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler},
            {BSP_BUTTON_3,false,BUTTON_PULL,button_event_handler}
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    }

    And add a case to the button event handler, like this:

    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
            case BSP_BUTTON_3:
                NRF_LOG_INFO("test");
                //DO SOMETHING
                //FOR EXAMPLE, START ADVERTISING
                advertising_start();
                NRF_LOG_INFO("Advertising Started");
                break;
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }

    Hope this helps.

    - Andreas

Children
  • Hey,

    thank you for the response. I understand that my Button initialisation was wrong. But I still have some Problems/ things I haven't understood left:

    • I implemented your Code and it is not advertising. It is not even going in the handler for BSP_BUTTON_3. Can it be Because the Board hasn't started advertising?
    • How is the handler implemented? Is it like a software interrupt?
    • My version was/still is working. But only with the NRF_LOG_INFO("This makes it work"). Why just with the output?
  • Hi.

    I've been out of office this week, so sorry for the late reply.

    Moe said:
    I implemented your Code and it is not advertising. It is not even going in the handler for BSP_BUTTON_3. Can it be Because the Board hasn't started advertising?

     I added a if-sentence to the button event handler, I forgot that the button creates an event when it is pushed down and when you release the button, try this:

    /**@brief Function for handling events from the button handler module.
     *
     * @param[in] pin_no        The pin that the event applies to.
     * @param[in] button_action The button action (press/release).
     */
    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
            case BSP_BUTTON_3:
                if(button_action == 1)
                {
                  advertising_start();
                  NRF_LOG_INFO("Advertising Started");
                }
                break;
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }

    Note that you cannot start advertising if you are already advertising, what I mean is that if you advertise using advertising_handle_number_1, you cannot start a new advertising with the same advertising handle. You have to stop advertising if you want to reuse the same advertising handle.

     

    Moe said:
    How is the handler implemented? Is it like a software interrupt?

    Its a GPIOTE hardware interrupt which is implemented in app_button.c

    Moe said:
    My version was/still is working. But only with the NRF_LOG_INFO("This makes it work"). Why just with the output?

     I'm unsure what you mean here, could you elaborate?

    - Andreas

  • Hi,

    thank you for the response. I tried the changes.

     I added a if-sentence to the button event handler, I forgot that the button creates an event when it is pushed down and when you release the button, try this:

    I noticed that the handler isn't called if the Board is not connectet with an other Bluetooth Device. I tested the the it with the following code and It just worked when I connected an other Device. When there was no Device connected the handler was never called.

    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    	NRF_LOG_INFO("HELLO I'M A BUTTON HANDLER");
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
            case BSP_BUTTON_3:
                if(button_action == 1)
                {
                  //advertising_start();
                  NRF_LOG_INFO("Advertising Started");
                }
                break;
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }

    int main(void)
    {
        // Initialize.
        log_init();
        leds_init();
        timers_init();
        buttons_init();
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started.");
        advertising_start();
    
    		for (;;)
        {
    	        idle_state_handle();
        }
    }
     

     I'm unsure what you mean here, could you elaborate?

    I mean my first version is working.

    int main(void)
    {
        // Initialize.
        log_init();
        leds_init();
        timers_init();
        buttons_init();
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started.");
        advertising_start();
    
    
    	  int a=0;
        // Enter main loop.
        for (;;)
        {
    			if(a==0)
    			NRF_LOG_INFO("This makes it work");
    			
    			if(app_button_is_pushed(1)&&a==0)
    			{
    				a=1;
    				NRF_LOG_INFO("Advertising Started in the for loop");
    				advertising_start();
    			}
            idle_state_handle();
        }
    }

    But If I leave this

    NRF_LOG_INFO("This makes it work");

    out my version is not working eighter. My Question is: What does the NRF_LOG_INFO do to make it work?

  • Hi.

    I'm unsure why your handler does not work, it does not have to be connected to another board in order to work, have you done any other modifications to your code, or source files which are used in the example?

    My button handler works fine when i'm not connected, and when i'm connected.

    			if(a==0)
    			NRF_LOG_INFO("This makes it work");

    There problem could be that you don't use brackets ( { and } ) in your if-sentence.

    NRF_LOG_INFO shouldn't have any implications here.

    - Andreas

  • Hey,

    thank you for not giving up on me. I have the SDK as Zip-File. Unzipped it into a new Folder, and opend the ..\nRF5_SDK_15.2.0_9412b96\examples\ble_peripheral\ble_app_blinky\ project. Then I included the initialisation of the Buttons you gave me.

    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler},
            {BSP_BUTTON_3,false,BUTTON_PULL,button_event_handler}
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    }

    After this I implemented your handler-Function.

    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    	NRF_LOG_INFO("HELLO I'M A BUTTON HANDLER");
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
            case BSP_BUTTON_3:
                if(button_action == 1)
                {
                  //advertising_start();
                  NRF_LOG_INFO("Advertising Started");
                }
                break;
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }

    The rest of the Project is unchanged. I'm able to compile and flash the project with no errors to the nRF52832. When I press the Button nothing happens. It only calls the handler, when there is a device connected.

    There problem could be that you don't use brackets ( { and } ) in your if-sentence.

    It doesn't change if I use the brackets { } for the IF in my version or not.

    int main(void)
    {
        // Initialize.
        log_init();
        leds_init();
        timers_init();
        buttons_init();
        power_management_init();
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        // Start execution.
        NRF_LOG_INFO("Blinky example started.");
        advertising_start();
    
    
    	  int a=0;
        // Enter main loop.
        for (;;)
        {
    			if(a==0)
    			{
    				NRF_LOG_INFO("This makes it work");
    			}
    			if(app_button_is_pushed(1)&&a==0)
    			{
    				a=1;
    				NRF_LOG_INFO("Advertising Started in the for loop");
    				advertising_start();
    			}
            idle_state_handle();
        }
    }

    The button_init is the same initialisation you gave me and the one I'm using when I try to fix the problem with the handler.

    static void buttons_init(void)
    {
        ret_code_t err_code;
    
        //The array must be static because a pointer to it will be saved in the button handler module.
        static app_button_cfg_t buttons[] =
        {
            {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler},
            {BSP_BUTTON_3,false,BUTTON_PULL,button_event_handler}
        };
    
        err_code = app_button_init(buttons, ARRAY_SIZE(buttons),
                                   BUTTON_DETECTION_DELAY);
        APP_ERROR_CHECK(err_code);
    }

    the button_event_handler is unchanged from the original blinky example.

    static void button_event_handler(uint8_t pin_no, uint8_t button_action)
    {
        ret_code_t err_code;
    
        switch (pin_no)
        {
            case LEDBUTTON_BUTTON:
                NRF_LOG_INFO("Send button state change.");
                err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);
                if (err_code != NRF_SUCCESS &&
                    err_code != BLE_ERROR_INVALID_CONN_HANDLE &&
                    err_code != NRF_ERROR_INVALID_STATE &&
                    err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    
            default:
                APP_ERROR_HANDLER(pin_no);
                break;
        }
    }

    When there is an output in the main loop my version (shown in the 3 Code modifications above, (btw the rest of the project is unchanged) is working. When I remove the NRF_LOG_INFO it is not working. I have tried to use a loop to slower the whole main loop. I tought that maybe because it is called to often and to fast in a row there might be some buggs. But the delay loop didn't fixed the Problem only a NRF_LOG_INFO fixed it.

    -Moe

Related