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

Using a Qt vista style Widget makes my Bleutooth data acquisition faster…why?

I'm using a Nordic dev board (PCA10040, nRF52832) with modified "Nordic_HRM" firmware sending packets of 20bytes at 100Hz over Bluetooth Low Energy.

I'm using Nordic's heart_rate_collector example to retrieve the data on a Windows 10 computer using Nordic's USB BLE dongle (PCA10031). I'm using version 2.2.1 of the pc-ble-driver. I modified the example code to report the data frequency of the last second (it originally reports the average data frequency for the whole session)

What I experience is very wierd:

  • The heart_rate_collector example (win32 console app) retrieves data only at 65Hz. So looks like 35% of the data are being lost. I originally believed 100Hz sampling rate was too high for a BLE connection...
  • - But, funny thing is that if I add a very simple GUI (QApplication and QDialog) to the project, then teh program is eventually able to receive data at 100Hz....but it depends on the mouse activity! When the mouse moves around a button, frequency jumps to 100Hz, when it's static, it drops to 65Hz. I know it's hard to believe, so I did a video ;-)
  • - And, even more funny, if I remove the Qt style plugin qwindowsvistastyle.dll from my installation folder, then GUI is hugly and then there is no way you can get the 100Hz anymore, you're stuck to 65Hz. I know it's also hard to believe, so I did another video ;-)

When you are using vista display style, when the mouse moves around a button, you see Qt does some repaint to draw the button focus. And I'm wondering if this probably reports to Windows that the process needs more attention and finally makes the OS give more attention to this process and then it looses less data?

Note that I tried to change the process priority to "High" in the task manager but this apparently has no effect.

Question is/are:

  • Can anyone explain what's going on here?
  • I'm not necessarily concerned about having the win32 console app be able to retrieve the data at 100Hz. But I'm really concerned about having my Qt app be able to do that, without requiring the user to be constantly moving his mouse around a button....is there anything that could be done (at QApplication level, Windows level, Nordic driver level....)?

------------------------------------
The MCVE code:

mydialog.h:

#pragma once

#include <QApplication>
#include <QDialog>
#include <QPushButton>
#include <QVBoxLayout>
#include <QShowEvent>
#include <QLabel>

class MyDialog : public QDialog
{
    Q_OBJECT

public:
    MyDialog();
    ~MyDialog();

    void showEvent( QShowEvent* event ) override;

public slots:
    void toggle();
    void notify( uint32_t count, float freq );

private:
    int run();
    uint8_t cccd_value;
    uint32_t close();

    QLabel* label;
};

