Example "peripheral_nus" for nrf52840 Dongle - non-functional reconnect to "nrfConnect".

Hello. I used the "peripheral_nus" example for nrf52840 - everything goes as it should - I connect via bluetooth and the "nrfConnect - mobile" application receives the message "Hello World!" - it sends the message, but as soon as I disconnect from it, reconnecting is no longer possible - I have to disconnect the device from power (reset) to be able to connect again. Could someone advise me what I am missing or what is wrong? I used Visual Studio Code 1.121.0 - nRF Connect SDK v3.3.0.

Than you.

#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/services/nus.h>

#define DEVICE_NAME		CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN		(sizeof(DEVICE_NAME) - 1)

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

static const struct bt_data sd[] = {
	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_SRV_VAL),
};

static void notif_enabled(bool enabled, void *ctx)
{
	ARG_UNUSED(ctx);

	printk("%s() - %s\n", __func__, (enabled ? "Enabled" : "Disabled"));
}

static void received(struct bt_conn *conn, const void *data, uint16_t len, void *ctx)
{
	ARG_UNUSED(conn);
	ARG_UNUSED(ctx);

	printk("%s() - Len: %d, Message: %.*s\n", __func__, len, len, (char *)data);
}

struct bt_nus_cb nus_listener = {
	.notif_enabled = notif_enabled,
	.received = received,
};

int main(void)
{
        int err;

	printk("Sample - Bluetooth Peripheral NUS\n");

	err = bt_nus_cb_register(&nus_listener, NULL);
	if (err) {
		printk("Failed to register NUS callback: %d\n", err);
		return err;
	}

	err = bt_enable(NULL);
	if (err) {
		printk("Failed to enable bluetooth: %d\n", err);
		return err;
	}

	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
	if (err) {
		printk("Failed to start advertising: %d\n", err);
		return err;
	}

	printk("Initialization complete\n");

	while (true) {
		const char *hello_world = "Hello World!\n";

		k_sleep(K_SECONDS(3));

		err = bt_nus_send(NULL, hello_world, strlen(hello_world));
		printk("Data send - Result: %d\n", err); 

		if (err < 0 && (err != -EAGAIN) && (err != -ENOTCONN)) {
			return err;
		}
	}

        return 0;
}

Parents
  • Hi,

    You need to restart advertising after the disconnect. This is done in the samples in the recycled callback. I see this is not done in the peripheral_nus sample though, which is a minimal Zephyr sample. But it is done for instance in the Bluetooth peripheral_uart sample under nRF, which is the NSU sample Nordic supports.

    I have modified your sample adding the needed code to properly start advertising after disconnecting:

    #include <zephyr/kernel.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/services/nus.h>
    
    #define DEVICE_NAME CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
    
    static struct bt_conn *current_conn;
    static struct k_work adv_work;
    
    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_SRV_VAL),
    };
    
    static void adv_work_handler(struct k_work *work)
    {
    	int err;
    
    	ARG_UNUSED(work);
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    	if (err) {
    		printk("Failed to start advertising: %d\n", err);
    	}
    }
    
    static void advertising_start(void)
    {
    	k_work_submit(&adv_work);
    }
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err) {
    		printk("Connection failed: %u\n", err);
    		return;
    	}
    
    	current_conn = bt_conn_ref(conn);
    	printk("Connected\n");
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	ARG_UNUSED(conn);
    
    	printk("Disconnected: reason 0x%02x\n", reason);
    
    	if (current_conn) {
    		bt_conn_unref(current_conn);
    		current_conn = NULL;
    	}
    }
    
    static void recycled(void)
    {
    	printk("Connection recycled, restarting advertising\n");
    	advertising_start();
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.recycled = recycled,
    };
    
    static void notif_enabled(bool enabled, void *ctx)
    {
    	ARG_UNUSED(ctx);
    
    	printk("%s() - %s\n", __func__, (enabled ? "Enabled" : "Disabled"));
    }
    
    static void received(struct bt_conn *conn, const void *data, uint16_t len, void *ctx)
    {
    	ARG_UNUSED(conn);
    	ARG_UNUSED(ctx);
    
    	printk("%s() - Len: %d, Message: %.*s\n", __func__, len, len, (char *)data);
    }
    
    struct bt_nus_cb nus_listener = {
    	.notif_enabled = notif_enabled,
    	.received = received,
    };
    
    int main(void)
    {
    	int err;
    
    	printk("Sample - Bluetooth Peripheral NUS\n");
    
    	err = bt_nus_cb_register(&nus_listener, NULL);
    	if (err) {
    		printk("Failed to register NUS callback: %d\n", err);
    		return err;
    	}
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Failed to enable bluetooth: %d\n", err);
    		return err;
    	}
    
            k_work_init(&adv_work, adv_work_handler);
    	advertising_start();
    	printk("Initialization complete\n");
    
    	while (true) {
    	        const char *hello_world = "Hello World B!\n";
    
                    k_sleep(K_SECONDS(3));
    
    		err = bt_nus_send(NULL, hello_world, strlen(hello_world));
    		printk("Data send - Result: %d\n", err);
    
    		if (err < 0 && (err != -EAGAIN) && (err != -ENOTCONN)) {
    			return err;
    		}
    	}
    
    	return 0;
    }
    

    With this, reconnecting works as expected when I test on the nRF52840 Dongle.

