Sailor 简介
Sailor 简介
对于一个做控制的人来说,一个合适的串口示波器是必要的,同时还需要考虑实时性稳定性等多个方面,从效率来看,个人感觉 printf("%d,%d,...",&data1,&data2,...)
这种协议应该是首先就需要排除的,因为从数据本身来看,它浪费了大量的数据传输带宽,就算是打印一个 1.00001
这样一个简单的数据,也需要至少传递7-byte
(并且随数字大小会发生改变),而一个float
数据的完整表达只需要 4-byte
,在相同波特率下,显然同时间内后者可以提供精度更高,数量更多的数据,以及对于相同数据量,后者也可以明显的缩短传输时间,大家不妨算算对于传统波特率 115200
以10ms
为周期的刷新率,可以传递的最大数据量其实不能大于 115.2-byte
,对于方式二则可以传递 28个float或int数据
,这个传输速率是硬件固有的、我们没法改变,但是当大家使用网上的串口示波器大可按硬件属性上限算一下最高刷新率,对于使用 printf
打印数据的示波器打着 1khz
刷新率这种就显得可笑了。在此我自身不愿意浪费数据带宽、同时我希望刷新频率不受限于软件本身,数据长度也不受限于软件本身,简言之就是数据量小时可以传递较少的数据,也就可以提高刷新率,如果要传递较多的数据,就可以减小刷新率,而这个刷新率则由下位机自行决定发送周期(需要考虑硬件上限),再直白点就是协议需要满足尽可能不浪费数据带宽的情况下实现不定长的数据收发,因此制定合适的协议是必须的。
对于以上问题,我们可以拿出 12-byte
,作为协议的最短数据长度,其中包含一些必要的数据内容如数据帧头(包含帧头、扩展帧数据长度、crc校验)、设备类型、设备ID、数据ID和尾部校验,我们可以先解析帧头(这是固定长度,检测相对简单),以获取完整的数据帧长度,之后再对整个数据帧进行检验即可,如此就解决了不定长收发数据的问题,同时考虑数据内容的准确性,避免数据因为一些不必要的因素造成干扰,拿出 2~3byte
的数据带宽来做CRC数据校验是值得的,如此一来,从理论上分析其数据量会比传统串口示波器效率高很多,而且不定长的机制可以让用户按需求调整自己的数据量和刷新频率。
在上面我们已经从理论上解决了如何制作高效率的串口示波器的问题,而之后就是具体去实现它,当真正去实现它时,你会发现网上并没有很好的案例可以给你学习和参考,都只是实现功能,实现功能和把这件功能做到极致是两码事,其难点主要还是在于PC端的上位机,对于下位机来说MCU是有中断概念的实习系统,它本身的数据传输延迟可以很低,响应延迟可以很低,因此在下位机端简单用一个空闲中断就能解决,但是对于上位机来说,它的工作机制是扫描,这就意味这系统本身不会自动的帮你分割数据,在什么地方取出帧头,如何从混乱的数据帧中找到数据的帧头,并逐一解析整个数据帧是一个比较复杂的问题,对于PC端的串口通信实现也要考虑其扫描的周期、数据处理的速度,还有数据处理应当不受影响,因此数据的处理应当是比较底层的语言来实现(因为有更高的效率,和更大的可操作性),如果使用C#提供的接口实现,那问题就很大了,.net
内部时间的最小单位是15ms,不谈数据处理耗费,光等待就有点浪费时间,因此我在此考虑了用 QT 实现,SailorProject也就这样产生了,至于具体实现请看后文介绍,此方案我在此已经开源,供大家学习。
对于C#能否实现高效率的串口数据收发这个问题,答案自然也是可以的,我之后用 wpf
写的 KmdFoc
上位机也能达到很高的收发效率,极低的数据处理占用,此方案则是用的WIN自带的C++ API和我自定义的 Seasky
协议编写了静态库以提供给 C# 调用,不得不说这种方式开发工业上位机是一个不错的选择,比传统直接用C#本身来说会更稳定,效率更高,高度的封装也使得其使用起来相对比较简单,因此对于此种类型的上位机,基本上只需要写UI就好了,可以极大的缩短开发周期,此方案暂时不开源,但是会提供 .dll
文件,这意味着如果你使用 Seasky
协议开发,同时你想开发一款虚拟和现实协调的上位机,基于该静态库你可以比较轻松的开发 Unity上位机
,并对你的机器人实时协同。