Mutli role in NRF connect, Advertising while connected

Hello,

I need to use muti role in NRF connect, to continue advertising when one connection is active.

I can find some topics about it using legacy sofdevices, but did not fined how to do in NRF Connect.

Thanks,

BR

Johanan

Parents
  • I found the sample multiple_adv_sets and it builds OK and working. Now I am trying to understand how to implement in my project.

    I can see what it is doing by sending to types of advertising. This is not optimal as it increases the power consumption. I understand correctly, once a connection is started, the advertising stops. So is it possible to start the 2nd advertising only when connected?

    My system will be a central unit which scans most of the time, and sensors that will advertise most of the time. However, the sensor needs to be connectable for configuration and some info. While connected, the sensor needs to continue advertising so the cental unit can get the sensor state. On the other hand, the central unit needs also to be connectable, and keep scanning when connection is active.

    The connection is used only when someone needs to get some info, and most of the time the central unit will be scanning (no power limit on central), and sensors will be advertising. I think that adding another advertisement set will reduce battery life of the sensor,

    Please advise.

    Thanks

    Johanan

  • Hello Johanan,

    It is indeed possible to resume advertising after connecting. It is even easier if you intend to use the same advertising set as you were originally using.

    All you need to do is to start advertising in the connected event. If you intend to use the same advertising set (which is connectable, I assume), you just need to add this to your prj.conf:

    CONFIG_BT_MAX_CONN=2

    This needs to be set in order to advertise with a connectable advertising set while you are already in a connection because you are "risking" that something else tries to connect as well. 

    Alternatively, you can start your second advertising using:

    err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad), sd,
    			      ARRAY_SIZE(sd));

    instead of

    err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
    			      ARRAY_SIZE(sd));

    I don't remember if you need to increase CONFIG_BT_MAX_CONN in this case. You can test it. In that case, you would need to stop this advertising set in the disconnected event, and restart your normal, connectable advertising set, if you want devices to be able to connect to it again.

    If I were you, I would just set CONFIG_BT_MAX_CONN to 2, and just disconnect the second connection if you are already connected to one device, and make sure that you start advertising again, but you would need to consider whether this would be a typical use case or not.

    Best regards,

    Edvin

  • I added  CONFIG_BT_MAX_CONN=2 , with no other change in code, but it does not work. It stops advertising when connected.

    I also tried the alternative  but it also fail:

    void on_connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err) {
    		LOG_ERR("Connection error %d", err);
    		return;
    	}
    	LOG_INF("Connected");
    	my_conn = bt_conn_ref(conn);
    	isConnected = true;
    	adv_param->options = BT_LE_ADV_NCONN;
    	err = bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad), NULL, 0); 
    	if (err) {
    		printk("Failed to start advertising when Connected (err %d)\n", err);
    		return;
    	}
    	printk("Advertising while Connected!!\n");
    }

    What am I missing here?

    Thanks

Reply
  • I added  CONFIG_BT_MAX_CONN=2 , with no other change in code, but it does not work. It stops advertising when connected.

    I also tried the alternative  but it also fail:

    void on_connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err) {
    		LOG_ERR("Connection error %d", err);
    		return;
    	}
    	LOG_INF("Connected");
    	my_conn = bt_conn_ref(conn);
    	isConnected = true;
    	adv_param->options = BT_LE_ADV_NCONN;
    	err = bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad), NULL, 0); 
    	if (err) {
    		printk("Failed to start advertising when Connected (err %d)\n", err);
    		return;
    	}
    	printk("Advertising while Connected!!\n");
    }

    What am I missing here?

    Thanks

Children
  • Did you try this:

    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
        int ret;
    
    	if (err) {
    		LOG_ERR("Connection failed (err %u)", err);
    		return;
    	}
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	LOG_INF("Connected %s", addr);
    
    	current_conn = bt_conn_ref(conn);
    
    
    	dk_set_led_on(CON_STATUS_LED);
    
        ret = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
    	                      ARRAY_SIZE(sd));
    	if (ret) {
    		printk("Failed to start advertising when Connected (ret %d)\n", ret);
    		return;
    	}
    }

    That works on my end. It also works if I replace BT_LE_ADV_CONN with BT_LE_ADV_NCONN.

    I can connect to it, and scan for it using another phone, and still see it's advertisements. 

    If it doesn't work on your end, what do you observe? Doe the log say "Failed to start advertising when connected? What is the reason (err)? And what does your adv_param look like? Where is it declared/set?

    BR,

    Edvin

  • Hi Edvin

    I trayed everything I could think of but can't get it to work.

    I sent you the project in private msg, I wonder if you can take a look at the main.c, and find my mistake.

    Thanks,

    Johanan 

  • Hello,

    I tried, but it failed in your state machine.

    Can you just try this:

    /* Callbacks */
    void on_connected(struct bt_conn *conn, uint8_t err)
    {
        int ret;
    	char addr[BT_ADDR_LE_STR_LEN];
    	if (err) {
    		LOG_ERR("Connection error %d", err);
    		return;
    	}
    	LOG_INF("Connected");
    	my_conn = bt_conn_ref(conn);
    	newConState = connected;
    	
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	LOG_INF("Connected %s", addr);
    
        ret = bt_le_adv_start(adv_param,
                              ad,
                              ARRAY_SIZE(ad),
                              NULL,
                              0);
        LOG_INF("connected - adv %d", ret);
    
    }

    Do you need to have CONFIG_BT_CENTRAL=y? It seems like this is what is causing the issues. However, I don't know exactly why. I would need to investigate further.

    Best regards,

    Edvin

  • Our Bluetooth stack team came to the rescue.

    The config you need to add is this one:

    https://github.com/nrfconnect/sdk-nrf/blob/main/subsys/bluetooth/controller/Kconfig#L110

    CONFIG_BT_CTLR_SDC_PERIPHERAL_COUNT=2

    and your 

    CONFIG_BT_MAX_CONN needs to be at least 3.

    That should do it.

    Best regards,

    Edvin

  • Hi,

    That state machine was just a crude attempt to restart advertising outside the on_connect() function.

    I removed it, and revert to the straightforward simple on_connect().

    The problem, as you stated was this:

    CONFIG_BT_CENTRAL=y

    which is not really needed. I removed it and all working as expected.

    So, I assume the last answer applies if one needs CENTRAL as well (which I might need in developing the next project: a central unit for these sensors, that can also be connected also to a mobile app)

    Thanks again for your support. 

    BR

    Johanan

Related