Communicate two microcontrollers via BLE

Hello,

I'm using a nRF52 DK to test BLE communication with another microcontroller. What I need to test is the nRF52 pairing with another brand microcontroller, send a data stream and close the connection.

Could you please tell me which example from the Bluetooth samples list I can use for starting?

Thanks for your attention.

Regards,

Parents
  • Hello ,

    Thank you very much. I've reviewed this example and it is supposed to connect with the first device with an strong signal. Is there a way to force the board to connect with the device with a given MAC address?

  • Below the main.c file:

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *  @brief Nordic UART Service Client sample
     */
    
    #include <errno.h>
    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/sys/printk.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    
    #include <bluetooth/services/nus.h>
    #include <bluetooth/services/nus_client.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    
    #include <zephyr/settings/settings.h>
    
    #include <zephyr/drivers/uart.h>
    
    #include <zephyr/logging/log.h>
    
    #define LOG_MODULE_NAME central_uart
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    /* UART payload buffer element size. */
    #define UART_BUF_SIZE 20
    
    #define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
    #define KEY_PASSKEY_REJECT DK_BTN2_MSK
    
    #define NUS_WRITE_TIMEOUT K_MSEC(150)
    #define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
    #define UART_RX_TIMEOUT 50
    
    static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
    static struct k_work_delayable uart_work;
    
    K_SEM_DEFINE(nus_write_sem, 0, 1);
    
    struct uart_data_t {
    	void *fifo_reserved;
    	uint8_t  data[UART_BUF_SIZE];
    	uint16_t len;
    };
    
    static K_FIFO_DEFINE(fifo_uart_tx_data);
    static K_FIFO_DEFINE(fifo_uart_rx_data);
    
    static struct bt_conn *default_conn;
    static struct bt_nus_client nus_client;
    
    #if 1
    static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
    			 struct net_buf_simple *ad)
    {
    	char addr_str[BT_ADDR_LE_STR_LEN];
    	char addr_str_tmp[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	printk("Device found\n");
    	bt_addr_le_to_str((addr), addr_str_tmp, sizeof(addr_str_tmp));
    	printk("MAC: %s found\n", addr_str_tmp);
    
    	if (default_conn) {
    		return;
    	}
    
    	/* We're only interested in connectable events */
    	if (type != BT_GAP_ADV_TYPE_ADV_IND &&
    	    type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
    		return;
    	}
    
    	bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
    	printk("Device found: %s (RSSI %d)\n", addr_str, rssi);
    
    	/* connect only to devices in close proximity */
    	if (rssi < -70) {
    		return;
    	}
    
    	if (bt_le_scan_stop()) {
    		return;
    	}
    
    	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
    				BT_LE_CONN_PARAM_DEFAULT, &default_conn);
    	if (err) {
    		printk("Create conn to %s failed (%u)\n", addr_str, err);
    		start_scan();
    	}
    }
    
    
    #endif
    
    static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
    					const uint8_t *const data, uint16_t len)
    {
    	ARG_UNUSED(nus);
    
    	struct uart_data_t *buf;
    
    	/* Retrieve buffer context. */
    	buf = CONTAINER_OF(data, struct uart_data_t, data);
    	k_free(buf);
    
    	k_sem_give(&nus_write_sem);
    
    	if (err) {
    		LOG_WRN("ATT error code: 0x%02X", err);
    	}
    }
    
    static uint8_t ble_data_received(struct bt_nus_client *nus,
    						const uint8_t *data, uint16_t len)
    {
    	ARG_UNUSED(nus);
    
    	int err;
    
    	for (uint16_t pos = 0; pos != len;) {
    		struct uart_data_t *tx = k_malloc(sizeof(*tx));
    
    		if (!tx) {
    			LOG_WRN("Not able to allocate UART send data buffer");
    			return BT_GATT_ITER_CONTINUE;
    		}
    
    		/* Keep the last byte of TX buffer for potential LF char. */
    		size_t tx_data_size = sizeof(tx->data) - 1;
    
    		if ((len - pos) > tx_data_size) {
    			tx->len = tx_data_size;
    		} else {
    			tx->len = (len - pos);
    		}
    
    		memcpy(tx->data, &data[pos], tx->len);
    
    		pos += tx->len;
    
    		/* Append the LF character when the CR character triggered
    		 * transmission from the peer.
    		 */
    		if ((pos == len) && (data[len - 1] == '\r')) {
    			tx->data[tx->len] = '\n';
    			tx->len++;
    		}
    
    		err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
    		if (err) {
    			k_fifo_put(&fifo_uart_tx_data, tx);
    		}
    	}
    
    	return BT_GATT_ITER_CONTINUE;
    }
    
    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	ARG_UNUSED(dev);
    
    	static size_t aborted_len;
    	struct uart_data_t *buf;
    	static uint8_t *aborted_buf;
    	static bool disable_req;
    
    	switch (evt->type) {
    	case UART_TX_DONE:
    		LOG_DBG("UART_TX_DONE");
    		if ((evt->data.tx.len == 0) ||
    		    (!evt->data.tx.buf)) {
    			return;
    		}
    
    		if (aborted_buf) {
    			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    					   data);
    			aborted_buf = NULL;
    			aborted_len = 0;
    		} else {
    			buf = CONTAINER_OF(evt->data.tx.buf,
    					   struct uart_data_t,
    					   data);
    		}
    
    		k_free(buf);
    
    		buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
    		if (!buf) {
    			return;
    		}
    
    		if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
    			LOG_WRN("Failed to send data over UART");
    		}
    
    		break;
    
    	case UART_RX_RDY:
    		LOG_DBG("UART_RX_RDY");
    		buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
    		buf->len += evt->data.rx.len;
    
    		if (disable_req) {
    			return;
    		}
    
    		if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
    		    (evt->data.rx.buf[buf->len - 1] == '\r')) {
    			disable_req = true;
    			uart_rx_disable(uart);
    		}
    
    		break;
    
    	case UART_RX_DISABLED:
    		LOG_DBG("UART_RX_DISABLED");
    		disable_req = false;
    
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    			k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    			return;
    		}
    
    		uart_rx_enable(uart, buf->data, sizeof(buf->data),
    			       UART_RX_TIMEOUT);
    
    		break;
    
    	case UART_RX_BUF_REQUEST:
    		LOG_DBG("UART_RX_BUF_REQUEST");
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    			uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    		}
    
    		break;
    
    	case UART_RX_BUF_RELEASED:
    		LOG_DBG("UART_RX_BUF_RELEASED");
    		buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
    				   data);
    
    		if (buf->len > 0) {
    			k_fifo_put(&fifo_uart_rx_data, buf);
    		} else {
    			k_free(buf);
    		}
    
    		break;
    
    	case UART_TX_ABORTED:
    		LOG_DBG("UART_TX_ABORTED");
    		if (!aborted_buf) {
    			aborted_buf = (uint8_t *)evt->data.tx.buf;
    		}
    
    		aborted_len += evt->data.tx.len;
    		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    				   data);
    
    		uart_tx(uart, &buf->data[aborted_len],
    			buf->len - aborted_len, SYS_FOREVER_MS);
    
    		break;
    
    	default:
    		break;
    	}
    }
    
    static void uart_work_handler(struct k_work *item)
    {
    	struct uart_data_t *buf;
    
    	buf = k_malloc(sizeof(*buf));
    	if (buf) {
    		buf->len = 0;
    	} else {
    		LOG_WRN("Not able to allocate UART receive buffer");
    		k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    		return;
    	}
    
    	uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT);
    }
    
    static int uart_init(void)
    {
    	int err;
    	struct uart_data_t *rx;
    	printk("uart_init\n");
    	if (!device_is_ready(uart)) {
    		LOG_ERR("UART device not ready");
    		printk("UART device not ready\n");
    		return -ENODEV;
    	}
    
    	rx = k_malloc(sizeof(*rx));
    	if (rx) {
    		rx->len = 0;
    	} else {
    		return -ENOMEM;
    	}
    
    	k_work_init_delayable(&uart_work, uart_work_handler);
    
    	err = uart_callback_set(uart, uart_cb, NULL);
    	if (err) {
    		return err;
    	}
    
    	return uart_rx_enable(uart, rx->data, sizeof(rx->data),
    			      UART_RX_TIMEOUT);
    }
    
    static void discovery_complete(struct bt_gatt_dm *dm,
    			       void *context)
    {
    	struct bt_nus_client *nus = context;
    	LOG_INF("Service discovery completed");
    	printk("Service discovery completed\n");
    
    	bt_gatt_dm_data_print(dm);
    
    	/* Assign connection instance. */
    	nus_client.conn = bt_gatt_dm_conn_get(dm);
    
    	bt_nus_handles_assign(dm, nus);
    	bt_nus_subscribe_receive(nus);
    
    	bt_gatt_dm_data_release(dm);
    }
    
    static void discovery_service_not_found(struct bt_conn *conn,
    					void *context)
    {
    	LOG_INF("Service not found");
    	printk("Service not found\n");
    }
    
    static void discovery_error(struct bt_conn *conn,
    			    int err,
    			    void *context)
    {
    	LOG_WRN("Error while discovering GATT database: (%d)", err);
    }
    
    struct bt_gatt_dm_cb discovery_cb = {
    	.completed         = discovery_complete,
    	.service_not_found = discovery_service_not_found,
    	.error_found       = discovery_error,
    };
    
    static void gatt_discover(struct bt_conn *conn)
    {
    	int err;
    
    	if (conn != default_conn) {
    		return;
    	}
    
    	err = bt_gatt_dm_start(conn,
    			       BT_UUID_NUS_SERVICE,
    			       &discovery_cb,
    			       &nus_client);
    	if (err) {
    		LOG_ERR("could not start the discovery procedure, error "
    			"code: %d", err);
    		printk("could not start the discovery procedure, error "
    			"code: %d\n", err);
    	}
    }
    
    static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
    {
    	if (!err) {
    		LOG_INF("MTU exchange done");
    	} else {
    		LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
    	}
    }
    
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("connected conn_err: %u\n", conn_err);
    
    	if (conn_err) {
    		LOG_INF("Failed to connect to %s (%d)", addr, conn_err);
    		printk("Failed to connect to %s (%d)\n", addr, conn_err);
    
    		if (default_conn == conn) {
    			bt_conn_unref(default_conn);
    			default_conn = NULL;
    
    			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    			if (err) {
    				LOG_ERR("Scanning failed to start (err %d)",
    					err);
    				printk("Scanning failed to start (err %d)\n",
    					err);
    			}
    		}
    
    		return;
    	}
    
    	LOG_INF("Connected: %s", addr);
    	printk("Connected: %s\n", addr);
    
    	static struct bt_gatt_exchange_params exchange_params;
    
    	exchange_params.func = exchange_func;
    	err = bt_gatt_exchange_mtu(conn, &exchange_params);
    	if (err) {
    		LOG_WRN("MTU exchange failed (err %d)", err);
    	}
    
    	err = bt_conn_set_security(conn, BT_SECURITY_L2);
    	if (err) {
    		LOG_WRN("Failed to set security: %d", err);
    
    		gatt_discover(conn);
    	}
    
    	err = bt_scan_stop();
    	if ((!err) && (err != -EALREADY)) {
    		LOG_ERR("Stop LE scan failed (err %d)", err);
    		printk("Stop LE scan failed (err %d)\n", err);
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("Disconnected: %s (reason %u)", addr, reason);
    
    	if (default_conn != conn) {
    		return;
    	}
    
    	bt_conn_unref(default_conn);
    	default_conn = NULL;
    
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	printk("bt_scan_start err:%i\n", err);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)",
    			err);
    	}
    }
    
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    			     enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (!err) {
    		LOG_INF("Security changed: %s level %u", addr, level);
    	} else {
    		LOG_WRN("Security failed: %s level %u err %d", addr,
    			level, err);
    	}
    
    	gatt_discover(conn);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    	.security_changed = security_changed
    };
    
    static void scan_filter_match(struct bt_scan_device_info *device_info,
    			      struct bt_scan_filter_match *filter_match,
    			      bool connectable)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));
    
    	LOG_INF("Filters matched. Address: %s connectable: %d",
    		addr, connectable);
    }
    
    static void scan_connecting_error(struct bt_scan_device_info *device_info)
    {
    	LOG_WRN("Connecting failed");
    }
    
    static void scan_connecting(struct bt_scan_device_info *device_info,
    			    struct bt_conn *conn)
    {
    	default_conn = bt_conn_ref(conn);
    }
    
    static int nus_client_init(void)
    {
    	int err;
    	struct bt_nus_client_init_param init = {
    		.cb = {
    			.received = ble_data_received,
    			.sent = ble_data_sent,
    		}
    	};
    	printk("bt_nus_client_init\n");
    	err = bt_nus_client_init(&nus_client, &init);
    	if (err) {
    		LOG_ERR("NUS Client initialization failed (err %d)", err);
    		printk("NUS Client initialization failed (err %d)", err);
    		return err;
    	}
    
    	LOG_INF("NUS Client module initialized");
    	printk("NUS Client module initialized\n");
    	return err;
    }
    
    BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,
    		scan_connecting_error, scan_connecting);
    
    static int scan_init(void)
    {
    	int err;
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 1,
    	};
    
    	bt_addr_t esp_add[BT_ADDR_SIZE] = {0xD2, 0x29, 0xF5, 0xF9, 0x55, 0x60};
    	bt_addr_le_t esp32_address = {
    		.type = BT_ADDR_LE_PUBLIC,
    		.a = /*esp_add*/{0xD2, 0x29, 0xF5, 0xF9, 0x55, 0x60},
    	};
    
    	printk("scan_init\n");
    	bt_scan_init(&scan_init);
    	bt_scan_cb_register(&scan_cb);
    
    	//err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE);
    	//err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_ADDR, esp32_address);
    	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_ADDR, &esp32_address);
    	if (err) {
    		LOG_ERR("Scanning filters cannot be set (err %d)", err);
    		printk("Scanning filters cannot be set (err %d)\n", err);
    		return err;
    	}
    	
    	char addr_str[BT_ADDR_LE_STR_LEN];
    	bt_addr_le_to_str(&esp32_address, addr_str,
    				  sizeof(addr_str));
    	printk("Address filter added %s\n", addr_str);
    
    	//err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
    	err = bt_scan_filter_enable(BT_SCAN_ADDR_FILTER, false);
    	
    	if (err) {
    		LOG_ERR("Filters cannot be turned on (err %d)", err);
    		printk("Filters cannot be turned on (err %d)\n", err);
    		return err;
    	}
    
    	LOG_INF("Scan module initialized");
    	printk("Scan module initialized\n");
    	return err;
    }
    
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_INF("Pairing cancelled: %s", addr);
    }
    
    
    static void pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    	printk("addr: %s", addr);
    
    	LOG_INF("Pairing completed: %s, bonded: %d", addr, bonded);
    	printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
    }
    
    
    static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    		
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	LOG_WRN("Pairing failed conn: %s, reason %d", addr, reason);
    	printk("Pairing failed conn: %s, reason %d\n", addr, reason);
    }
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.cancel = auth_cancel,
    };
    
    static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    
    void main(void)
    {
    	int err;
    
    	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
    	if (err) {
    		LOG_ERR("Failed to register authorization callbacks.");
    		return;
    	}
    	printk("bt_conn_auth_cb_register\n");
    
    	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
    	printk("bt_conn_auth_info_cb_register err: %i\n", err);
    	if (err) {
    		printk("Failed to register authorization info callbacks.\n");
    		return;
    	}
    
    	err = bt_enable(NULL);
    	printk("bt_enable err: %i\n", err);
    	if (err) {
    		LOG_ERR("Bluetooth init failed (err %d)", err);
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    	printk("Bluetooth initialized\n");
    	LOG_INF("Bluetooth initialized");
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	int (*module_init[])(void) = {uart_init, scan_init, nus_client_init};
    	for (size_t i = 0; i < ARRAY_SIZE(module_init); i++) {
    		err = (*module_init[i])();
    		//printk("i: %i\n", i);
    		if (err) {
    			printk("ERR\n");
    			return;
    		}
    	}
    	printk("\n");
    
    	printk("Starting Bluetooth Central UART example\n");
    	
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err) {
    		LOG_ERR("Scanning failed to start (err %d)", err);
    		printk("Scanning failed to start (err %d)\n", err);
    		return;
    	}
    
    	LOG_INF("Scanning successfully started");
    	printk("Scanning successfully started\n");
    
    	for (;;) {
    		/* Wait indefinitely for data to be sent over Bluetooth */
    		//struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
    		//				     K_FOREVER);
    
    		struct uart_data_t *buf;
    		buf->data[0] = 0;
    		buf->data[1] = 1;
    		buf->data[2] = 2;
    		buf->len = 3;
    
    		//err = bt_nus_client_send(&nus_client, buf->data, buf->len);
    		if (err) {
    			LOG_WRN("Failed to send data over BLE connection"
    				"(err %d)", err);
    			printk("Failed to send data over BLE connection"
    				"(err %d)\n", err);
    		}
    
    		//err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
    		if (err) {
    			LOG_WRN("NUS send timeout");
    			//printk("NUS send timeout\n");
    		}
    	}
    }
    

  • I am not able to spot any errors in your implementation. Could you upload the full project so I can try reproducing this here?

  • I see the problem now: your main loop is always running as you have commented the k_fifo_get() function. 

    As a test, try to add a call to k_msleep(1000); in your loop. This will allow the other threads such as the system workqueue to run. 

  • Thanks! Now the connection is established but the pairing still doesn't work. I have uncommented the 'bt_nus_client_send' and 'k_sem_take' functions but no data is received by the ESP32 and the pairing fails after some time:

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    bt_conn_auth_cb_register
    bt_conn_auth_info_cb_register err: 0
    bt_enable err: 0
    Bluetooth initialized
    uart_init
    scan_init
    Address filter added 60:55:F9:F5:29:D2 (public)
    Scan module initialized
    bt_nus_client_init
    NUS Client module initialized
    
    Starting Bluetooth Central UART example
    scan err: 0
    Scanning
    Scanning successfully started
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    connected conn_err: 0
    Connected: 60:55:F9:F5:29:D2 (public)
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Pairing failed conn: 60:55:F9:F5:29:D2 (public), reason 9
    Service discovery completed
    NUS send timeout

    Do you know why this could be happening?

