This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

BLE nus slow transmitting after being connected for a while

Hi,

I have implemented BLE nus uart on my device and am getting some weird problems with the transfer speed.

When I connect to the device and transfer data via BLE nus to the mobile phone the data is transferred very quickly, however, if I keep the device connected for a while after connecting and then transferring data then the data is sent extremely slow. The same happens if I send data with BLE nus and then send again afterwards. I currently switch between slow and fast connection interval, could this be a problem? But, the weird thing is that when I connected to the device in the beginning and wait for a while it also happens when still on fast connection interval.

I currently am using sdk 15.0 with SD 6.0

Parents
  • Hello,

    Changing the connection interval may affect the tranfer rate, but this is a quite complex topic. Check out the ble_app_att_mtu_throughput example to see how the connection parameters is affecting the transfer rate.

    Have you tried sniffing the connection using nRF Sniffer? Are there any connection parameter updates when the transfer rate is going slow? Is there anything changing from your application? Are you starting to send smaller packets? How do you queue the packets? Do you wait for one packet to be completed (TX COMPLETE) before queuing the next, or do you queue them as soon as you can, until it returns NRF_ERROR_RESOURCES?

    BR,

    Edvin

  • Hello,

    Thank you for the immediate support!

    No, I haven't tried nRF sniffer as I currently only have one dev board that is in used already. Will check if I might have an extra that I could setup as a sniffer.

    As I do it currently is that whenever I receive an init package from the mobile app, I update the connection interval to fast instead of slow. Afterwards I start packaging data available on the nRF device and send it to the mobile phone. The data could sometime be large chunks but also small. The problem I've observed is that when starting the sending directly after connecting to the device it is much more faster than when sending again or waiting for a few minutes and then sending the data. If I have waited like for more than 4-5 minutes the device even freezes and I'll have to reset the device manually.

  • Hadi Deknache said:
    I just want to mention that I have a second processor that is sending some UART data with the nrf ble module. Could is somehow cause any trouble? The second processor is sending data to the nrf module which then transfers it to the mobile.

     I don't know. You need to debug. When you "freeze", is the processor running, or has your application crashed? Have you tried to monitor the log from the nRF? Does it say anything when it freezes?

    Please check the return values for a given softdevice call. For ble_nus_data_send(), that would be sd_ble_gatts_hvx(). In ble_gatts.h you can see the possible return values.

    NRF_ERROR_TIMEOUT is 13 (0x0D), while NRF_ERROR_RESOURCES is 19 (0x13). You see the 19, right? So you get an NRF_ERROR_RESOURCES, meaning that the queue is full (which is a good thing if you try to send as much as possible because you have filled the queue.

    So let's try another approach then. What is the connection interval changed to after a while?

    To sum up.

    1: What happenes at the "freeze"?

    2: What is your connection interval "after a while"?

    And what are the actual rates that you are seeing? What determines how fast you are trying to send? The incoming UART? And how fast is that?

  • Yes, the other processor which is sending the data is still alive and waiting for the nrf ble module to send an ack when it has sent everything to the mobile phone. Since the processor doesn't send any ack it times out after 20 seconds and restarts the ble as it seem to have been stuck/frozen.

    Exactly, my bad. The error is as you say NRF_ERRO_RESOURCES is what I get sometimes. However, the last thing I get when debugging and performing ble_nus_data_send() is this error:

    <info> app: Sending NUS data! 0x0
    <info> app: DONE!

    The connection intervals I change between are these:

    // Connection Interval and timeout for slow connection
    #define SLOW_MIN_CONN_INTERVAL MSEC_TO_UNITS(180, UNIT_1_25_MS)
    #define SLOW_MAX_CONN_INTERVAL MSEC_TO_UNITS(375, UNIT_1_25_MS) 
    #define SLOW_CONN_SUP_TIMEOUT  MSEC_TO_UNITS(6000, UNIT_10_MS)
    #define SLOW_SLAVE_LATENCY     4
    
    // Connection Interval and timeout for fast connection
    #define FAST_MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS) 
    #define FAST_MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_1_25_MS)
    #define FAST_CONN_SUP_TIMEOUT  MSEC_TO_UNITS(5000, UNIT_10_MS)
    #define FAST_SLAVE_LATENCY     4
    
    // Time from initiating event (connect or start of notification) to first time
    // sd_ble_gap_conn_param_update is called (20 seconds).
    #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(20000)
    
    // Time between each call to sd_ble_gap_conn_param_update after the first call
    // (5 seconds).
    #define NEXT_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)
    
    // Number of attemps before giving up connection parameter negotiation
    #define MAX_CONN_PARAMS_UPDATE_COUNT   3

    So normally I use slow, when there is a request from the mobile application, it switches to fast and wait for it to success and then start sending. 

    When the nrf device freezes, I seem to not get any more prints in any of the other places. It seem like it just locked itself somehow or maybe hard faulted I don't know what is actually happening, but seem like it just stops.

  • Try some debugging. Check how fast you can usually queue packets when you connect, and how many you can queue "after a while".

    Please note that the connection interval is decided by the central. You can ask for certain parameters on the peripheral, but it is the phone (iPhone) that decides. You may not use the connection interval that you think.

    It is very hard for me to say whats going on here. Try to print a message every time you successfully queue a packet, and print the length of the queued packet. What does it look like at first, and after a while? Does it look like it is slowing down?

  • Ok, I seem to have traced the error where it seem to be stuck. When checking the prints it seem to be stuck in a while loop which is trying to do app_uart_get() and is returning error 5 from app_fifo_get(), I assume that this error is NRF_ERROR_NOT_FOUND. Am I correct?

    app_uart_get is fetching uart from the second processor but is returning this error. What could be causing this problem? Why is it triggering this error?

    Also, sometimes I also receive APP_UART_COMMUNICATION_ERROR, what could cause this error? It seem like it is losing some packages which cause the data to be incomplete. Is there some way to fix this issue?

  • Hello,

    The app_uart and app_fifo get are open source, so you can check why it returns NRF_ERROR_NOT_FOUND:

    uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte)
    {
        if (FIFO_LENGTH() != 0)
        {
            fifo_get(p_fifo, p_byte);
            return NRF_SUCCESS;
        }
    
        return NRF_ERROR_NOT_FOUND;
    
    }

    And you can see that FIFO_LENGTH() is a macro:

    #define FIFO_LENGTH(F) fifo_length(&F)              /**< Macro to calculate length of a FIFO. */
    
    //where fifo_length(&F):
    
    static __INLINE uint32_t fifo_length(app_fifo_t * const fifo)
    {
      uint32_t tmp = fifo->read_pos;
      return fifo->write_pos - tmp;
    }

    So I believe you are trying to read out the UART data, when you haven't received any data yet (you have read out all you have received). You should wait for the uart_event_handle() event before you read out the next byte.

    BR,

    Edvin

Reply
  • Hello,

    The app_uart and app_fifo get are open source, so you can check why it returns NRF_ERROR_NOT_FOUND:

    uint32_t app_fifo_get(app_fifo_t * p_fifo, uint8_t * p_byte)
    {
        if (FIFO_LENGTH() != 0)
        {
            fifo_get(p_fifo, p_byte);
            return NRF_SUCCESS;
        }
    
        return NRF_ERROR_NOT_FOUND;
    
    }

    And you can see that FIFO_LENGTH() is a macro:

    #define FIFO_LENGTH(F) fifo_length(&F)              /**< Macro to calculate length of a FIFO. */
    
    //where fifo_length(&F):
    
    static __INLINE uint32_t fifo_length(app_fifo_t * const fifo)
    {
      uint32_t tmp = fifo->read_pos;
      return fifo->write_pos - tmp;
    }

    So I believe you are trying to read out the UART data, when you haven't received any data yet (you have read out all you have received). You should wait for the uart_event_handle() event before you read out the next byte.

    BR,

    Edvin

Children
No Data
Related