经过前期漫长的环境搭建和配置,接下来终于到了通过写代码,进行项目的时候啦。

在此之前搭建了个conda环境,完成了两个包的下载,使得旭日X3派已具备了对USB进行读取,并且在数据进行处理后,通过mqtt进行上传服务器的基础。具体的完成比较曲折,详情也可以参考主页之前的一些文章。

本项目的思路在于,通过旭日X3派在边缘端,对USB窗口进行读取,获取到其实时的传感器数据,传感器数据原本是RS232协议进行传输的,通过一个RS232转USB装置进行转换,来实现更方便的读取。因为对数据连续性的要求比较高,接下来需要对数据进行频率的分析,所以根据采样定理,我们可知,要保证采样频率达到所需采用信号的最高频率两倍以上。所选用的传感器是200赫兹,也就是每秒钟获得200个数据。但是要保证传输的可靠性,保证尽可能低的系统占用,选择每10秒钟进行一次数据的打包和上传,打包的格式为 Json.文件。也就是说每个 Json.文件中包含有2000条数据。

首先进行USB的读取。可以看到旭日X3派上一共有三个USB口,其中两个为USB2.0,一个为USB 3.0,也就是蓝色的插口。这里就直接选用USB2.0的插口。在检查转换模块正确接线后,将其插在USB上。这里所采用的USB转Rs232转换模块是ch340芯片进行驱动, Windows上需要对其进行驱动的安装,然后即可达到即插即用的效果,而在Linux上这一点并不相同。我们所安装的Ubuntu20.0所自带的Linux内核中已经内置了ch340驱动,就不需要我们自己安装。之前我不太确定这一点,于是就打算试一试,就发现不需要安装驱动也可以正常使用。但是Linux中如果没有图形界面,并不能达到即插即用的效果,在插上以后需要对USB的插口进行扫描,判断USB所分配的名称。 Linux系统中USB所分配的名称常常是/dev/ttyUSB0 格式的。这一名称的格式对应了windows系统中大家常见的comX的格式。

ls /dev/ttyUSB*

列出系统上挂载的所有USB设备

全是我编号为/dev/ttyUSB格式的设备,类似于windows系统里面的COM

dmesg | grep ttyUSB0

用这个指令具体的查看USB0端口上所挂载的设备信息。

需要注意,由于Python中的定时模块并不是很准确,同时窗口的响应也并不是严格按照0.05秒的时间间隔进行响应,所以其实际频率在10秒进行截断的情况下,每一包数据的数据量往往在2000上下1、2进行浮动。如果严格按照2000帧的格式进行编码。那么不确定长度,对于Java和C Sharp等强类型语言在处理JSON时是致命的。同时对于人工智能模型而言,在训练和预测时,其输入的数据长度需要固定,所以建议采用当数据包大小达到2000时进行截断,而不是在10秒时进行截断,这样可以获得更加可靠的长度,为2000的数据包。

通过对时间的判断,以及最后对波形的绘制,发现传感器在读取过程中出现了粘包的问题。具体的体现是波形中出现严重的梯形现象,并且每2000帧所需要的时间远远大于10秒,也就是每秒中的帧率远远达不到200帧。经过排除发现是之前的代码中对包的大小长度的一条判断造成了这种情况。当时的判断是不等于0,而且要只等于23。这里的23是每一位个数据包标准的数据长度,但是在实际的过程中通过对包的大小打印以及分析发现。有大量的相邻两个数据包存在属于同一个而被分成两个。或者是有被分成两个后其中一个与旁边的完整的包黏在一起,甚至发生两个完整的包粘在一起的情况。这种情况造成了大量不等于23长度的数据的出现。

经过分析后决定加入了一级缓存,首先尝试了固定大小缓存,但是此举在有连续两帧被分开时并不可靠,此时李家河将超管的散而成为46或69。后改为达到单帧大小整数倍;

随后出现了在十秒数据完成采集后,进行打包发送与存档,延迟时间较长,造成传感器自身缓存达到十桢以上,严重影响了数据的连续性。

如图是波形在不正常,有粘包现象时所收集到的数据波形。可以看到相邻的数据间有大量相等的数据。

于是编写了子进程函数,将打包 发送和写文件三个动作放在子进程处理,每次对子进程传参整个字典,防止阻塞主线程。

经过仔细思考以后将缓存改为了不固定大小,而在每帧时对数据进行判断,看其是否达到23的倍数,若达到23的倍数即进入打包进程。这一操作将使得分包和并包更为灵活;而每针的时间则改为通过对每一次缓存的开头和结尾时间进行截取,然后根据其对23的倍数进行分时得出其中间点。这一操作时的采样的灵活性和速度性能都得到比较好的兼顾。

随后遇到了在进入十秒周期一开始就遇到不完整的问题,造成缓存始终无法达到要求,于是在每次进入周期时,先确保首帧的完整性,避免只有后半针被读入缓存,永远无法达到23倍数的情况。

经过测试,可以达到200hz的速度。同时也排除了json清除不正常的问题,解决了先前四次发送后报错的问题。

至此,对于传感器数据的读取以及分包和包的操作就全部完成了。可以看到,只是对传感器数据的读取是较为简单的,但是在读取的过程中会遇到大量的问题,因此需要在使用的过程中格外注意。

下面放上一张传感器正常工作时的图片,可以看到它有非常好的连续性,看起来让人爽心悦目。