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

Unable to send 1kBps of data using ble nus service on SDK12.3

I am sending 6 packets of 20B each data using ble_nus_string_send() function at every 120ms using app timer. but the function returns error BLE_ERROR_NO_TX_PACKETS. So unable to find the exact issue that is causing this issue. As far as the calculations 1kB should not be an issue.

I am also confused that why the counter value always return as 1 of p_ble_evt->evt.common_evt.params.tx_complete.count. 

these are the connection interval values I have used

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(7.5, UNIT_1_25_MS)
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_1_25_MS)

Parents
  • Hello,

    You can check the throughput on BLE with different connection settings here.

    Using SDK12.3.0, the throughput isn't great, because this was before BLE5 came, with higher throughput options, so the throughput you are looking at is GATT server - ATT_MTU 23 - 1MB Phy, so 192kbps  = 24kBps.

    6 * 20B every 120ms = 1kBps = 8 kbps, so you are within the limits.

    The issue is that this throughput limitation is continuous, while you are sending bursts of 120 bytes, which is too much for the softdevice to store away.

    Possible solutions:

    I see that you use the nRF52832. I suggest that you go to SDK15.2.0, the latest softdevice. Here the size of ble_nus_data_send() (the new name for ble_nus_string_send) string is up to ~240bytes, depending on what you are connected to. In addition you can use 2M phy, which is more power efficient.

    Alternative solution:

    Since the issue is that you are filling up the TX buffer, you have to spread out the packets. You can still have your timer firing every 120ms, and call ble_nus_data_send() until it returns BLE_ERROR_NO_TX_PACKETS. This means that the softdevice buffer is full, and the last packet that you tried to queue is not queued successfully. However, all the packets that returned NRF_SUCCESS is successfully queued, and will be sent.

    If you look inside ble_nus_string_send(), it is actually sd_ble_gatts_hvx() that returns BLE_ERROR_NO_TX_PACKETS. You should then wait for an event called BLE_EVT_TX_COMPLETE in on_ble_evt() in main.c (you have to add this event check. Just add it in between two other event cases).

    When this event occurs, it means that at least one packet has been transmitted successfully and the softdevice has received an ACK. This also means that some space in the softdevice TX queue is freed up, and you can try to queue more packets.

    Basically, you are looking for something like:

    volatile bool m_queue_full = false;
    volatile uint8_t m_packets_to_send = 0;
    
    on_ble_evt()
    {
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                ...
                break;
            ...
            
            case BLE_EVT_TX_COMPLETE:
                queue_full = false;
            
            default:
                break;
        }
    }
    
    
    void my_timeout_handler()
    {
        m_packets_to_send = 6;
    }
    
    
    int main()
    {
        ...
        for (;;)
        {
            while (packets_to_send && !m_queue_full)
            {
                err_code = ble_nus_string_send()
                {
                    if (err_code == NRF_SUCCESS)
                    {
                        packets_to_send--;
                    }
                    else if (err_code == NRF_ERROR_NO_TX_PACKETS)
                    {
                        m_queue_full = true;
                    }
                    else
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
            }
        }
    
    }

    Best regards,

    Edvin

Reply
  • Hello,

    You can check the throughput on BLE with different connection settings here.

    Using SDK12.3.0, the throughput isn't great, because this was before BLE5 came, with higher throughput options, so the throughput you are looking at is GATT server - ATT_MTU 23 - 1MB Phy, so 192kbps  = 24kBps.

    6 * 20B every 120ms = 1kBps = 8 kbps, so you are within the limits.

    The issue is that this throughput limitation is continuous, while you are sending bursts of 120 bytes, which is too much for the softdevice to store away.

    Possible solutions:

    I see that you use the nRF52832. I suggest that you go to SDK15.2.0, the latest softdevice. Here the size of ble_nus_data_send() (the new name for ble_nus_string_send) string is up to ~240bytes, depending on what you are connected to. In addition you can use 2M phy, which is more power efficient.

    Alternative solution:

    Since the issue is that you are filling up the TX buffer, you have to spread out the packets. You can still have your timer firing every 120ms, and call ble_nus_data_send() until it returns BLE_ERROR_NO_TX_PACKETS. This means that the softdevice buffer is full, and the last packet that you tried to queue is not queued successfully. However, all the packets that returned NRF_SUCCESS is successfully queued, and will be sent.

    If you look inside ble_nus_string_send(), it is actually sd_ble_gatts_hvx() that returns BLE_ERROR_NO_TX_PACKETS. You should then wait for an event called BLE_EVT_TX_COMPLETE in on_ble_evt() in main.c (you have to add this event check. Just add it in between two other event cases).

    When this event occurs, it means that at least one packet has been transmitted successfully and the softdevice has received an ACK. This also means that some space in the softdevice TX queue is freed up, and you can try to queue more packets.

    Basically, you are looking for something like:

    volatile bool m_queue_full = false;
    volatile uint8_t m_packets_to_send = 0;
    
    on_ble_evt()
    {
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                ...
                break;
            ...
            
            case BLE_EVT_TX_COMPLETE:
                queue_full = false;
            
            default:
                break;
        }
    }
    
    
    void my_timeout_handler()
    {
        m_packets_to_send = 6;
    }
    
    
    int main()
    {
        ...
        for (;;)
        {
            while (packets_to_send && !m_queue_full)
            {
                err_code = ble_nus_string_send()
                {
                    if (err_code == NRF_SUCCESS)
                    {
                        packets_to_send--;
                    }
                    else if (err_code == NRF_ERROR_NO_TX_PACKETS)
                    {
                        m_queue_full = true;
                    }
                    else
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
            }
        }
    
    }

    Best regards,

    Edvin

Children
  • Thanks for your quick reply. Well as my whole project is based on SDK12.3 so migrating to 15.2 is not easy at this time so I will prefer to go with you alternative solution proposed.

    To know that my soft-device buffer is full, I am reading counter "p_ble_evt->evt.common_evt.params.tx_complete.count" which is always 1 and since I am also getting  BLE_EVT_TX_COMPLETE on every packet send ( 6 times within 120ms, so does this mean that my buffer is not queuing for some reason?

  • I am a bit confused. Didn't you say you got BLE_ERROR_NO_TX_PACKETS?

    I guess the tx_complete.count says how many packets that was ACKed, in case the SD hasn't had time to issue the event in between the two packs. I haven't really looked into that parameter before.

    Do you mean that you tried that method, to queue another pack on TX_COMPLETE, and then you get NRF_SUCCESS on all ble_nus_string_send() calls? 

    What do you mean that your buffer is not queuing? Do you see the data on the other side of the link? 

    BR,

    Edvin

  • Thanks Edvin, after moving to the SDK15.2.0, I finally able to send 1kBps easily, also I have tried to send data at 4kBps without any issue.

Related