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 Reply Children
No Data
Related