main.cpp (modification of Nordic's main.c), fully available in pastbin

...

static MyDialog* notify_dialog = NULL;
static void on_hvx(const ble_gattc_evt_t * const p_ble_gattc_evt)
{
    clock_t now = clock();

    if (!m_hvx_start) {
        m_hvx_start = now;
    }

    m_hvx_count++;

    float seconds = (float)(now - m_hvx_start) / CLOCKS_PER_SEC;

    if ( seconds >= 1 )
    {
        float pkt_per_sec = m_hvx_count / seconds;

        if ( notify_dialog )
            notify_dialog->notify( m_hvx_count, pkt_per_sec );

        printf("pkts: %06d, pkt/s: %f\n", m_hvx_count, pkt_per_sec);

        fflush(stdout);

        // reset counters
        m_hvx_start = clock();
        m_hvx_count = 0;
    }
}

...

MyDialog::MyDialog() 
{
    setLayout( new QVBoxLayout() );
    QPushButton* button = new QPushButton( "Toggle", this );
    connect( button, SIGNAL(clicked()), this, SLOT(toggle()) );

    layout()->addWidget( button );
    layout()->addWidget( label = new QLabel( this ) );

    notify_dialog = this;
}

MyDialog::~MyDialog()
{
    notify_dialog = NULL;
    close();
}

void MyDialog::showEvent( QShowEvent* event )
{
    QDialog::showEvent( event );
    run();
}

int MyDialog::run()
{
    uint32_t error_code;
    char* serial_port;
    physical_layer_t * phy;
    data_link_layer_t * data_link_layer;
    transport_layer_t * transport_layer;

        cccd_value = 0;

    serial_port = UART_PORT_NAME;

    printf("Serial port used: %s\n", serial_port); fflush(stdout);

    phy = sd_rpc_physical_layer_create_uart(serial_port, 1000000, SD_RPC_FLOW_CONTROL_NONE, SD_RPC_PARITY_NONE);

    data_link_layer = sd_rpc_data_link_layer_create_bt_three_wire(phy, 100);

    transport_layer = sd_rpc_transport_layer_create(data_link_layer, 100);

    m_adapter = sd_rpc_adapter_create(transport_layer);

    //sd_rpc_log_handler_severity_filter_set(adapter, SD_RPC_LOG_INFO);

    error_code = sd_rpc_open(m_adapter, status_handler, ble_evt_dispatch, log_handler);

    if (error_code != NRF_SUCCESS)
    {
        printf("Failed to open the nRF5 BLE Driver. Error code: 0x%02X\n", error_code);
        fflush(stdout);
        return error_code;
    }

    error_code = ble_stack_init();

    if (error_code != NRF_SUCCESS)
    {
        return error_code;
    }

    error_code = ble_options_set();

    if (error_code != NRF_SUCCESS)
    {
        return error_code;
    }

    scan_start();
}

void MyDialog::toggle()
{
    cccd_value ^= CCCD_NOTIFY;
    hrm_cccd_set(cccd_value);
}

uint32_t MyDialog::close()
{
    uint32_t error_code = sd_rpc_close(m_adapter);

    if (error_code != NRF_SUCCESS)
    {
        printf("Failed to close the nRF5 BLE Driver. Error code: 0x%02X\n", error_code);
        fflush(stdout);
        return error_code;
    }

    printf("Closed\n"); fflush(stdout);

    return error_code;
}

void MyDialog::notify( uint32_t count, float freq )
{
    std::stringstream str;
    str << "During the last second, received " << count << " packets, frequency is " << freq << "Hz";
    label->setText( str.str().c_str() );
}

int main(int argc, char *argv[])
{
    QApplication app( argc, argv );
    MyDialog frame;
    frame.show();
    return app.exec();
}

Parents
  • Hello,

    Thank you for the stackoverflow link. 

    I don't have any experience with Qt or GUI programming, but you were correct. I wouldn't have believed you without the short video clips :P

    What would be interesting is to see a sniffer trace from your connection while you do the mouse hovering thing. 

    I am not sure whether you are familliar with the nRF Sniffer, but it is a FW that does require another DK/dongle, but it can capture all the packets on air. Maybe it can give some hint on why the packet rate is going down.

    Check it out here. If possible, please save the trace as a .pcapng, and post it here. It would be interesting to see.

    Now, I am no C++ expert, but what type of variable is your m_hvx_count?

    Could it be some IRQ priority issue that the on_hvx() is not being prioritized when you hover the mouse over the button?

    BR,

    Edvin

  • Hello Edvin,

    m_hvx_count is just a counter of notifications. It's a uint32.

    Long time ago when I first reported this issue with 100Hz data to nordic (https://devzone.nordicsemi.com/f/nordic-q-a/32699/nrf52-fails-to-transmit-20bytes-data-at-100hz) I used the sniffer as recommanded. It did not help at all...the sniffer logs are still available here as uploaded files.

    Jean

  • Hello,

    What I really wanted to know is whether the m_hvx_count was "volatile" or not. Whether it could be that it was not actually incremented, even though you thought so, but I guess since it is incremented that probably isn't the answer. 

    There are a lot of things I don't know about your application.

    Is your device (Qt application) a central or peripheral? Is it sending or receiving notifications?

    What is your connection interval?

    Can you show me the snippet where you increment the m_hvx_count?

  • Hello Edvin,

    My device is a central. The peripheral is a "Nordic_HRM" example customized to send data at 100Hz.

    The full code is available at https://pastebin.com/mNzjg5LZ. It's nordic sample program with just a QApplication added. All information you are looking for is available here.

    Kind regards,

    Jean Porcherot

Reply Children
No Data
Related