Reply
  • Thanks! Now the connection is established but the pairing still doesn't work. I have uncommented the 'bt_nus_client_send' and 'k_sem_take' functions but no data is received by the ESP32 and the pairing fails after some time:

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    bt_conn_auth_cb_register
    bt_conn_auth_info_cb_register err: 0
    bt_enable err: 0
    Bluetooth initialized
    uart_init
    scan_init
    Address filter added 60:55:F9:F5:29:D2 (public)
    Scan module initialized
    bt_nus_client_init
    NUS Client module initialized
    
    Starting Bluetooth Central UART example
    scan err: 0
    Scanning
    Scanning successfully started
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    connected conn_err: 0
    Connected: 60:55:F9:F5:29:D2 (public)
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    Pairing failed conn: 60:55:F9:F5:29:D2 (public), reason 9
    Service discovery completed
    NUS send timeout

    Do you know why this could be happening?

Children
  • Did you add k_msleep(1000) to your main loop? Like this:

    	...
    	for (;;) {
    		/* Wait indefinitely for data to be sent over Bluetooth */
    		//struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
    		//				     K_FOREVER);
    
    		struct uart_data_t *buf;
    		buf->data[0] = 0;
    		buf->data[1] = 1;
    		buf->data[2] = 2;
    		buf->len = 3;
    
    		//err = bt_nus_client_send(&nus_client, buf->data, buf->len);
    		if (err) {
    			LOG_WRN("Failed to send data over BLE connection"
    				"(err %d)", err);
    			printk("Failed to send data over BLE connection"
    				"(err %d)\n", err);
    		}
    
    		//err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
    		if (err) {
    			LOG_WRN("NUS send timeout");
    			//printk("NUS send timeout\n");
    		}
    
    		k_msleep(1000);
    	}

  • I tested your sample against the peripheral_uart sample and had to make a few additional changes to make it work:

        //main loop
    	for (;;) {
    		/* Wait indefinitely for data to be sent over Bluetooth */
    		//struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
    		//				     K_FOREVER);
    
    		struct uart_data_t buffer; // allocate buffer on stack
    		buffer.data[0] = 1;
    		buffer.data[1] = 2;
    		buffer.data[2] = 3;
    		buffer.len = 3;
    
    		err = bt_nus_client_send(&nus_client, buffer.data, buffer.len);
    		if (err) {
    			LOG_WRN("Failed to send data over BLE connection"
    				"(err %d)", err);
    			printk("Failed to send data over BLE connection"
    				"(err %d)\n", err);
    		}
    
    		//err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
    		if (err) {
    			LOG_WRN("NUS send timeout");
    			//printk("NUS send timeout\n");
    		}
    
    		k_msleep(1000);
    	}
    	
    // Remove k_free() and k_sem_give() in this function. 
    static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
    					const uint8_t *const data, uint16_t len)
    {
    	ARG_UNUSED(nus);
    
    	struct uart_data_t *buf;
    
    	/* Retrieve buffer context. */
    	buf = CONTAINER_OF(data, struct uart_data_t, data);
    	//k_free(buf); //you are not using heap so there is nothing to free
    
    	//k_sem_give(&nus_write_sem);
    
    	if (err) {
    		LOG_WRN("ATT error code: 0x%02X", err);
    	}
    }

  • Why is it necessary to comment k_free() and k_sem_give()? When I try connecting to an ESP32 the test still fails:

    *** Booting Zephyr OS build v3.2.99-ncs2 ***
    bt_conn_auth_cb_register
    bt_conn_auth_info_cb_register err: 0
    bt_enable err: 0
    Bluetooth initialized
    uart_init
    scan_init
    Address filter added 60:55:F9:F5:29:D2 (public)
    Scan module initialized
    bt_nus_client_init
    NUS Client module initialized
    
    Starting Bluetooth Central UART example
    scan err: 0
    Scanning
    Scanning successfully started
    Failed to send data over BLE connection(err -128)
    NUS send timeout
    connected conn_err: 0
    Connected: 60:55:F9:F5:29:D2 (public)
    Failed to send data over BLE connection(err -128)
    NUS send timeout

    The ESP32 already has a UUID which allows sending strings from a mobile application. Is there something particular to nRF52 in the implementation of NUS?

    Moreover, could you please explain me how the 'pairing_failed' function is called? As it is declared as a callback function it is not clear for me under which situation it is launched.

  • You will get a code assert if you call k_free() on a pointer that has not been allocated from heap, and k_sem_give() is redundant as you are not using k_sem_take().

    Unknown said:
    The ESP32 already has a UUID which allows sending strings from a mobile application. Is there something particular to nRF52 in the implementation of NUS?

    You need to implement your own GATT Client which matches the GATT server on your ESP32. The NUS client will only work with the NUS service: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/libraries/bluetooth_services/services/nus.html 

    You may be able to use the existing NUS client as a starting point and change out the UUIDs to match the UUIDs used by the ESP.

    Unknown said:
    Moreover, could you please explain me how the 'pairing_failed' function is called? As it is declared as a callback function it is not clear for me under which situation it is launched.

    The pairing is handled by the Zephyr Bluetooth host and it will invoke the pairing failed or pairing success callback depending on the outcome.

    Are you still getting the pairing error? If so, is there a long (i.e. several seconds) delay before the pairing failed is called?

Related