【Qt系列】基于QChart的超声波传感器数据动态可视化实现【精简串口方案】

张开发
2026/4/19 13:52:52 15 分钟阅读

分享文章

【Qt系列】基于QChart的超声波传感器数据动态可视化实现【精简串口方案】
1. 项目背景与需求分析最近在做一个超声波测距项目需要实时显示传感器采集到的距离数据。网上找了一圈发现大多数串口助手只能显示文本数据缺少直观的曲线展示功能。于是决定自己动手用Qt的QChart组件开发一个精简版可视化工具。这个方案最大的特点就是轻量级和定制化。相比功能繁杂的商业串口工具我们只保留核心的数据接收和曲线绘制功能。实测下来整个工程代码量不到300行但完全能满足超声波数据监控的需求。特别适合嵌入式开发、物联网设备调试等场景。先说说硬件部分。超声波传感器通过串口发送距离数据格式通常是ASCII字符串或二进制浮点数。我的方案兼容这两种格式自动完成数据解析。软件架构分为三个模块串口通信负责设备连接和数据接收数据处理将原始数据转换为可绘制的数值曲线展示用QChart实现动态更新2. 开发环境搭建2.1 Qt环境配置首先确保安装了Qt Creator和必要的模块。打开项目的.pro文件添加这两个关键依赖QT serialport charts遇到编译报错的话检查Qt安装时是否勾选了Qt Charts模块。我在Windows平台实测时发现如果通过在线安装器安装Qt默认可能不包含这个组件需要手动勾选。2.2 界面设计使用Qt Designer拖拽几个核心控件QComboBox选择串口号QPushButton连接/断开按钮QPlainTextEdit显示原始数据QChartView用于绘制曲线布局可以参考这个结构Vertical Layout ├─ Horizontal Layout (串口控件区) └─ Vertical Layout ├─ QChartView (曲线区域) └─ QPlainTextEdit (数据日志区)3. 核心代码实现3.1 串口通信模块创建serial.h头文件继承QMainWindow类。关键成员变量包括QSerialPort global_port; // 串口对象 QTimer *m_timer; // 数据更新定时器串口初始化函数要完成三件事扫描可用端口配置默认参数115200波特率、8数据位建立信号槽连接void SerialInit() { // 扫描端口 foreach(const QSerialPortInfo info, QSerialPortInfo::availablePorts()) { ui-comboBox-addItem(info.portName()); } // 连接信号槽 connect(global_port, QSerialPort::readyRead, this, MainWindow::handleData); }3.2 数据解析逻辑超声波传感器通常返回类似123.45cm的字符串。我们需要提取数字部分void handleData() { QByteArray raw global_port.readAll(); QString str QString(raw); // 正则匹配数字 QRegularExpression re((\\d\\.?\\d)); QRegularExpressionMatch match re.match(str); if(match.hasMatch()) { float distance match.captured(1).toFloat(); updateChart(distance); } }对于二进制浮点数据更简单float distance; memcpy(distance, raw.constData(), sizeof(float));3.3 动态曲线绘制QChart的使用分四个步骤创建图表基础m_chart new QChart(); m_chartView new QChartView(m_chart); m_chart-setTitle(超声波距离监测);配置坐标轴QValueAxis *axisX new QValueAxis; axisX-setRange(0, 100); // 初始显示100个点 axisX-setTitleText(时间); QValueAxis *axisY new QValueAxis; axisY-setRange(0, 500); // 假设最大测距500cm axisY-setTitleText(距离(cm));创建曲线序列QSplineSeries *series new QSplineSeries(); series-setName(实时数据); m_chart-addSeries(series);动态更新数据void updateChart(float value) { static int x 0; series-append(x, value); // 自动滚动显示 if(x 100) { axisX-setRange(x-100, x); } }4. 性能优化技巧4.1 数据采样控制实测发现超声波模块的更新频率可能高达50Hz。如果每个数据点都立即绘制会导致曲线更新过快视觉上无法分辨CPU占用率飙升解决方案是加入数据缓冲// 在类定义中添加 QVectorQPointF buffer; int maxPoints 20; // 每20个点更新一次 void handleData(float value) { buffer.append(QPointF(counter, value)); if(buffer.size() maxPoints) { series-append(buffer); buffer.clear(); } }4.2 内存管理长时间运行后曲线数据可能积累过多。需要定期清理历史数据// 保留最近1000个点 if(series-count() 1000) { series-removePoints(0, series-count()-1000); }4.3 界面响应优化在主线程中直接处理串口数据可能造成界面卡顿。推荐的做法是使用QSerialPort的readyRead信号触发数据读取将耗时的数据处理移到工作线程通过信号槽将结果传回主线程更新UI5. 实际应用案例最近用这个工具调试了一款工业测距传感器分享几个实用技巧数据校验在串口通信中加入CRC校验避免错误数据影响曲线bool checkCRC(QByteArray data) { quint16 crc /*计算CRC值*/; return crc /*解析的CRC值*/; }异常值过滤超声波可能返回错误的最大值如9999if(value 500) { // 合理范围检查 return; }多曲线对比扩展支持同时显示多组传感器数据QSplineSeries *series1 new QSplineSeries(); QSplineSeries *series2 new QSplineSeries(); m_chart-addSeries(series1); m_chart-addSeries(series2);这个方案经过三个项目的实际验证稳定性很好。代码已上传到GitHub需要完整工程的朋友可以私信我获取。遇到具体实现问题也欢迎交流讨论。

更多文章