Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Only first BLE peripheral sends data to central when using multiple NUS clients (BLE_NUS_C_ARRAY_DEF, Multi-Link)

Hello,
I'm developing a BLE Central application using the nRF52 SDK.
The central connects to multiple peripheral devices (nRF52832), each sending 6-byte ADXL345 accelerometer data at 20 Hz via Nordic UART Service (NUS).

I'm using the BLE_NUS_C_ARRAY_DEF(m_ble_nus_c, NRF_SDH_BLE_CENTRAL_LINK_COUNT) macro to support multiple clients, based on project: https://github.com/NordicPlayground/nrf52-ble-app-uart-c-multilink

And I want to classify data that where it is from 

Everything works fine for:

  • Scanning and connecting to peripherals

  • MTU exchange

  • Service discovery

  • Assigning conn_handle to the correct NUS client index

  • Enabling notifications

  • Disconnection and MAC cleanup

What doesn't work: Only the first connected peripheral (typically assigned conn_handle = 0x0000) successfully sends data via BLE_NUS_C_EVT_NUS_TX_EVT.
Even though the others connect and complete discovery, they never trigger NUS data events, and I receive no data from them.

I've verified that:

  • Each peripheral works correctly (tested with Android, receiving data from 5 devices in parallel)

  • GAP success of each peripheral device, and NUS discovery success of each peripheral device. 

Attached is the debug terminal image, which verifies the function works well, but the data comes from the first connected peripheral device. 

--------------------------------------------------------------------------------------------

Any idea why only one peripheral sends data, even though others connect successfully and notifications are enabled?


How can I reliably receive data from all connected peripherals and distinguish where each packet comes from?

Below are the parts of the code I've made. 

typedef struct {
    uint16_t conn_handle;         // Assigned connection handle for the peripheral
    ble_gap_addr_t mac_addr;      // MAC address of the connected peripheral
    bool in_use;                  // Slot usage flag
} device_info_t;

static device_info_t m_connected_devices[MAX_CONNECTED_DEVICES]; // Array to track connected peripherals

~~~~

static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
    ret_code_t err_code;

    switch (p_scan_evt->scan_evt_id)
    {
        case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
            // Connection failed, report error
            err_code = p_scan_evt->params.connecting_err.err_code;
            APP_ERROR_CHECK(err_code);
            break;

        case NRF_BLE_SCAN_EVT_CONNECTED:
        {
            // Successfully initiated connection to peripheral
            ble_gap_evt_connected_t const * p_connected = p_scan_evt->params.connected.p_connected;

            NRF_LOG_INFO("Connecting to target %02x%02x%02x%02x%02x%02x",
                         p_connected->peer_addr.addr[0], p_connected->peer_addr.addr[1],
                         p_connected->peer_addr.addr[2], p_connected->peer_addr.addr[3],
                         p_connected->peer_addr.addr[4], p_connected->peer_addr.addr[5]);

            // Store MAC address in the first available slot
            for (int i = 0; i < MAX_CONNECTED_DEVICES; i++)
            {
                if (!m_connected_devices[i].in_use)
                {
                    m_connected_devices[i].mac_addr = p_connected->peer_addr;
                    m_connected_devices[i].in_use = true;
                    break;
                }
            }
            break;
        }

        case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:
            // Restart scanning on timeout
            NRF_LOG_INFO("Scan timed out.");
            scan_start();
            break;

        default:
            break;
    }
}

~~~~

static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt)
{
    ret_code_t err_code;

    switch (p_ble_nus_evt->evt_type)
    {
        case BLE_NUS_C_EVT_DISCOVERY_COMPLETE:
        {
            // Find the device slot matching the connection handle
            int matched_index = -1;
            for (int i = 0; i < MAX_CONNECTED_DEVICES; i++)
            {
                if (m_connected_devices[i].in_use &&
                    m_connected_devices[i].conn_handle == p_ble_nus_evt->conn_handle)
                {
                    matched_index = i;
                    break;
                }
            }

            if (matched_index != -1)
            {
                // Assign handles to the correct NUS client and enable notifications
                err_code = ble_nus_c_handles_assign(&m_ble_nus_c[matched_index],
                                                    p_ble_nus_evt->conn_handle,
                                                    &p_ble_nus_evt->handles);
                APP_ERROR_CHECK(err_code);

                err_code = ble_nus_c_tx_notif_enable(&m_ble_nus_c[matched_index]);
                APP_ERROR_CHECK(err_code);

                NRF_LOG_INFO("Discovery complete.:conn_handle = 0x%04X assigned to NUS[%d]",
                             p_ble_nus_evt->conn_handle, matched_index);
            }
            else
            {
                NRF_LOG_WARNING("No matching MAC slot for conn_handle 0x%04X",
                                p_ble_nus_evt->conn_handle);
            }
            break;
        }

        case BLE_NUS_C_EVT_NUS_TX_EVT:
        {
            // Incoming data from a peripheral — identify and log it
            uint16_t conn_handle = p_ble_nus_evt->conn_handle;
            uint8_t *data = p_ble_nus_evt->p_data;
            uint16_t len = p_ble_nus_evt->data_len;

            for (int i = 0; i < MAX_CONNECTED_DEVICES; i++)
            {
                if (m_connected_devices[i].in_use &&
                    m_connected_devices[i].conn_handle == conn_handle)
                {
                    ble_gap_addr_t *addr = &m_connected_devices[i].mac_addr;
                    NRF_LOG_INFO("[%02X:%02X:%02X] data received %d",
                                 addr->addr[5], addr->addr[4], addr->addr[3],
                                 m_connected_devices[i].conn_handle);
                    NRF_LOG_HEXDUMP_INFO(data, len);
                }
            }
            break;
        }

        case BLE_NUS_C_EVT_DISCONNECTED:
            // Re-start scanning when a device disconnects
            NRF_LOG_INFO("Disconnected.NUS_C");
            scan_start();
            break;
    }
}

I guess there might be problems in the "BLE_NUS_C_EVT_NUS_TX_EVT:" I cannot find out how to solve this problem. 

Please help me and thanks in advance. 

Parents Reply Children
No Data
Related