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

NRF52832: How to properly enable/disable Bluetooth multiple times?

Hello everyone,

is there an example that demonstrates how to turn off and on the Bluetooth completely multiple times in the application?

I need really low consumption (tens of microamperes) and the only way I can do that is to invoke the sd_softdevice_disable() API. However, at a later time I cannot init the Bluetooth correctly.

Here is my code (based on the ble_peripheral_uart example from nRF5_SDK_17.0.2_d674dde, s132, nRF52832-CIAA(build code: E1) 512kB Flash, 64kB RAM):

/**@brief Function for the SoftDevice initialization.
 *
 * @details This function initializes the SoftDevice and the BLE event interrupt.
 */
static void ble_stack_init(uint32_t enable_request)
{
    ret_code_t err_code;

    if(enable_request){
    	err_code = nrf_sdh_enable_request();
    	APP_ERROR_CHECK(err_code);
    }

    // Configure the BLE stack using the default settings.
    // Fetch the start address of the application RAM.
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    // Enable BLE stack.
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}

void user_bluetooth_init(void){
	ret_code_t err;
	const nrf_clock_lf_cfg_t sd_lf_config =	{
			.source       = NRF_SDH_CLOCK_LF_SRC,
			.rc_ctiv      = NRF_SDH_CLOCK_LF_RC_CTIV,
			.rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
			.accuracy     = NRF_SDH_CLOCK_LF_ACCURACY
	};
	static uint32_t first_time = 1; 

	if(!ble_enabled){
		ble_enabled = 1;
		central_connected = 0;

		if(first_time){
			timers_init();
			ble_stack_init(first_time);
			gap_params_init();
			gatt_init();
			services_init();
			advertising_init();
			conn_params_init();
			first_time = 0;
		}
		else{
			err = sd_softdevice_enable(&sd_lf_config, fault_handler);
			APP_ERROR_CHECK(err);
			
			// Configure the BLE stack using the default settings.
			// Fetch the start address of the application RAM.
			uint32_t ram_start = 0;
			err = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
			APP_ERROR_CHECK(err);

			// Enable BLE stack.
			err = nrf_sdh_ble_enable(&ram_start);
			APP_ERROR_CHECK(err);
		}

		user_bluetooth_advertising_start();
	}
}

void user_bluetooth_deinit(void){
	if(ble_enabled){
		ble_enabled = 0;
		sd_softdevice_disable();
		nrf_delay_ms(1000);
	}
}

int main(void){
	DEBUGOUT("on\n");
	user_bluetooth_init();
	
	nrf_delay_ms(5000);
	
	DEBUGOUT("off\n");
	user_bluetooth_deinit();
	
	nrf_delay_ms(5000);
	
	DEBUGOUT("on\n");
	user_bluetooth_init();
	
	nrf_delay_ms(5000);

	while(1){ }
}

If I try to connect with nRF Toolbox on the second turn on (I can see that the device is advertising correctly), the nRF Toolbox displays an error: "The device does not have required services."

Thank you in advance for your time!

Regards,

L. B.

Parents
  • Hello,

    The Softdevice does not increase the sleep current, so there shouldn't be any point in disabling it. I'm not seeing calls to any sleep function in the code you posted either.

    Have you tried to measure the current with original ble_app_uart example after commenting the UART init? That should give you comparable results to what our online power profiler gives if you input the same set of paramaters (regulator setting, and advertising interval).

    If I try to connect with nRF Toolbox on the second turn on (I can see that the device is advertising correctly), the nRF Toolbox displays an error: "The device does not have required services."

     All Softdevice configurations including the attribute table gets cleared when you disable the Softdevice.

    Best regards,

    Vidar

  • Yes, indeed, the code I've pasted is modified to isolate the problem, so I haven't shown the functions. Yes, I have measured the current of the ble_uart but I needed even better consumption.

    So, I figured out how to fix the problem:

    void user_bluetooth_init(void){
    	ret_code_t err;
    	const nrf_clock_lf_cfg_t sd_lf_config =	{
    			.source       = NRF_SDH_CLOCK_LF_SRC,
    			.rc_ctiv      = NRF_SDH_CLOCK_LF_RC_CTIV,
    			.rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
    			.accuracy     = NRF_SDH_CLOCK_LF_ACCURACY
    	};
    	static uint32_t first_time = 1;
    
    	if(!ble_enabled){
    		ble_enabled = 1;
    		central_connected = 0;
    
    		if(first_time){
    			timers_init();
    			ble_stack_init(first_time);
    			gap_params_init();
    			gatt_init();
    			services_init();
    			advertising_init();
    			conn_params_init();
    			first_time = 0;
    		}
    		else{
    			err = sd_softdevice_enable(&sd_lf_config, fault_handler);
    			APP_ERROR_CHECK(err);
    
    			// Configure the BLE stack using the default settings.
    			// Fetch the start address of the application RAM.
    			uint32_t ram_start = 0;
    			err = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
    			APP_ERROR_CHECK(err);
    
    			// Enable BLE stack.
    			err = nrf_sdh_ble_enable(&ram_start);
    			APP_ERROR_CHECK(err);
    
                //These have to be added ...
                //Do not use error checking because it will crash
    		    ble_nus_init_t nus_init;
    		    nrf_ble_qwr_init_t qwr_init = {0};
    		    qwr_init.error_handler = nrf_qwr_error_handler;
    		    nrf_ble_qwr_init(&m_qwr, &qwr_init);
    		    memset(&nus_init, 0, sizeof(nus_init));
    		    nus_init.data_handler = nus_data_handler;
    		    ble_nus_init(&m_nus, &nus_init);
    		}
    
    		user_bluetooth_advertising_start();
    	}
    }

    Regards,

    L. B.

  • You can also call "advertising stop" if the goal is to temporarly disable BLE. What's the wake-up source to make the device start advertising again? Maybe you can reduce th current consumption even further by entering System OFF mode.

Reply Children
Related