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

Maximizing throughput for ADC -> BTLE periperhal uart

I'm trying to use the ADC on the DK52 (PCA100040) to sample and transmit data to a PC.  I've been able to write code that samples data to a buffer and I've modified the peripehral uart example to transmit data, but I'm not able to keep the datarate sustained before the kernel crashes and reboots the processor.  

The call to bt_nus_get_mtu() returns 20, which is a very small size.  

I would like to transmit at 1000kbits per second which should be doable based on what I've read, but I seem a fair ways off.  Is this acheiavable with this hardware?  Or possibly a different MCU in your family?  On the other end I've tested it using a BCM20702 dongle on a windows 10 box as well as the nrf toolbox uart application.  Both result in a max mtu of 20 and a crash right afterwards.

I basically will sample data and write it to a buffer (using the adc's double buffering).  I then malloc a new buffer and dump it into a fifo.  I've modified the tx thread from the peripheral uart example to read from the fifo and write out packets.  

Please let me know if this is tractable with BTLE or if I need to switch to a traditional bluetooth IC.  

struct adc_sample {
  nrf_saadc_value_t samples[800];
}

void ble_write_thread(void) {
  static uint32_t max_mtu = 0;

  /* Don't go any further until BLE is initialized */
  k_sem_take(&ble_init_ok, K_FOREVER);

  for (;;) {
    /* Wait indefinitely for data to be sent over bluetooth */
    uint8_t *buf = k_fifo_get(&fifo_uart_rx_data, K_FOREVER);
    uint16_t len = sizeof(struct adc_sample);

    if (!max_mtu) {
      max_mtu = bt_nus_get_mtu(current_conn);
      printk("Max MTU=%d\n", max_mtu);
    }

    while (len) {
      if (bt_nus_send(current_conn, buf, Z_MIN(len,max_mtu))) {
        printk("=");
        LOG_WRN("Failed to send data over BLE connection");
        break;
      } else {
        buf += Z_MIN(len, max_mtu);
        len -= Z_MIN(len, max_mtu);
      }
    }
    
    printk("!");
    k_free(buf);
  }
}

On the other end, I'm using this example for the bleak python btle library: github.com/.../uart_service.py

  • Hi Reza

    Which version of the nRF Connect SDK are you using?

    The peripheral_uart example is not very well optimized for throughput unfortunately. 

    First off the sample does not do MTU negotiation out ouf the box like you noticed, and secondly it relies on dynamic allocation of UART data, which is risky if you are pushing a lot of data. 

    I am working on a modified version of the peripheral_uart sample that adds MTU negotiation and also uses a modified UART interface that uses static FIFO's for data buffering rather than dynamically allocated buffers. 

    Could you have a look at the example and see if it seems suitable for your application? 

    5861.per-uart-app-uart.zip

    You can build it in a similar way to the standard peripheral_uart sample, but the "modules" folder need to be on the same level as the peripheral_uart folder for the sample to build out of the box. 

    Best regards
    Torbjørn

Related