前言

    在《QT串口动态实时显示大量数据波形曲线(一)》和《QT串口动态实时显示大量数据波形曲线(二)》中介绍了串口编程和chart绘图编程。也介绍了chart和customplot绘图的基本区别。customplot绘图在代码上非常简单,不用点,线,坐标系和图表一层一层的放那么麻烦。 

   第一部分: 串口接收大量数据动态显示的难点

    串口大量数据QT接收时问题的原因:

    (1)10ms40个8位数。在示波器上监视串口波形,其实这个总线负载率差不多到了60%。如果再想传输更多的数据,只能利用更高的波特率,但是119200差不多是最高的波特率了,更高的只能自己去编写代码,比较麻烦。将总线负载率进一步升高。底层的传输机制不太允许(底层芯片的DMA传输已经用上),传输数据太多容易引起错误码。

    (2)上层串口接收机制不完善,也就是《一》中介绍的串口接收readyread函数和readall函数的问题,所以传输数据不能进一步增加。进一步增加之后接收中断(暂时这样叫吧)次数也随之增加,影响绘图时间,同时接收的数据会出现丢点现象,这一点我在试验时验证过,接收数据太多就会丢点。

    (3)接收数据多之后,绘图就会增加。数据点增加不会大幅度增加时间,但是增加图表数量会增加程序执行时间,对串口的接收造成影响。这一点也经过验证。

    选择customplot绘图的原因:

    (1)程序简单,(2)图表多种多样,好看,(3)手势程序简单(观察波形时使用)

第二部分:准备工作

    (1)文件添加,网上下载customplot的c文件和h文件,放入文件夹里。切记不要不和整体文件放在一起,否则拷贝文件的时候会带来不便。用MDK和CCS编写程序的时候很忌讳这点,头文件啥的最好和主程序文件放一起,或者整体文件的单独的文件夹下。

qt 做数据分析 qtchart大量数据_面向对象编程

    (2)pro文件中加入以下程序,包含绘图,串口,系统。最后一个就是customplot绘图的。

QT       += charts core gui serialport widgets printsupport

    (3)打开项目中,项目中添加以下文件。添加方式“右键”就可以了。

qt 做数据分析 qtchart大量数据_数据可视化_02

    (4)c文件和h文件里面添加以下程序,也就是include语句

#include "qcustomplot.h"

第三部分:UI界面添加模块

    (1)找到container里面的widget模块,拉到ui界面里面。

qt 做数据分析 qtchart大量数据_qt 做数据分析_03

    (2)“右键”widget模块,点击“提升为”,弹出对话框。手动在提升的类名称里面输入QCustomPlot,注意一定要大小写都对,所有字母都对,错一个都不行,别问我为啥,说多了都是泪。添加完一次之后就会自动在框里显示了,下次就不用手动输入了,直接选就行。然后换object名字,

qt 做数据分析 qtchart大量数据_面向对象编程_04

第四部分:初始程序

    这部分就简单了,直接上程序。

ui->PLOTVSAMP->addGraph();
    ui->PLOTVSAMP->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ScatterShape::ssPlus,5));
    ui->PLOTVSAMP->addGraph();
    ui->PLOTVSAMP->graph(1)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ScatterShape::ssCross,5));
    ui->PLOTVSAMP->xAxis->setLabel("TIME");
    ui->PLOTVSAMP->xAxis->setRange(0,101);
    ui->PLOTVSAMP->yAxis->setRange(-10,10);

    第一句添加图表,就是直接放到刚才你在ui界面的widget区域,第二句把第一条曲线放进去,然后放第二条。后三句设置坐标轴的信息。比chart要简单的多。其实在我自己的程序中加入了6条曲线graph,这里仅仅拿出来2个作为例子。这部分非常占用时间,如果不在ui->setupUi(this)里面定义这些东西的话,在槽函数里定义的话,那完蛋了,槽函数执行时间过长,可能会影响你下次槽函数的执行。

第五部分:显示程序

数组,

QVector<double> gvUTCms(100);
        QVector<double> gvVsuAmp(100),gvVsvAmp(100),gvVswAmp(100);

    定义的时候只能在子函数里面定义,不能全局定义,现在还没找到能全局定义的方法。百度之后也没找到,有,但是弄过来没啥用,不知道为啥。这个变量定义只能在一个子函数里面用,再加一个子函数,不好意思,系统报错。这个比较头疼。

ui->PLOTVSAMP->graph(0)->setData(gvUTCms,gvVsuAmp);
        ui->PLOTVSAMP->graph(1)->setData(gvUTCms,gvVsvAmp);
        ui->PLOTVSAMP->graph(2)->setData(gvUTCms,gvVswAmp);
        ui->PLOTVSAMP->replot();

    这个就是画图程序,直接放数据,然后replot就可以了。

    这次画图中,chart的手势啥的都不能用了,customplot比那个方便的多。

ui->PLOTVSAMP->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);

    直接加入上面程序,在观察波形的时候就可以直接滚轴查看了,非常的方便,并且也仅仅添加这句程序就行了。

    这个就是应该就是customplot方便的地方,给你编写好的库函数,直接设置就好了。这点和STM32的HAL库有点类似。麻烦的地方就是:你不知道他有这个库函数,你不知道他有这个命令,哎,只能用到啥去查啥了,用了一次就知道了。

第六部分:其他

    做按钮转换坐标轴的时候发现了一个问题,只有下面指令执行后,坐标轴和其他绘图信息才会改变。

ui->PLOTVSAMP->graph(0)->setData(gvUTCms,gvVsuAmp);
ui->PLOTVSAMP->replot();

    也就是说,只能绘点的程序启动后,坐标轴和图的信息才会改变。没看过这个的底层函数,所以只能这样大概的推测一下。

第七部分:项目总结

    整个软件编写从接触QT到完成测试经历2个星期,中间包含了串口接收程序,ui显示制作,数据处理程序,绘图程序几个部分。初步了解了面向对象编程的简便性。开始接触QT时,感觉程序啥的都看不懂,并且不是逻辑顺序执行程序,思维方式不大相同。最后硬着头皮看了相关资料,视频和例程才慢慢看懂程序。中间编程时,有些地方编译不过,很是难受,找了很多资料也都没有办法用,只能一点一点的试,最后实在不行,就推倒程序重新来,过程很痛苦。最后软件差不多完成时,又遇到丢点的问题,设计到性能提高,这块是比较费时间的,并且是比较难的。

    如果需要程序源码,请留下邮箱,会打包发送。