This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Wake on any Event Low Power Mode Using a timed event

I am really new at working with Bluetooth and the various protocols contained within.

I am using SDK 17.0 and drivers 2.7.  I am working on a DK-52 board.

I am working with the HRM Demo.  In particular with the battery service timed event.  I came across the place in the code where the device will go in to sleep mode.  The comments say it should not come back until a button is pushed to wake it up or a reset / powerup occurs.

//---------------------------------------------------------------------------
/**@brief Function for putting the chip into sleep mode.
*
* @note This function will not return.
*/
//---------------------------------------------------------------------------
static void sleep_mode_enter(void)
{
ret_code_t err_code;

err_code = bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);

// Prepare wakeup buttons.
err_code = bsp_btn_ble_sleep_mode_prepare();
APP_ERROR_CHECK(err_code);

// Go to system-off mode (this function will not return; wakeup will cause a reset).
err_code = sd_power_system_off();
APP_ERROR_CHECK(err_code);
}

I never use the buttons on the DK board and from what I am seeing the battery service sends out battery information every couple of seconds.  After so many bursts of information, it appears the device somehow just resets itself and continues the process all over again.

If I wanted to keep the system on, full ram retention and wake on any event, which sd function would I need to call so that I could go into Ultra-low power mode and not lose the bonding information with the client app?  Is there a demo that demonstrates this type of low power mode that I could look at?

Is there a good method that I could use to determine if the client app was bonded with the device and not send battery level info but wait until a bond occurs and then send that battery info across so as not to waste much battery power as well?

Thanks in advance.