Reply
  • Hi,

    You need to restart advertising after the disconnect. This is done in the samples in the recycled callback. I see this is not done in the peripheral_nus sample though, which is a minimal Zephyr sample. But it is done for instance in the Bluetooth peripheral_uart sample under nRF, which is the NSU sample Nordic supports.

    I have modified your sample adding the needed code to properly start advertising after disconnecting:

    #include <zephyr/kernel.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/services/nus.h>
    
    #define DEVICE_NAME CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
    
    static struct bt_conn *current_conn;
    static struct k_work adv_work;
    
    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = {
    	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_SRV_VAL),
    };
    
    static void adv_work_handler(struct k_work *work)
    {
    	int err;
    
    	ARG_UNUSED(work);
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    	if (err) {
    		printk("Failed to start advertising: %d\n", err);
    	}
    }
    
    static void advertising_start(void)
    {
    	k_work_submit(&adv_work);
    }
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err) {
    		printk("Connection failed: %u\n", err);
    		return;
    	}
    
    	current_conn = bt_conn_ref(conn);
    	printk("Connected\n");
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	ARG_UNUSED(conn);
    
    	printk("Disconnected: reason 0x%02x\n", reason);
    
    	if (current_conn) {
    		bt_conn_unref(current_conn);
    		current_conn = NULL;
    	}
    }
    
    static void recycled(void)
    {
    	printk("Connection recycled, restarting advertising\n");
    	advertising_start();
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.recycled = recycled,
    };
    
    static void notif_enabled(bool enabled, void *ctx)
    {
    	ARG_UNUSED(ctx);
    
    	printk("%s() - %s\n", __func__, (enabled ? "Enabled" : "Disabled"));
    }
    
    static void received(struct bt_conn *conn, const void *data, uint16_t len, void *ctx)
    {
    	ARG_UNUSED(conn);
    	ARG_UNUSED(ctx);
    
    	printk("%s() - Len: %d, Message: %.*s\n", __func__, len, len, (char *)data);
    }
    
    struct bt_nus_cb nus_listener = {
    	.notif_enabled = notif_enabled,
    	.received = received,
    };
    
    int main(void)
    {
    	int err;
    
    	printk("Sample - Bluetooth Peripheral NUS\n");
    
    	err = bt_nus_cb_register(&nus_listener, NULL);
    	if (err) {
    		printk("Failed to register NUS callback: %d\n", err);
    		return err;
    	}
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Failed to enable bluetooth: %d\n", err);
    		return err;
    	}
    
            k_work_init(&adv_work, adv_work_handler);
    	advertising_start();
    	printk("Initialization complete\n");
    
    	while (true) {
    	        const char *hello_world = "Hello World B!\n";
    
                    k_sleep(K_SECONDS(3));
    
    		err = bt_nus_send(NULL, hello_world, strlen(hello_world));
    		printk("Data send - Result: %d\n", err);
    
    		if (err < 0 && (err != -EAGAIN) && (err != -ENOTCONN)) {
    			return err;
    		}
    	}
    
    	return 0;
    }
    

    With this, reconnecting works as expected when I test on the nRF52840 Dongle.

Children
Related