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

Proper way to start/stop advertising?

It seems like this should be a simple thing, but I can't find an example of it, and nothing I've read here seems to help.

I want my app to come up in general advertising mode and stay there, forever, until certain things happen. Then I want it to shut down to a reasonably low-power state (nothing running but timers) until a button is pressed, at which time it will wake up and start advertising again, and then stop again, etc.

But when I call sd_ble_gap_adv_stop(), it returns a bad state error if it doesn't happen to be advertising at the moment (I assume that means between intervals), but if I ignore that error the program then fails with a timer memory error (trying to do an m_evt_schedule_func(), which I assume is the next advertisement).

I guess what I really want is advertising always on, but in "IDLE" mode sometimes. But I don't see any way to do that with softdevice calls. Can sd_ble_gap_adv_start() be called more than once with different parameters, maybe? Can I shutdown and restart the whole softdevice?

My startup code (using SDK 12.1) is:

void advertising_start()
{
    ble_gap_conn_sec_mode_t         sec_mode;
    ble_gap_conn_params_t           gap_conn_params = {
        .min_conn_interval = MIN_CONN_INTERVAL,
        .max_conn_interval = MAX_CONN_INTERVAL,
        .slave_latency = SLAVE_LATENCY,
        .conn_sup_timeout = CONN_SUP_TIMEOUT
    };
    ble_advdata_t                   adv_data = {
	    .name_type = BLE_ADVDATA_FULL_NAME,
	    .include_appearance = false,
	    .flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE
    };
    static ble_gap_adv_params_t     adv_params = {
	    .type = BLE_GAP_ADV_TYPE_ADV_IND,
	    .p_peer_addr = NULL,
	    .fp = BLE_GAP_ADV_FP_ANY,
	    .interval = APP_ADV_INTERVAL, // 100 ms
	    .timeout = 0
    };

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

    APP_ERROR_CHECK(sd_ble_gap_device_name_set(&sec_mode,
				      (const uint8_t *)P.bt.device_name,
				      strlen(P.bt.device_name)));

    APP_ERROR_CHECK(sd_ble_gap_ppcp_set(&gap_conn_params));
	APP_ERROR_CHECK(ble_advdata_set(&adv_data, NULL));
	APP_ERROR_CHECK(sd_ble_gap_adv_start(&adv_params));
}
  • Hi,

    If you get NRF_ERROR_INVALID_STATE when calling sd_ble_gap_adv_stop(), it usually means you are not advertising. You will not get this error if you are "between intervals", you will still be in the advertising state. Where are calling sd_ble_gap_adv_stop()? Most of the BLE peripheral examples in the SDK is setup to advertise in 180s and then stop until button 1 is pressed. You can disable this timeout by setting APP_ADV_TIMEOUT_IN_SECONDS to 0. You should easily be able to change the code to stop/start advertising on some other event than the timeot/button. Notice that the device is also going to sleep while advertising. Have a look at the call to power_manage() in the BLE examples.

    Best regards,

    Jørgen

  • I'm basing my code on ble_app_uart, but it just advertises once for 180 seconds and then powers down, restarting on the button press. I don't want to shut down, I just want to stop advertising, shut off my display, etc. I tried another tack of just letting it go to IDLE after its timeout, then restarting advertising. That works, but if I don't restart I get a timer crash. If try sd_ble_gap_adv_stop() I get an INVALID_STATE error and then a timer crash. I don't want to shut down, I just want it to shut up.

  • Looks like all the samples do the same thing: on getting the BLE_ADV_EVT_IDLE, they shut down completely. I can't find any example where they continue without advertising. I wouldn't mind shutting down the whole Bluetooth stack if I could restart it.

  • The device is not shut down completely, it is put into system off sleep mode. A wakeup from this mode will trigger a reset. You can avoid putting the device into system off mode by removing the call to sleep_mode_enter() on the BLE_ADV_EVT_IDLE event. You can disable the softdevice by calling softdevice_handler_sd_disable(), but make sure you are not advertising or in a connection when calling this. Notice that you will have to initialize the softdevice and all advertising settings before staring advertising again. Also, make sure you are not calling any softdevice functions if you disable the softdevice. Softdevice functions have a sd_ prefix.

  • In SDK 15, if you are using a template derived project, you should use the following statement with the parameter to stop advertising:

    sd_ble_gap_adv_stop(m_advertising.adv_handle);

Related