BLE Data Rate Issues Between Two nRF52840 Boards

Good morning,
I am trying to send data via BLE from a custom board (with the nRF52840 microcontroller) that has sensors, to an evaluation board nRF52840 PCA10056. To do this, I am using Segger Embedded Studio and started with the example codes ble_app_uart (from ble_peripheral) and ble_app_uart_c (from ble_central).
I use the function void adc_timer_timeout_handler(void * p_context) to sample the data and fill a buffer of size BUFFER_SIZE:

void adc_timer_timeout_handler(void * p_context)
    {

    uint16_t dimensione = BUFFER_SIZE;

    nrfx_saadc_sample_convert(0, &adc_val);

    sentData[index++] = adc_val;

        if(index >= BUFFER_SIZE){
          index = 0;
          buffer_ready = true;   
        }
        
        if(buffer_ready){

          err_code = ble_nus_data_send(&m_nus, sentData, &dimensione, m_conn_handle);

          if(err_code == NRF_SUCCESS){

            buffer_ready = false;

          } else if (err_code != NRF_ERROR_RESOURCES){

            APP_ERROR_CHECK(err_code);
          }

        }

    }

Thus, to send the data, I use the function ble_nus_data_send.

On the receiving board, I use the function void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len) to receive the data:

static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len)
{
    ret_code_t ret_val;
    static uint8_t data_array[BUFFER_SIZE];
    static uint16_t index = 0;
    char uart_string[BLE_NUS_MAX_DATA_LEN];
    
    NRF_LOG_INFO("Receiving data.");
    NRF_LOG_HEXDUMP_DEBUG(p_data, data_len);

    nrf_gpio_pin_toggle(LED_2);

    if (data_len != BUFFER_SIZE)
    {
        NRF_LOG_ERROR("Unexpected data length: %d", data_len);
        return;
    }
    
    // Reset del buffer
    memset(buffer, 0, BUFFER_SIZE);

    buffer[0] = 0xFF;
    buffer[1] = 0xFF;

    // Copiare i dati nel buffer globale
    for (uint8_t i = 0; i < data_len; i++)
    {
        buffer[2+i] = p_data[i];
    }

    for (uint8_t j = 0; j < data_len+2; j++)
    {
        ret_val = app_uart_put(buffer[j]);
        NRF_LOG_INFO("SAMPLE: %d", j);

        if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
        {
            APP_ERROR_CHECK(ret_val);
        }

    }
}

I then send them via serial to the PC to display them using the app_uart_put function (adding 2 bytes = 255 as a header).

The connection parameters in the custom board code are as follows:

#define DEVICE_NAME                     "Nordic_UART"                               /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */

#define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */

#define APP_ADV_INTERVAL                64                                          /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */

#define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */

#define ADC_TIMER                       APP_TIMER_TICKS(50) 

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(7.5, UNIT_1_25_MS)             /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(20, UNIT_1_25_MS)             /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY                   0                                           /**< Slave latency. */
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                           /**< Number of attempts before giving up the connection parameter negotiation. */

#define DEAD_BEEF                       0xDEADBEEF                                  /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */

#define UART_TX_BUF_SIZE                256                                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE                256                                         /**< UART RX buffer size. */

#define BUFFER_SIZE                     15

With these configurations, I am able to send the data, but I am facing two issues:

  • I actually need to sample at 200Hz, so using APP_TIMER_TICKS(5). However, when doing this, I see that the evaluation board can never connect to the other board.
  • So, I thought of sampling every 5ms but filling a buffer with 100 samples to send the data every half second, leaving more time between communications. However, in this case, the receiving function on the evaluation board always returns the message: "Unexpected data length: 20", as if it were only receiving 20 bytes, even though I am sending 100. This happens despite having set the following in sdk_config.h (on both codes):

#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247
#define NRF_SDH_BLE_GAP_DATA_LENGTH 251

I can't understand why this is happening.
In general, I would like to know if it's normal that BLE can't connect when trying to send data after a few ms, and also why I can't send more than 20 bytes. The connection speed should theoretically be 1Mbps, while I am transmitting much more slowly.
Please let me know your thoughts, your help would be very valuable.
Thank you so much,
Gabriele

Related