Hi,
I’m developing a BLE IoT product using the nRF52840 DK, where I need to send a payload of 60 bytes. In a previous response to one of my questions, I was advised to increase the MTU size to handle the larger payload. I implemented the MTU size increase using the code provided, and everything works fine when I connect to the device for the first time.
However, when I disconnect and try to reconnect, the device is no longer visible in the Bluetooth device list. This issue only occurs after the first disconnect. I’m not sure what could be causing the problem.
Has anyone experienced this before or have any suggestions on how to resolve this issue? I'm attaching my code below for reference.
Thanks in advance for your help!
main.c
/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include "main.h" #include "ff.h" #include "ffconf.h" #include "mem.h" #include "shell.h" #include "flash_management.h" #include "TargetPlatform.h" #include "vc_date_time.h" #include "vc_ble_bio_data_service.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 <zephyr/settings/settings.h> LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart), "Console device is not ACM CDC UART device"); const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); char app_ecg_live[50]; char app_ecg_past[50] = {0}; vcPatchData_t patchData; int64_t current_date; int loop = 0; FATFS fs; int64_t app_time = 0; volatile uint32_t available_instance_count = 1; extern struct tm new_date_time; uint32_t dtr = 0; K_MUTEX_DEFINE(test_mutex); /** * @brief Message queue declaration for managing led patterns. * * This message queue is used to store and manage led patterns. */ K_MSGQ_DEFINE(process_ecg_data_queue, sizeof(app_ecg_live), 10, 4); #define DEVICE_NAME CONFIG_BT_DEVICE_NAME #define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1) /** * @brief Bluetooth advertising parameters. * * This variable holds the parameters for Bluetooth advertising. */ static struct bt_le_adv_param *adv_param = BT_LE_ADV_PARAM( (BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_IDENTITY), /* Connectable advertising and use identity address */ 1600, /* Min Advertising Interval 1000ms (1600*0.625ms) */ 1601, /* Max Advertising Interval 1000.625ms (1601*0.625ms) */ NULL); /* Set to NULL for undirected advertising */ /** * @brief Bluetooth advertising data. * * This variable holds the advertising data for Bluetooth. */ 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), }; /** * @brief Bluetooth scan response data. * * This variable holds the scan response data for Bluetooth. */ static const struct bt_data sd[] = { BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_UDS_VAL)), }; static char *app_ecg_data_live_cb() { return app_ecg_live; } static char *app_ecg_data_past_cb() { return app_ecg_live; } static struct vc_bds_svc_cb app_vc_bds_callbacks = { .ecg_data_live_cb = app_ecg_data_live_cb, .ecg_data_past_cb = app_ecg_data_past_cb, }; static void exchange_func(struct bt_conn *conn, uint8_t att_err, struct bt_gatt_exchange_params *params); /* STEP 11.2 - Create variable that holds callback for MTU negotiation */ static struct bt_gatt_exchange_params exchange_params; struct bt_conn *my_conn = NULL; static void update_data_length(struct bt_conn *conn) { int err; struct bt_conn_le_data_len_param my_data_len = { .tx_max_len = BT_GAP_DATA_LEN_MAX, .tx_max_time = BT_GAP_DATA_TIME_MAX, }; err = bt_conn_le_data_len_update(my_conn, &my_data_len); if (err) { LOG_ERR("data_len_update failed (err %d)", err); } } static void update_mtu(struct bt_conn *conn) { int err; exchange_params.func = exchange_func; err = bt_gatt_exchange_mtu(conn, &exchange_params); if (err) { LOG_ERR("bt_gatt_exchange_mtu failed (err %d)", err); } } /** * @brief Callback function for Bluetooth connection established event. * * This function is called when a Bluetooth connection is established. * * @param conn Pointer to the connection structure. * @param err Error code indicating the connection status. * 0 if connection is successful, non-zero error code otherwise. * * @return None. */ static void on_connected(struct bt_conn *conn, uint8_t err) { if (err) { LOG_ERR("Connection failed (err %u)", err); return; } LOG_INF("Connected"); my_conn = bt_conn_ref(conn); update_data_length(my_conn); update_mtu(my_conn); } /** * @brief Callback function for Bluetooth connection disconnected event. * * This function is called when a Bluetooth connection is disconnected. * * @param conn Pointer to the connection structure. * @param reason Disconnection reason code. * * @return None. */ static void on_disconnected(struct bt_conn *conn, uint8_t reason) { LOG_INF("Disconnected (reason %u)", reason); } /** * @brief Callback function for Bluetooth security changed event. * * This function is called when Bluetooth security level changes. * * @param conn Pointer to the connection structure. * @param level New security level. * @param err Error code indicating the security change status. * * @return None. */ 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_INF("Security failed: %s level %u err %d", addr, level, err); } } void on_le_data_len_updated(struct bt_conn *conn, struct bt_conn_le_data_len_info *info) { uint16_t tx_len = info->tx_max_len; uint16_t tx_time = info->tx_max_time; uint16_t rx_len = info->rx_max_len; uint16_t rx_time = info->rx_max_time; LOG_INF("Data length updated. Length %d/%d bytes, time %d/%d us", tx_len, rx_len, tx_time, rx_time); } BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = on_connected, .disconnected = on_disconnected, .security_changed = security_changed, }; /* Implement callback function for MTU exchange */ static void exchange_func(struct bt_conn *conn, uint8_t att_err, struct bt_gatt_exchange_params *params) { LOG_INF("MTU exchange %s", att_err == 0 ? "successful" : "failed"); if (!att_err) { uint16_t payload_mtu = bt_gatt_get_mtu(conn) - 3; // 3 bytes used for Attribute headers. LOG_INF("New MTU: %d bytes", payload_mtu); } } /** * @brief Callback function for displaying passkey during Bluetooth pairing. * * This function is called to display the passkey during Bluetooth pairing. * * @param conn Pointer to the connection structure. * @param passkey Passkey to be displayed. * * @return None. */ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); LOG_INF("Passkey for %s: %06u", addr, passkey); } /** * @brief Callback function for canceling Bluetooth pairing. * * This function is called to cancel Bluetooth pairing process. * * @param conn Pointer to the connection structure. * * @return None. */ 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); } /** * @brief Callback function for Bluetooth pairing completion. * * This function is called when Bluetooth pairing is completed. * * @param conn Pointer to the connection structure. * @param bonded Flag indicating if the device is bonded after pairing. * * @return None. */ 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)); LOG_INF("Pairing completed: %s, bonded: %d", addr, bonded); } /** * @brief Callback function for Bluetooth pairing failure. * * This function is called when Bluetooth pairing fails. * * @param conn Pointer to the connection structure. * @param reason Error code indicating the reason for pairing failure. * * @return None. */ 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_INF("Pairing failed conn: %s, reason %d", addr, reason); } /** * @brief Bluetooth connection authentication callbacks structure. * * This structure holds callback functions related to Bluetooth connection authentication. */ static struct bt_conn_auth_cb conn_auth_callbacks = { .passkey_display = auth_passkey_display, .cancel = auth_cancel, .passkey_display = NULL, .passkey_confirm = NULL, }; /** * @brief Bluetooth connection authentication info callbacks structure. * * This structure holds callback functions related to Bluetooth connection authentication information. */ static struct bt_conn_auth_info_cb conn_auth_info_callbacks = { .pairing_complete = pairing_complete, .pairing_failed = pairing_failed}; int main(void) { /* Initialize sensors */ sensor_init(); /* Initialize GPIO and configure GPIOTE */ gpio_init(); flash_init(); vc_set_time(1999999997); /*erasing nand flash(mt29)*/ int err = 0; // Variable to store error codes err = bt_conn_auth_cb_register(&conn_auth_callbacks); // Register Bluetooth authorization callbacks if (err) { LOG_ERR("Failed to register authorization callbacks."); // Log error if registration fails } err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks); // Register Bluetooth authorization info callbacks if (err) { LOG_ERR("Failed to register authorization info callbacks."); // Log error if registration fails } err = bt_enable(NULL); // Enable Bluetooth if (err) { LOG_ERR("Bluetooth init failed (err %d)", err); // Log error if Bluetooth initialization fails } err = vc_bds_svc_init(&app_vc_bds_callbacks); // Initialize USB device if (err) { LOG_ERR("Failed to init usb dev (err:%d)", err); // Log error if initialization fails } LOG_INF("Bluetooth initialized"); // Log Bluetooth initialization success err = bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); // Start Bluetooth advertising if (err) { LOG_ERR("Advertising failed to start (err %d)", err); // Log error if advertising fails } } /** * @brief Application LED pattern thread. * * This thread runs continuously and switches between different LED patterns based on * the value of `moov_dev_pattern`. It calls the respective functions for booting, blinking, * and circular patterns. After executing a pattern, it waits for a period of 1000 milliseconds. */ void process_ecg_data(void) { while (1) { k_msgq_get(&process_ecg_data_queue, &app_ecg_live, K_FOREVER); if (is_ecg_live_enabled()) { if ( vc_ecg_send_live_data(app_ecg_live)) { LOG_ERR("vc_ecg_send_live_data error"); } } else { LOG_INF("app_ecg_live:%s", app_ecg_live); k_mutex_lock(&test_mutex, K_FOREVER); int len = strlen(app_ecg_live); app_ecg_live[len ] = '\n'; storingData(app_ecg_live); k_mutex_unlock(&test_mutex); } } } /** * @brief Application LED pattern thread. * * This thread runs continuously and switches between different LED patterns based on * the value of `moov_dev_pattern`. It calls the respective functions for booting, blinking, * and circular patterns. After executing a pattern, it waits for a period of 1000 milliseconds. */ void process_ecg_data_past(void) { char patchData[40]; while (1) { if (is_ecg_past_enabled()) { k_mutex_lock(&test_mutex, K_FOREVER); readFromFile(app_ecg_past); if (vc_ecg_send_past_data(app_ecg_past)) { LOG_ERR("vc_ecg_send_live_data error"); } k_mutex_unlock(&test_mutex); } k_msleep(100); } } void usb_thread() { if (usb_enable(NULL)) { printk("usb enable failed\n"); return; } printk("usb thread started\n"); while (1) { if (!dtr) { uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); k_sleep(K_MSEC(100)); } else { k_sleep(K_SECONDS(1)); } } } K_THREAD_DEFINE(write_id, 32768, process_ecg_data, NULL, NULL, NULL, 5, 0, 10000); K_THREAD_DEFINE(read_id, 32768, process_ecg_data_past, NULL, NULL, NULL, 6, 0, 10000); K_THREAD_DEFINE(usb_id, 1024, usb_thread, NULL, NULL, NULL, 6, 0, NULL);
prj.conf
CONFIG_LOG=y CONFIG_PRINTK=y CONFIG_LOG_MODE_IMMEDIATE=y CONFIG_CBPRINTF_FP_SUPPORT=y # CONFIG_LOG_BACKEND_RTT=y CONFIG_SPI=y CONFIG_SENSOR=y CONFIG_PM_DEVICE=y CONFIG_APPLICATION_DEFINED_SYSCALL=y CONFIG_MAIN_STACK_SIZE=32768 # CONFIG_FILE_SYSTEM=y #timer CONFIG_DATE_TIME=y CONFIG_DATE_TIME_UPDATE_INTERVAL_SECONDS=0 CONFIG_DATE_TIME_TOO_OLD_SECONDS=0 CONFIG_DATE_TIME_NTP=y CONFIG_NETWORKING=y CONFIG_NET_SOCKETS=y #Enable MCUBOOT bootloader build in the application CONFIG_BOOTLOADER_MCUBOOT=y #Set firmware image version CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION="1.0.1" #Include MCUMGR and the dependencies in the build CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y #usb CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample" CONFIG_USB_DEVICE_PID=0x0004 CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_UART_LINE_CTRL=y #bluetooth configuration CONFIG_BT=y CONFIG_BT_SMP=y CONFIG_BT_SMP_APP_PAIRING_ACCEPT=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DEVICE_NAME="VC Manoj" CONFIG_BT_DIS=y CONFIG_BT_DIS_PNP=y CONFIG_BT_DIS_MANUF="DotcomIoTLLP" CONFIG_BT_DIS_PNP_VID_SRC=2 CONFIG_BT_DIS_PNP_VID=0x1915 CONFIG_BT_DIS_PNP_PID=0xEEEB CONFIG_BT_DIS_PNP_VER=0x0100 #bt Update Data Length and MTU CONFIG_BT_GATT_CLIENT=y CONFIG_BT_USER_DATA_LEN_UPDATE=y CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 CONFIG_BT_BUF_ACL_RX_SIZE=251 CONFIG_BT_BUF_ACL_TX_SIZE=251 CONFIG_BT_L2CAP_TX_MTU=247