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

[Qeustion] data send delay error

HI, I am seungwoo

I am developing data transmission using nrf52810.

A 300-kilobyte file is divided into 220 bytes and transmitted continuously.


11-27 17:24:24.416 W 15138 lbs_tag_service woo send4 packetInteration = 212total = 1543
11-27 17:24:24.418 E 2945 bt_att gatt_act_write() failed op_code=0x52 rt=143
11-27 17:24:26.236 W 15138 lbs_tag_service woo send4 packetInteration = 213total = 1543

If I send data, periodically, the above bt_att gatt_act_write () failed op_code = 0x52 rt = 143 occurs.

This error delays a lot of time.

GATT_CONNECTION_CONGESTED

added in API level 21

public static final int GATT_CONNECTION_CONGESTED

A remote device connection is congested.

Constant Value: 143 (0x0000008f)

The issue is thought to occur when the android ble stack becomes full.

I think I can not get the best speed if I get a delay of about 2 seconds every time the stack is full.

I want to know if there is a workaround.

I am using example ble_app_uart.

  • Hi ,

    On Android, after calling writeCharacteristic, you have to wait for onCharacteristcWrite callback before you may call next operation, e.x. next writeCharacteristic. We recommend using our BLE Library (https://github.com/NordicSemiconductor/Android-BLE-Library/), which handles all the queueing for you + handles most common problems. There is alternative, for example RxAndroidBLE etc.

    If you are sending data from the Android without response, on Android 5 and older you also have to ensure that the buffer doesn't get overflown. To do this you may either send each n-th (n=~200) packet as Write With Response (Write type default), or use some other synchronization mechanizm. In DFU we were using notifications, which we called PRN (Packet Receipt Notification). They had to be sent every n packets from the peripheral when the device has received all n packets. Since Marshmallow the Android handles buffer overflow on it's own and it just postpones the onCharacteristicWrite callback until the buffer is available again.

    Best Regards,

    Aleksander

  • Hi, 

    Answer Thank you very much.

    If I look at the speed I currently calculate

    Number of packets sent per second

    1packet (MTU byte) * 6(Number of packets sent per Android 1 interval,  nexus5 6) * 83(interval 12ms) = 500 packet

    However, as mentioned above, there are about 200 GATT_CONNECTION_CONGESTED problems.

    So I have two questions.

    1. Does Nordic chip affect processing speed?

        - I use nrf52810, ble_app_uart ( default , interval 12ms, buffer 256)

    2. Can you improve on android side?

       -  I tried the test in the following way.

          1 ~ 100 packet (WRITE_TYPE_NO_RESPONSE)  ->101  packet (Write type default) -> 102  ~ 200 (WRITE_TYPE_NO_RESPONSE) 

          In this case, the same problem does not occur.

         However, it takes longer to transfer.

    In my opinion, the best way is to send data continuously with WRITE_TYPE_NO_RESPONSE with an MTU of 244 bytes.

    But this causes GATT_CONNECTION_CONGESTED to be a problem.

    Can you tell me in detail what you need to fix or fix to improve?

     Thanks

  • Hi, 

    Could you let me know what was your actual speed you achieved in your test ? 

    Note that there is no guarantee that you will have 6 packets per connection at interval 12ms. It's depends on the phone and the size of your MTU. We need to have a sniffer trace to see what exactly happened over the air. 

    When writing with response, you can't achieve highest throughput because that command can't be stacked, you need to wait for the first one to finish be fore you send the next one. 

  • What phone are you using for testing?

    The 2nd approach you mentioned: 

    > 1 ~ 100 packet (WRITE_TYPE_NO_RESPONSE)  ->101  packet (Write type default) -> 102  ~ 200 (WRITE_TYPE_NO_RESPONSE) 

    should not increase the transfer time a lot. When you send the data with WRITE_TYPE_NO_RESPONSE, the onCharacteristicWrite callback is called when the data are written to the outgoing queue, not when they were sent. That's why it may seem as they were send super fast, while you just have filled the buffer, which is then processed much slower. The delay, which you get by putting the WRITE_TYPE_DEFAULT in the middle, or also at the end, is just to ensure that he buffer gets empty before you put more data into it. So the transfer indeed would be a bit slower, as the Write With Response takes the whole connection interval (1 packet instead of 6 is sent), but prevents from overflowing the buffer.

    To increase the speed you may experiment with different connection intervals, MTU, try phones supporting DLE (Data Length Extension, Android 6+ required, but not all phones support it). In longer connection interval you may fit more data if they are send without response.

    Also, the slowest connection interval supported by Android is 11.25 ms (until Lollipop it was 7.5ms).

    And remember, that you may send only MTU-3 bytes using Write Without Response in a single write. For example, the default MTU is 23, which is 20 bytes of data available.

  • Hi, 

    Thank you very much for your quick reply.

    I am currently testing through nexus5.
    The phone supports DLE.
    Therefore, even if the MTU size exceeds 200 bytes, it operates normally.

    I think it is the fastest way to use Write Without Response.

    However, there is a delay due to GATT_CONNECTION_CONGESTED, which occurs when the queue is full on the bluetooth bleed stack.

    I say precisely

    GATT_CONNECTION_CONGESTED does not occur, and we ask if we can send packet continuously.

    Even if MTU size and interval are modified, the same GATT_CONNECTION_CONGESTED occurs.

    https://issuetracker.google.com/issues/37121017

    And above, it seems that the android queue is full.

    How can I fix this?

    Thank you

Related