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

Periodic advertisement when APP_ADV_DURATION expires

Hi,

I am using ble_app_uart example for peripheral device and it will be powered by a 3.7 V battery. I need to use battery as long as possible. So I decided to make peripheral device advertise periodically.

Since I need to use app_timer, System ON sleep mode works for me. I know that device doesn't advertise when APP_ADV_DURATION expires (assume it is not 0).  I tried to restart advertise after APP_ADV_DURATION which triggers BLE_ADV_EVT_IDLE event. Also I disabled sleep_mode_enter() function in BLE_ADV_EVT_IDLE since it will put device in System OFF sleep mode.

My timeout handler is like this:

static void single_shot_timer_handler(void * p_context)
{
 uint32_t err_code;
 
 err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); 
 APP_ERROR_CHECK(err_code);
}



And I wanted to start timer in BLE_ADV_EVT_IDLE event like this:

switch (ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
            NRF_LOG_INFO("adv fast");
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;
        case BLE_ADV_EVT_IDLE:
            NRF_LOG_INFO("idle");                        
            err_code = app_timer_start(m_single_shot_timer_id, APP_TIMER_TICKS(20000), NULL);
            APP_ERROR_CHECK(err_code);
            //sleep_mode_enter();
            break;

I just wanted to advertise for 10 seconds and make it sleep for 20 seconds. I expected timer to start 20 seconds after BLE_ADV_EVT_IDLE. However, device advertises all the time. I mean when APP_ADV_DURATION expires, it doesn't stop advertising.

By the way APP_ADV_DURATION macro is 1000. And I use SDK 16

Could you please help me about it ? I will be very appreciated if you give me a suggestion.

Best Regards

Parents
  • Hi,

    Have you debugged the application to see if the BLE_ADV_EVT_IDLE event ever is generated?

    Is the APP_ADV_DURATION macro used in the code to set the timeout? How is the advertising configured? Are you using ble_advertising library?

    If you can upload the full project, it will be much easier to check what is going on.

    Best regards,
    Jørgen

  • It looks like the UART is causing the high current. I'm not sure if you need it when the device is not connected, but I could reduce the sleep current by adding this to the BLE_ADV_EVT_IDLE event:

    app_uart_close();
    *(volatile uint32_t *)0x40002FFC = 0;
    *(volatile uint32_t *)0x40002FFC;
    *(volatile uint32_t *)0x40002FFC = 1;

    And then reinitialize it in the timer_handler:

    uart_init();

    I then see about 6 uA average current during sleep:

  • Thank you Jørgen, it works now !

    But I thought that the peripheral device will be in BLE_ADV_EVT_IDLE event even when it is connected to a central device nearby. It doesn't disconnect when APP_ADV_DURATION expires. I don't want it connected to central device continuously because I am planning to send data during a connection then make it sleep.

    So could you give me a suggestion about that ? Do I have to create another timer to end connection after a time duration (for example after 10 seconds like I did before) so that device will sleep again ?

  • The BLE_ADV_EVT_IDLE is only valid for the advertising role, it does not relate to connections (apart from the fact that a connection can only be established when the device is advertising). When a connection is established, the advertising will have to be restarted by the application. If a connection is established, you have to explicitly disconnect on one of the sides for the link to disconnect. If you want to disconnect at a specific time after the connection, you can do that with another timer. If you will transfer some data when a device connects, it may be simpler to do the disconnect once the data transfer is completed.

  • Thanks for the advice. I found out that sd_ble_gap_disconnect() function is used to disconnect. I executed this function on peripheral side after ble_nus_data_send returned 0x0. Whenever disconnection happens, it connects again. But, I want to keep disconnection for a while. I mean after data transmission, I don't want it to connect immediately since my overall purpose is to reduce power consumption. I made a research in forum, but I couldn't find the solution. Do you have any suggestion about that ? 

Reply
  • Thanks for the advice. I found out that sd_ble_gap_disconnect() function is used to disconnect. I executed this function on peripheral side after ble_nus_data_send returned 0x0. Whenever disconnection happens, it connects again. But, I want to keep disconnection for a while. I mean after data transmission, I don't want it to connect immediately since my overall purpose is to reduce power consumption. I made a research in forum, but I couldn't find the solution. Do you have any suggestion about that ? 

Children
  • There is no way for the peripheral side to prevent a central for making a connection to the device when it is advertising, but if you have control over both sides of the link, you can tell the central to not reconnecting to the peer it has recently been connected to. If you store the address of connected devices for a period of time that you do not want it to reconnect, you can check this list before initiating a connection. The other alternative is to stop advertising on the peripheral after the disconnect.

  • I will try your first idea. The second way works by the way. Now, peripheral device keeps disconnection for a period by using another timer.

    Lastly, I have 2 more questions:

    1. You said that the average current during sleep is about 6 uA. Sometimes the current is around 9 uA - 15 uA momentarily. What does cause that ?

    2. Is this average 6 uA current normal during sleep ? I mean that can this be more reduced ?

Related