Only BLE sleep and wake-up sequence control in a nRF52832, while CPU running in normal mode

Hello,

For the development of a new device I am using a custom hardware with a nRF52832 chip. I am working over the nRF5_SDK_17.1.0 using the SES IDE environment.

As a controller, the nRF52832 manages a state machine for acquiring some data from an SPI sensor and storing this data in a SPI flash. I only need to connect the device by BLE during some specific moments.

So, for increasing the autonomy of the small battery the device has, I would need that the CPU could run in normal mode while the BLE should be sleep. And wake-up the BLE in a controlled way in those specific moments. And after having transmitted the information, I should put the BLE services to sleep again.

Do you know of any example that could help me for managing this?

Thank you very much in advance.

Regards,

Joel

Parents
  • Hi Joel,

    In practice, BLE (in some form) will be in use when scanning, advertising or being in one or more BLE connections. If you disconnect any connections, and stop advertising and scanning (if you ever to that), then BLE will not be in use, and will not contribute to the current consumption.

    Exactly how to do this is application specific so I don't have any good examples, but generally it mens that if you are done with BLE, call the API's that stop it. If in a connection, call sd_ble_gap_disconnect(). And if advertising, call sd_ble_gap_adv_start(). And so on. And when you need to use BLE, start these tasks again (in the same way as you started originally, but without the configuration step). For instance, if using the advertising module, call ble_advertising_start() to start advertising.

    Einar

  • Hi Einar,

    Thank you for your answer.

    Is there no specific function for putting BLE in sleep mode? Does the nRF52832 put BLE in sleep mode automatically?

    Best Regards,

    Joel Invers

  • Hi Joel,

    No, there is no specific function for putting BLE in sleep mode. The nRF itself, will normally enter low power system off mode when there is nothing to be done. This effectively means that the CPU is sleeping waiting for interrupt. This happens by a call to sd_app_evt_wait() in the main loop, either directly, or via some library. For the BLE stack (SoftDevice), this will wake up on RTC interrupts when there is stuff to do, but when configured to do nothing it will never wake the CPU (with one exception, which is regular calibration of the LFRC if not using an external 32.768 kHz crystal).

    PS: You may find Optimizing Power on nRF52 Designs useful.

  • Hi Einar,

    Thank you for your proposal. I see it interesting.

    So the CPU may be running in normal mode, but if the BLE services are stopped or disconnected we have to understand that the BLE part of the SoC will not be contributing to the current consumption. This is something I will have to test on my final hardware.

    Regards,
    Joel

  • Hi Joel,

    Yes, that is right. Bluetooth is a high level feature, and the stack use may different resources on the chip (the most important being the radio, CPU, RNG, CCM, RTC, TIMER, LF and HF clocks). However, we make low power designs, and the stack is very carefully tailored to be as low power as possible, and will only contribute to current consumption when needed. In idle, the stack keeps the LF clock and an RTC active, for time keeping, but that is all, and with that, the idle current consumption is typically about 2 uA. You can experiment with the online power profiler to see the current consumption related to BLE in different use cases and with different configurations.

Reply
  • Hi Joel,

    Yes, that is right. Bluetooth is a high level feature, and the stack use may different resources on the chip (the most important being the radio, CPU, RNG, CCM, RTC, TIMER, LF and HF clocks). However, we make low power designs, and the stack is very carefully tailored to be as low power as possible, and will only contribute to current consumption when needed. In idle, the stack keeps the LF clock and an RTC active, for time keeping, but that is all, and with that, the idle current consumption is typically about 2 uA. You can experiment with the online power profiler to see the current consumption related to BLE in different use cases and with different configurations.

Children
  • Hi Einar,

    Thank you for your answer. I will check it.

    Regards,

    Joel

  • Hello Einar,

    At the beginning of the main() function I call the next initializations:

        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
        printf("\r\nUART started.\r\n");
        NRF_LOG_INFO("Debug logging for UART over RTT started.");
        advertising_start();
        ble_gap_addr_t my_addr;
        err_code = sd_ble_gap_addr_get(&my_addr);
        APP_ERROR_CHECK(err_code);
        NRF_LOG_INFO("addr %02x:%02x:%02x:%02x:%02x:%02x", my_addr.addr[0],
                                                          my_addr.addr[1],
                                                          my_addr.addr[2],
                                                          my_addr.addr[3],
                                                          my_addr.addr[4],
                                                          my_addr.addr[5]);    

    In the services_init() function I initiate the NUS and the DFU services:

    static void services_init(void)
    {
        uint32_t           err_code;
        ble_nus_init_t     nus_init;
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize NUS.
        memset(&nus_init, 0, sizeof(nus_init));
    
        nus_init.data_handler = nus_data_handler;
    
        err_code = ble_nus_init(&m_nus, &nus_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize the DFU service
        ble_dfu_buttonless_init_t dfus_init =
        {
            .evt_handler =  ble_dfu_buttonless_evt_handler
        };
        err_code = ble_dfu_buttonless_init(&dfus_init);
        APP_ERROR_CHECK(err_code);
    
    }
    

    For selectively stopping all these tasks and stop all the BLE tasks (for maximum consumption reduction) what would be the best way/,method/codesequence that you would suggest to use?

    For reset them again I understand i should reinitiate them according to the same code I have shared. Is this ok?

    Thank you very much in advance.

    Regards,

    Joel

  • Hi Joel,

    jinvers said:
    For selectively stopping all these tasks and stop all the BLE tasks (for maximum consumption reduction) what would be the best way/,method/codesequence that you would suggest to use?

    There is no need to uninitialize anything Bluetooth related, but you should stop advertising, scanning (if relevant) etc if needed, or reduce the advertising interval etc if needed. This may not be as important as you could think, as the Bluetooth stack itself will not significantly contribute to the current consumption except during advertising events or connection events (or in scan windows). That is highly power optimized. You can see how this works on the current consumption by playing wth the online power profiler.

    jinvers said:
    For reset them again I understand i should reinitiate them according to the same code I have shared. Is this ok?

    Yes. For the other libraries etc. you use, it varies both on what you do and how you use it. Only NUS will not cause any issues, as that is just bluetooth. But do you also use UART? And is that always enabled? If so, the current consumption will be significant. So you should disable UART when you don't need it, and re-enable when you do. And logging you should disable for your production builds, as logging over UART will keep a UART instance the HW clock always running. 

  • Hi Einar,

    Yes. For the other libraries etc. you use, it varies both on what you do and how you use it. Only NUS will not cause any issues, as that is just bluetooth. But do you also use UART? And is that always enabled? If so, the current consumption will be significant. So you should disable UART when you don't need it, and re-enable when you do. And logging you should disable for your production builds, as logging over UART will keep a UART instance the HW clock always running. 

    I have not initialized the UART, but I still have the NRF_LOG_INFO messages and the logs are still enabled in the sdk_config.h file.

    Regards,

    Joel

  • I see. Then I would expect that you should get a low power consumption, comparable with what you see in the online power profiler. Have you checked to see if that is the case?

Related