This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE_GATTS_EVT_HVN_TX_COMPLETE event does not works on NUS for multi-role device

Hi,

In a multi-role central-peripheral code for a nRF52840-DK based device, I have to send a buffer acting as a peripheral. I use the ble_nus_data_send function sent as a trigger in the BLE_GAP_EVT_CONNECTED (into the ble_evt_handler function). So, I send the first data packet once the connection as peripheral has been established.

The rest of the buffer was expected to be sent using the BLE_GATTS_EVT_HVN_TX_COMPLETE event into the ble_evt_handler function. However, the event does not never occurs.

In fact, when I execute ble_nus_data_send the first time, it returns a NRF_ERROR_INVALID_STATE because it detects a condition ike !p_client->is_notification_enabled.

I have tried to clone the NUS configuration (as a peripheral) from the ble_app_uart example, working using the nRF5_SDK_17.1.0_ddde560. And including the sdk_config.h file configuration.

What should I setup to enable the BLE_GATTS_EVT_HVN_TX_COMPLETE event? Should I use another event?

Thank you very much in advance.

Best Regards,

Joel

Parents
  • Hi Joel,

    I cannot think of any situation where you would not get a BLE_GATTS_EVT_HVN_TX_COMPLETE notification as long as the notification/indication is successfully sent. If it is, it should always arrive, though you might not get the same number of BLE_GATTS_EVT_HVN_TX_COMPLETE events as you send notifications, as the same event can cover more than one notification (in that case, the count field informs you how many notifications has been sent).

    Could it be that you are for instance filtering on the wrong connection handle, and therefor do not see the events? This is just a guess, though.

    If you don't make progress, perhaps you can share your event handling code here so that I can see if I spot anything?

  • Hi Einar,

    The definition is:

    BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);

    The initialization is:

        ble_nus_init_t   nus_init;

        memset(&nus_init, 0, sizeof(nus_init));
        nus_init.data_handler = nus_data_handler;
        err_code = ble_nus_init(&m_nus, &nus_init);

    In the ble_evt_handler. In the BLE_GAP_EVT_CONNECTED event it discriminates if it works a central device or like a peripheral. In this second case it executes the next:

                    m_per_con_handle = p_gap_evt->conn_handle;
                    NRF_LOG_INFO("Peripheral connection 0x%x established.", m_per_con_handle);    
                    
                    app_timer_start(m_post_message_delay_timer_id, APP_TIMER_TICKS(2000), 0);
                    
                    app_timer_stop(m_adv_led_blink_timer_id);
                    
                    bsp_board_led_on(PERIPHERAL_ADV_CON_LED);
                    punter_buffer_accelerometre= 0;
                    num_rebuts_buffer_accelerometre= 128003;
                    send_data_ble_accel();

    Into the function send_data_ble_accel function the code executes

                   err_code = ble_nus_data_send(&m_nus, data_buf, &length, m_per_con_handle);

    If I debug this function in this stage I can see that the notification is not enabled.

    As a peer I'm using a second nRF52840-DK board running the ble_central_and_peripheral\experimental\ble_app_att_mtu_throughput example. Here I select the buttin 4. This board establish the connection as a central device and recognizes the other board.

    Regards,

    Joel

  • Hi Einar,

    I send the reply from this message.

    Throughput are controlled by several factors. Assuming you try to send notifications as fast as possible, you primarily want to look at the connection interval and event length, as well as the packet length. Also, remember that for a multi link and multi role peripheral the stack needs to allocate time for each link in each role, so you will never get a very high throughput compared to what you get with a single link. If you want to test for yourself, you can set for instance both the event length and connection interval to a equal value which is (say) 100 ms and only support a single peripheral link (do adjust NRF_SDH_BLE_TOTAL_LINK_COUNT, NRF_SDH_BLE_CENTRAL_LINK_COUNT and NRF_SDH_BLE_PERIPHERAL_LINK_COUNT) accordingly etc. Then you should see that you are able to get a decent throughout. As you add more connections (you don't need to actually establish them, just configure support for it, so that the SoftDevice will take it int

    I have made all the setup tests of MTU value, data length and connection interval using the ble_app_att_mtu_throughput example. MUT of 247, data length of 244 bytes and a connection intervbal of 50ms or 100ms get the best results. However, there is a big difference using that example compared to my new application.

    I understand that to get the necessary throughtput I will have to close temporarily the services not used. For example, disable the nus_c service while I need to connect the big volume of information to the phone app. Is it possible to change this' Could you suggest any example, please?

    Moreover, is there a way to dinamically change and adjust the number of peripheral links in execution mode?

    Regards,

    Joel

  • Hi Joel,

    jinvers said:
    I have made all the setup tests of MTU value, data length and connection interval using the ble_app_att_mtu_throughput example. MUT of 247, data length of 244 bytes and a connection intervbal of 50ms or 100ms get the best results. However, there is a big difference using that example compared to my new application.

    Have you adjusted the event length? Looking at the project you attached here NRF_SDH_BLE_GAP_EVENT_LENGTH is set to 12, which is 15 ms. For maximum throughput this should be as large as possible (up to the connection interval). There is also the important point that you need to fit all connections within this though, so if you have up to 8 connections with the same interval as a central role for instance, that means the event length can be only an eight of the connection interval. Please note the key point here, that number of connections is a very important factor for maximum throughput.

    jinvers said:
    I understand that to get the necessary throughtput I will have to close temporarily the services not used.

    I am not sure what you mean by close the service, but if a service is not used (so no data is passed in any way on it's characteristics), it is not used and does not have any consequences (other than that the service discovery might take more time if you have a lot of services). Also, there is no support for disabling services in the SoftDevice BLE stack.

    jinvers said:
    Moreover, is there a way to dinamically change and adjust the number of peripheral links in execution mode?

    You can control how many links you have, but not the links you configure the SoftDevice for. That is configured when you initialize the SoftDevice.

  • Hi Einar,

    I have increased the NRF_SDH_BLE_GAP_EVENT_LENGTH value. Considering that in the ble_app_att_mtu_throughput the value is 400 and that here I have a total of 8 connections, I have setup a value of 3200 (just to test a extrem value). The throughput has been increased and I have reduced the time for transmitting 125KBytes to around 5 seconds.

    I have also tried to reduce the number of communications from 8 to 4. But the throughput has not increased.

    Regatds,

    Joel

  • Hi Joel,

    125 kB in 5 seconds is about 200 kbps, which is actually quite a decent throughput. With a 1 Mbps PHY the maximum you can achieve in practice is about 700 kbps, but a normal application will typically see significantly less as this depends on several factors you typically cannot control, especially if you are communicating with a phone. If you want to try to squeeze out more you could make a sniffer trace to see what happens on the link. It could be that the nRF has more data (so the MD field set), but the phone has other things to do - like WiFi, other BT links, or something else. 

  • Hi Einar,

    I will try to run a sniffer.

    Anyway, may it be that I could also be tricked by the LOG information. I mean that I display Log NRF_LOG_INFO lines in the debug window to see the 125Kbytes sent. But in some of the lastest tests done to compare with the ble_app_att_mut_throughput example, I would say that the packets have been sent but there is still a queue of Logs messages to be displayed. So, perhaps the queue of NRF_LOG_INFO lines is tricking me. I have to double check.

    Regards,

    Joel

Reply
  • Hi Einar,

    I will try to run a sniffer.

    Anyway, may it be that I could also be tricked by the LOG information. I mean that I display Log NRF_LOG_INFO lines in the debug window to see the 125Kbytes sent. But in some of the lastest tests done to compare with the ble_app_att_mut_throughput example, I would say that the packets have been sent but there is still a queue of Logs messages to be displayed. So, perhaps the queue of NRF_LOG_INFO lines is tricking me. I have to double check.

    Regards,

    Joel

Children
  • Hi Einar,

    I'm using the nRF Sniffer with Wireshark and a nRF52840-DK board. I'm able to see the advertising paquets from the aggregator, but it cannot capture no one paquet of the 125kBytes sent by notifications.

    I'm filtering for RSSI level. Any suggestion for any specific setup?

    Regards,

    Joel

  • Hi Einar,

    I have used the nRF Connect phone app to measure the time for receiving the 125KBytes notifications.

    After desabling the scanning from the aggregator (to update its peripheral devices status), I have measured 2.5 seconds for sending the 125KBytes from the aggregator and being received by the nRFConnect app.

    So, I believe now this could be enough for the application.

    Anyway, if you could help me to improve the management of the nRF Sniffer for the future, it would be welcomed.

    Regards,

    Joel

  • Hi Joel,

    Good to hear you got a satisfactory throughput.

    Regarding the sniffer, you must configure the sniffer to "follow" the device when it is advertising, before the connection happens. As long as you do, and the sniffer does not miss the connection indication packet, it will also follow the connection (see Sniffing a connection involving a single Peripheral).

Related