[全幅表观采集开发日志2]从一次数据报错开始,简单聊聊串口通信的查错方案和开发思路

串口通信相关 - 一次Debug日志

目前项目的进度仍然是以旧的现有的采集系统为主的,也就是之前开发的全幅表观系统的采集软件。这个采集软件有这样那样的问题,有的难以解决,有的很好解决,目前比较严重的问题比较多,主要是至少要保证数据的可靠性,起码得保证数据可以正常跑通,但是这往往并不容易,所以一些常见的问题需要修改.

这次说的问题很简单,就是关于历程的数据问题。

具体有什么问题呢?这里简单阐述一下,之前的里程数据是这样的,是一个Mileage.txt文件,这个文件里面写了很多个json字符串,每一个json字符串包含的内容是ID,Mileage,Time,其中ID指代的是第几个脉冲,Mileage指代的是当前小车的历程,Time指代的是当前小车记录的时间。

image

现在的症状是TSD软件无法解析时间,会有错误,但是没有提示具体的错误是什么,所以这个症状需要慢慢检查,这个问题我也确实检查了很久,一时半会说不清楚。

但是对于这个问题,我们需要分成很多个方面去剖析,通过二分法的方式去做解答:

一、采集端和处理端

首先第一,要考虑是采集端的问题还是处理端的问题:问题显然是出现在采集端,因为采集端的代码一直在修改编译,但是处理端的代码却已经没有人维护了,是已经写死了的老软件。

当然,任何可能性都需要考虑进去。不过处理端的软件还是比较好验证,通过过往的比较成功的数据(甚至后来我们都直接拟合出了一套数据)放进软件里面,是显然正常的。所以问题没有出在处理端软件上。

不过在想这个可能性的时候就花了很长时间,因为这套数据拟合的并不是很好,不过也能明显看出效果。

总而言之,就是可以把问题确定在采集端上。

在确定这个问题之前,我们还需要明确一点,就是这个数据究竟是出了什么问题,这个也必须确定,有可能是数据偏大了偏小了,也可能是偏差较大,或者和法如的数据无法拟合,这些都有可能。

我之前有写过的那个 developerKey中有写过一个功能,就是将这个Mileage.txt文件变成两列文字,然后通过csv的功能,将这两列数据当成一个类似excel表的东西去处理。

image

然后我们在处理中发现一个问题,就是里程的问题不大,但是这个时间数据出现了明显的跳变。

也就是类似图片所示:

image

部分数据就是突然暴跌,这就导致法如的扫描仪没有办法对齐时间。

二、硬件还是软件

确认了问题所在,那就要尝试检索到问题的根本。原来是时间问题,那就必须把这个时间摘取出来进行处理。

这个时间问题可能涉及到很多方面,一是涉及到硬件串口返回的指令,可能这个指令本身就有问题

二是可能涉及到软件的处理,就是串口发送的消息是没问题的,但是接收到消息的处理出了问题,这个都是非常有可能的。

为了验证这个问题,其实最好的方法就是直接让小车跑起来,然后直测小车的数据。于是我花了半天的时间写了一个脚本,让小车运行脚本跑起来(实际上也是用Qt写的,别的软件还需要部署环境,太麻烦了,不乐意用),实测,在测试Demo状态下发现数据一切正常。

那么难道说就一定是软件的问题?其实也未必,还有可能是任务执行了,软件在运行的过程中会发生其他的串口指令任务,这导致了任务没法正常完成,这也是非常有可能的。

这个地方产生跳变的原因有很多,我一开始的想法是,有没有可能是数据出现阻塞了,就是串口产生的消息过多一下子进程处理不过来,可能把线程阻塞住了导致各种数据没法同步对齐导致的。

带着这个想法,我把写入文件的地方添加了一个多线程的处理,这样每次写入文件都会单开一个县城去写入(其实这样是不好的,没有办法保证数据是有顺序的,但是只是做一个测试)

在这个测试中,即使写入文件操作是多线程的,依然出现了跳变问题。

那还有可能是什么原因呢?

软件问题探幽

我个人对串口是不太了解的,我以为一个进程占用了串口之后就不能剥离这个进程和串口的关系否则串口就会失效。。。最后我实在没招了,想着让程序在解析里程信息的时候把接到的串口指令也一并打印出来看看效果。

