代码之家  ›  专栏  ›  技术社区  ›  jpo38

使用Qt-vista风格的小部件使我的数据采集更快…为什么?

  •  0
  • jpo38  · 技术社区  · 5 年前

    我使用的是一个北欧开发板(pca1040,nRF52832),带有经过修改的“Nordic\HRM”固件,通过蓝牙低能量以100Hz发送20字节的数据包。

    我所经历的非常奇妙:

    • enter image description here

    • QApplication QDialog enter image description here

    • 更有趣的是,如果我删除Qt风格的插件 qwindowsvistastyle.dll 从我的安装文件夹,然后图形用户界面是巨大的,然后没有办法你可以得到100Hz了,你被困在65Hz。我知道这也很难相信,所以我做了另一个视频;-) enter image description here

    注意,我试图在任务管理器中将进程优先级更改为“High”,但这显然没有效果。

    问题是:

    • 有人能解释一下这是怎么回事吗?
    • 我不必担心win32控制台应用程序能够以100Hz的频率检索数据。但我真的很担心我的Qt应用程序能够做到这一点,而不需要用户不断地移动鼠标在一个按钮上…有什么可以做的(在QApplication级别,Windows级别,Nordic驱动程序级别…)?

    MCVE代码:

    我的对话.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();
    }
    

    编辑

    1. 我意识到这个问题不是100%可复制的。有时,控制台软件也能在我的计算机上以100Hz的频率检索数据,有时不能。我觉得在电脑开了一段时间,我做了很多测试之后,它开始以100Hz的频率工作。当我关掉电脑再打开时,它总是回到65Hz的数据速率。。。。

    2. 我在pc-ble驱动程序代码中添加了更多的数据速率监控,并重新编译了它。一个在红色的线程( SerializationTransport::readHandler UartBoost::readHandler

    当以100Hz接收数据时,我看到:

    UartBoost::readHandler: 000213, pkt/s: 212.362900
    UartBoost::readHandler: 004315, bytes/s: 4302.093750
    SerializationTransport::readHandler: 000103, pkt/s: 102.385681
    pkts: 000102, pkt/s: 102.000000
    

    当以65Hz接收数据时,我看到:

    UartBoost::readHandler: 000061, pkt/s: 60.157787
    UartBoost::readHandler: 002570, bytes/s: 2534.516602
    SerializationTransport::readHandler: 000061, pkt/s: 60.157787
    pkts: 000061, pkt/s: 60.157787
    

    令人惊讶的是 UartBoost::readHandler 数据速率(字节/秒)从4302降低到2534(与最终采样率相同,该比率降低了约40%),而每秒的数据包数(pkt/s)则减少了71%(从212减少到60)。BLE加密狗发送的数据少了35%,但使用的数据包少了71%…我不知道该怎么总结。

    1. 在UartBoost::readHandler中添加了以下代码:

    添加了以下内容:

    std::cout << std::hex; 
    for ( size_t pos = 0; pos != bytesTransferred; ++pos ) 
        std::cout << (unsigned) readBufferData[pos] << " "; 
    std::cout << std::endl;
    

    如您所见,数据包被拆分。在65Hz时,每个数据包都是完整的通知。在100Hz时,数据包被拆分,这意味着需要多次读取才能获得完整的通知。这就解释了为什么在65Hz时,我们接收的字节少了一些,但数据包却少了很多。

    https://pastebin.com/FyFwR0yJ

    非常类似的情况下,我们有65赫兹,但约35线以上。这是意料之中的。

    所以看起来Windows或驱动程序在某些方面更喜欢发送更少的数据,但以更干净的方式(不拆分数据包)…再次,我不明白为什么。

    0 回复  |  直到 5 年前