我使用的是一个北欧开发板(pca1040,nRF52832),带有经过修改的“Nordic\HRM”固件,通过蓝牙低能量以100Hz发送20字节的数据包。
我所经历的非常奇妙:
-
-
QApplication
和
QDialog
-
更有趣的是,如果我删除Qt风格的插件
qwindowsvistastyle.dll
从我的安装文件夹,然后图形用户界面是巨大的,然后没有办法你可以得到100Hz了,你被困在65Hz。我知道这也很难相信,所以我做了另一个视频;-)
注意,我试图在任务管理器中将进程优先级更改为“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();
}
编辑
-
我意识到这个问题不是100%可复制的。有时,控制台软件也能在我的计算机上以100Hz的频率检索数据,有时不能。我觉得在电脑开了一段时间,我做了很多测试之后,它开始以100Hz的频率工作。当我关掉电脑再打开时,它总是回到65Hz的数据速率。。。。
-
我在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%…我不知道该怎么总结。
-
在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或驱动程序在某些方面更喜欢发送更少的数据,但以更干净的方式(不拆分数据包)…再次,我不明白为什么。