正当我小车没有停止,把进程停止了之后,不记得是为什么了,当时涛哥让我打开串口调试助手,我才知道原来即使进程停止了,只要串口还在,就可以一直接受串口得来的消息。

这样随着问题的越来越深入,我最终做了这样一个测试:让原有的程序启动小车,然后这个程序要在获得里程数据之后马上放开串口,再手动打开测试程序控制串口获得数据。

这样做的目的很简单,就是模拟正常的作业流程,然后让一个第三方的程序去获取解析从串口处获得的数据,来探明具体的问题所在。

柳暗花明....吗?

最后令人惊讶的是,第三方程序获取的串口信息完全是正确的!也就是说,正常作业中的数据是完全正确的,所有的问题都在处理上。

这就奇怪了,有什么不对。

因为明明第三方程序我是完全照搬的原有的里程数据处理方案,那也就是说,这个处理模式实际上是完全照搬的,二者是实质上完全没有区别的

我自己又处理了一下生成的数据,看了一会,突然一拍脑门,怎么之前没发现这个问题?

我发现,几乎所有的错误数据都指向了这个点

image

就是这个接近6200000的数据,几乎所有的数据都到此戛然而止了。虽然这并不是一个2的幂,但是显然和真正的答案非常接近了。

没错,应该就是数值溢出,这次我重新编译了一个程序进去,通过GBK远程调试,终于发现并解决了这个问题。

原有的代码里,是从串口获取一个qulonglong类型的数字,然后通过QString::number函数转换成一个QString类型的数字方便输出和转换。

问题就出在这个QString::number类型,似乎精度有问题,其中数字的大小是超过八位的,但是输出的字符串可能只有七位甚至六位。

接下来的,只有泡杯茶,看看输出的数据,解决这个QString的精度问题就行了//虽然不知道Qt为什么会出这种问题,明明另外一个程序的处理方式完全一致,偏偏这个数值会溢出....

那是溢出吗?

今天早上我来验证了一下这个问题,发现远比我想象中的奇怪

我们来看一下这个程序是如何执行的

image

在程序中有两条时间线,其中小车的时间CarT是以脉冲的形式,隔一个tick就向着我们发送一次,所以几乎可以理解为小车的时间是完全同步的。但是法如扫描仪的时间ScannerT并不是同步的,而是隔接近一分钟才获取一次(法如扫描仪性能限制),然后计算一个detaT = ScannerT - CarT,在一个周期内所有的CarT + detaT = ScannerT,意思就是取一个临时值,让所有的小车时间都加上这个临时值,当作当前同步状态下的时间。

吗?

这个时候问题来了,按理说这个detaT可能很大,也可能很小,但是应该是一直保持不变的,因为时间的流速是一定的。不可能说同样的时间在你小车上就走得快,在你扫描仪上就走得慢,这是没道理的。

但是?我们来看一下采集到的数据,我们把明显跳变的数据单独拎出来看看:
image

这是显然错误的,首先我们可以看到,dScan和dCar是比较均匀恒定的,这就说明在采集扫描仪和小车的时间上并没有大问题。

问题出在哪呢?问题就出在这个dS - dC上,这个值远远大于0,这是显然不可能的,因为dS 和 dC显然是在同一个时间间距上做的时间记录,而他们的时间流速居然远远大于0,这显然是不可能的。

再看Scan-Car,这个值代表着扫描仪的时间和小车的时间渐行渐远了,这显然是不正常的。

柳暗花明!

那就回头看看代码,看看是哪里出了问题。

其实问题也很明显了,那就是扫描仪和小车的时间单位不相同,在询问硬件组的意见之后,小车的时间单位应该是100ns,而扫描仪的时间规格经推断大概是10ns,也就是说这个时间单位都不同,算出来的数据也显然没有意义。为了验证这个猜想,我们可以将小车的时间x10,再来做一次计算。

image

这样,小车和扫描仪的时间流速最终能统一了,Q.E.D

posted @ 2023-05-11 00:26  轩先生。  阅读(98)  评论(0编辑  收藏  举报