Allen Shea

  • Hello,

    it appears the device somehow just resets itself and continues the process all over again.

    What observations do you do that supports this scenario? Do you see anything in the log? Does it disconnect from the connected device? What do you connect to? A phone?

    Is there a good method that I could use to determine if the client app was bonded with the device and not send battery level info but wait until a bond occurs and then send that battery info across so as not to waste much battery power as well?

    Yes, but this isn't really saving much power. Bonding is used for encryption. If you wanted to, you could wait until the link is encrypted, but in reality this will save less than one battery message on average. It will not conserve much power.

    If I wanted to keep the system on, full ram retention and wake on any event, which sd function would I need to call so that I could go into Ultra-low power mode

    If you go to the "ultra low power mode", it basically means turning off the chip. The only way to wake it up from this state is by a button press. You can't use any timers in this system-off mode (which is why the comments say that you need a button press to wake up.). 

    System off mode, which is the lowest power mode you can use is typically used if you are advertising, but noone tries to connect. When the advertisements time out after 180s (configurable in your application), the device will go to system off mode. 

    Then there is system on mode, which is what we use when you are in a connection, advertising or scanning. If you look in your main() loop, you should see a sd_app_evt_wait(), which basically puts the device to sleep, but wake up on any event (timer, softdevice radio event, peripheral event or whatever you have set up). 

    So I am not completely sure what you are looking for (perhaps you are not so sure yourself). Do you see a current consumption that is too big for what you can tolerate? If so, what is the current consumption, and what current consumption do you need? Or are you concerned with security? Or are you curious about that the application seemingly resets? Did you try to monitor the log from the nRF? (UART log?) Does it say anything when the device resets?

    Best regards,

    Edvin

  • Hello Edvin,

    Thank you for the comments.  Here is some more information that might clarify what I am trying to accomplish and what I am seeing.


    Part of my goal is to make an educated guess on current consumption prior to making any development board changes and see if a small coin cell battery (30mAH) capacity will operate for an acceptable amount of time before having to be replaced.

    I believe I have the main objective of the task figured out right now but those few items about restart and transmits in advertising intermittently will definitely figure into the current consumption.

    My main goal is that when the app on the phone no longer detects the remote device, an alarm in the phone app will alert the person.

    --------------------------------------------------------------------
    NRF Log Output
    --------------------------------------------------------------------

    00.000: <info> app_timer: RTC: initialized.

    <info> app: BAS example started.

    <info> app: Erase bonds!

    <info> peer_manager_handler: All peers deleted.

    <info> app: Fast advertising.

    24.400: <info> app: Connected.

    <info> app: GATT ATT MTU on connection 0x0 changed to 247.

    26.261: <info> app: BLE_GAP_EVT_LESC_DHKEY_REQUEST

    <info> nrf_ble_lesc: Calling sd_ble_gap_lesc_dhkey_reply on conn_handle: 0

    27.586: <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Bonding

    <info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0 bond=0x1 lv4: 0 kdist_own:0x3 kdist_peer:0x2

    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Bonding data, action: Update

    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update

    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Local database, action: Update

    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Central address resolution, action: Update

    <info> app: Batt Lvl = 832 => 81 => 4

    31.972: <info> app: Batt Lvl = 829 => 81 => 4

    35.909: <info> app: Batt Lvl = 832 => 81 => 4

    39.981: <info> app: Batt Lvl = 829 => 81 => 4

    43.935: <info> app: Batt Lvl = 830 => 81 => 4

    47.973: <info> app: Batt Lvl = 828 => 81 => 4

    51.910: <info> app: Batt Lvl = 829 => 81 => 4

    55.327: <info> app: Fast advertising.

    <info> app: Disconnected, reason 19.

    --------------------------------------------------------------------
    Simple UART Log Output
    --------------------------------------------------------------------

    47:16.191: Disconnected, reason 19.
    47:44.435: BLE_GAP_EVT_AUTH_STATUS: status=0
    Disconnected, reason 22.

    49:32.163: óUART started. // This output occurs when a reset has occurred.

    Bonds deleted // I do this to keep from filling up and having issues connecting to rfConnect utility
    Starting Main Loop // Occurs right before going into Idle mode

    BLE_GAP_EVT_AUTH_STATUS: status=0 // Once connected then transmit Battery Level

    Batt Lvl = 828 => 81 => 4
    49:56.477: Batt Lvl = 829 => 81 => 4
    50:00.435: Batt Lvl = 829 => 81 => 4
    50:04.503: Batt Lvl = 828 => 81 => 4 = 4.068 sec.
    50:08.459: Batt Lvl = 828 => 81 => 4 = 3.956 sec.
    50:12.448: Batt Lvl = 828 => 81 => 4 = 3.989 sec.
    50:16.427: Batt Lvl = 828 => 81 => 4 = 3.979 sec.
    50:20.408: Batt Lvl = 829 => 81 => 4
    50:24.451: Batt Lvl = 830 => 81 => 4
    50:28.431: Batt Lvl = 830 => 81 => 4
    50:32.430: Batt Lvl = 827 => 81 => 4
    50:36.440: Batt Lvl = 829 => 81 => 4
    50:40.496: Batt Lvl = 830 => 81 => 4
    50:44.433: Batt Lvl = 830 => 81 => 4
    50:48.483: Batt Lvl = 829 => 81 => 4
    50:52.476: Batt Lvl = 829 => 81 => 4
    50:56.440: Batt Lvl = 829 => 81 => 4
    51:00.532: Batt Lvl = 829 => 81 => 4
    51:04.480: Batt Lvl = 830 => 81 => 4
    51:08.492: Batt Lvl = 830 => 81 => 4
    51:12.455: Batt Lvl = 832 => 81 => 4
    51:16.530: Batt Lvl = 830 => 81 => 4
    51:20.512: Batt Lvl = 829 => 81 => 4
    51:24.413: Batt Lvl = 829 => 81 => 4
    51:28.505: Batt Lvl = 830 => 81 => 4
    51:32.498: Batt Lvl = 828 => 81 => 4
    51:36.466: Batt Lvl = 828 => 81 => 4
    51:40.438: Batt Lvl = 827 => 81 => 4
    51:44.506: Batt Lvl = 830 => 81 => 4
    51:48.502: Batt Lvl = 829 => 81 => 4
    51:52.482: Batt Lvl = 829 => 81 => 4
    51:56.477: Batt Lvl = 830 => 81 => 4
    52:00.461: Batt Lvl = 830 => 81 => 4
    52:04.409: Batt Lvl = 827 => 81 => 4
    52:08.481: Batt Lvl = 827 => 81 => 4
    52:12.480: Batt Lvl = 830 => 81 => 4
    52:16.485: Batt Lvl = 830 => 81 => 4
    52:20.471: Batt Lvl = 830 => 81 => 4
    52:24.450: Batt Lvl = 829 => 81 => 4 = 3.979 sec.

    Disconnected, reason 19.

    55:24.961: óUART started. // This output occurs when a reset has occurred.
    Bonds deleted
    Starting Main Loop

    óUART started. // This output occurs when a reset has occurred.
    58:25.507: Bonds deleted
    Starting Main Loop

    óUART started. // This output occurs when a reset has occurred.
    01:01:25.772: Bonds deleted
    Starting Main Loop

    óUART started. // This output occurs when a reset has occurred.
    01:04:25.897: Bonds deleted
    Starting Main Loop

    óUART started. // This output occurs when a reset has occurred.
    01:07:26.042: Bonds deleted
    Starting Main Loop

    óUART started. // This output occurs when a reset has occurred.
    01:10:26.385: Bonds deleted
    Starting Main Loop

    --------------------------------------------------------------------

    The reason I show the Simple UART Log is because it shows the device restarting every 3 min. like you described before. If I turn on nRF Log this never shows up because of the code:

    //---------------------------------------------------------------------------
    /**@brief Function for handling the idle state (main loop).
    *
    * @details If there is no pending log operation, then sleep until next the next event occurs.
    */
    //---------------------------------------------------------------------------
    static void idle_state_handle(void)
    {
    ret_code_t err_code;

    err_code = nrf_ble_lesc_request_handler();

    APP_ERROR_CHECK(err_code);

    if (NRF_LOG_PROCESS() == false)
    {
    #ifdef dbg_Time_Idle_Dly

    bsp_board_led_on(3);

    #endif

    nrf_pwr_mgmt_run();

    #ifdef dbg_Time_Idle_Dly

    bsp_board_led_off(3);

    #endif
    }
    }


    --------------------------------------------------------------------

    My main loop cycle time is: 200ms active and 1.8 sec idle / sleep.

    --------------------------------------------------------------------

    When the unit apparently restarts, there is no difference with the main loop cycle on the O-scope that indicates the restart occurred. Is this something I should be concerned with?

    Since I am not encrypting anything, is there a better way to connect to the device rather than a bond or is that a necessary thing that has to be done? The reason I delete the bonds is because after so many times of changing the firmware a table filled up and I was no longer able to bond through nRFConnect utility. That is why I tell the unit to force delete the bonds on startup. Would it be better to only force delete the bond during debugging rather than all the time?

  • Hello Edvin,

    After some more testing, I am realizing that when the unit is connected to the nRFConnect utility app on the phone, I no longer seem to be going through the main Idle handler anymore.  Below is the code that I expected it to run while connected as well:

    //---------------------------------------------------------------------------
    /**@brief Function for handling the idle state (main loop).
    *
    * @details If there is no pending log operation, then sleep until next the next event occurs.
    */
    //---------------------------------------------------------------------------
    static void idle_state_handle(void)
    {
    ret_code_t err_code;

    err_code = nrf_ble_lesc_request_handler();

    APP_ERROR_CHECK(err_code);

    if (NRF_LOG_PROCESS() == false)
    {
    #ifdef dbg_Time_Idle_Dly

    bsp_board_led_on(3);

    #endif

    nrf_pwr_mgmt_run();

    #ifdef dbg_Time_Idle_Dly

    bsp_board_led_off(3);

    #endif
    }
    }

    It seems to only run this when not connected because it is advertising.  Once connected, it appears the full running of the device occurs until a disconnect and then it goes back into an idle advertising sleep mode of operation.

    Is it possible that sleep / idle mode can be accomplished during the timer event to go read the battery and then go into a low power mode like it does in the advertising mode to conserve more power but have the battery reporting timer control the low power mode?

    Thanks,

    Allen Shea

  • AllenS said:
    It seems to only run this when not connected because it is advertising.  Once connected, it appears the full running of the device occurs until a disconnect and then it goes back into an idle advertising sleep mode of operation.

    In the unmodified example, it reaches idle_state_handle() even if you are connected. 

    AllenS said:
    Is it possible that sleep / idle mode can be accomplished during the timer event to go read the battery and then go into a low power mode like it does in the advertising mode to conserve more power but have the battery reporting timer control the low power mode?

    I am a bit confused about your use of "low power mode". Can we please use the terms "system on mode" and "system off mode"?

    So you want to be connected, use a timer to generate the battery reading and send it over BLE, and be in system on mode. Is that correct?

  • When I spoke of low power mode, I was referring to what is happening during the advertising mode cycling between 1.8 sec off and 200 ms. active times.  On page 77 of the Nordic Datasheet nRF52832 Product Spec v1.4, under the heading Current consumption: Ultra-low power, I was trying to achieve the mode of ultra low power described as: System ON, Full RAM retention, Wake on any event because the consumption amount is 1.5 uA.  When you come out of Ultra low power mode and have already connected with the phone app, the battery reporting timer service would send out the updated battery status and then go back into the previously described Ultra low power mode until the next timed interval occurs to transmit another updated battery status.

    Once the phone app disconnects, then the remote device would need to go back into the advertising cycling mode as I described earlier.

    To answer your question, I do want to be in a system on mode because the design I am working with will not have a physical input that I can use to wake up the remote device from a system off mode so it needs to be a system on mode as I described before.

    I will look around and see if I can identify where the idle mode is occurring once the remote device has connected to the phone app.  Maybe there is a different handler being specified once the connection has occurred that I have not noticed yet.  If you have any suggestions on how to track that down, I am open to suggestions.

Related