写了个东半球第二好用的串口调试助手
熟悉我的朋友硬知道我是半个嵌入式工程师,对硬件和嵌入式有着强烈的兴趣,在工作之余会经常制作一些小巧精致的小玩意。在开发这些小东西的过程中,难免的会用到串口,在硬件上,串口是一个灵魂般的存在,它就是硬件的眼睛、耳朵和嘴巴,所有需要对硬件的控制,以及硬件本身想要打印的内容,都需要借助串口来输出。由于我很长一段时间开发工作都是在Mac上进行,在Mac上找到一款好用且没关的串口调试工具是在太难了,但是即便是这些原因,也都没有打动懒癌晚期的我。真正打动我的,是最近公司项目在调试过程中碰到的一些问题,让我这个前端方向的软件工程师看着很累。
简述
公司正在研发一款生物打印机,对硬件的调试是通过串口完成的,在这个过过程中需要长时间且可定制化的对设备进行一些测试,这些测试都需要能随时随地进行,而不是找一个嵌入式工程师去改写固件,或者找一个PC端的 C/C++ 工程师花几天时间编译一个测试工具。这个测试的本身,就是希望在硬件接口协议完善的情况下,任何一个设备的使用者,都可以参与编写自己的工作脚本,类似 GCODE
,甚至需要比 GCODE
还要简洁。
既然是这样的需要,我正好是前端工程师,对硬件又无比热爱,跨专业跨的总是扯裆,那这个活必须接了。
先看下测试工具的初版完成效果图。
Log 高亮效果,以 ESP32 的 Log 输出为例。
软件也支持字节显示,并且对特殊字节进行高亮着色。
几个特性:
- 类Linux终端,支持Log高亮;
- 使用了
Electron + Vue全家桶
,开发迭代方便,Electron比Nwjs更优秀; - 支持自定义测试脚本;
- 支持自定义主题,样式文件分离;
- 支持文件传送;
- 支持自定义文件传送方案;
- 支持插件系统,它除了是一个串口调试工具,通过插件还可以让它变成MQTT或者TCP测试工具。
实现方案
Vue UI
因为开发使用了 VueJS 作为数据驱动,所以可以借助 Vue 的生态,选择一些 Vue 的 UI组件库,这里我选择了 Keen-UI,完全的 android metiral
风格。
自动化
项目使用了 electron-vue 脚手架,有关该脚手架的介绍和使用可以点击链接查看。通过使用这个脚手架工具,可以实现项目流程化和自动化,脚手架内页包含了Electron的打包和编译,非常方便。
串口模块
因为是串口调试工具,所以需要使用串口功能,可惜 Electron 的发行版并没有附带 Serial 模块(nwjs的发行版是带的),所以需要使用第三方串口模块,这里我使用的是 node-serialport,这是一个NodeJS版本的串口SDK,借助这个开发库可以实现对串口的读写和枚举,非常的方便。
另外,需要安利一下,这个库因为基于 NodeJs
,所以它天生具备跨平台属性,不光可以在PC和Mac上运行,在一些基于 Arm
架构的Linux电脑上也可以顺利运行,我工作中的一些软件开发和测试工作,就是通过在Linux上写NodeJs脚本实现的,非常方便。
模块的安装很简单:
npm install serialport
基于Electron的版本需要rebuild,参考官方的文档重新编译后就可以在Electron上使用了。
脚本化
脚本化是一个应用之上的应用,相当于使用NodeJs作为开发语言,重新开发了一个脚本解释器,用户写一些更语义化的指令可以被脚本解释工具解释成机器语言执行,类似于一个Python解释器或者C编译器的角色。
实现这个功能的目的,是希望用户可以借助更字面化的语言,实现对设备的高级控制和编程。举个例子,用户希望可以归零设备,可以这样写:
home G.X
home G.Y
home G.Z
这三句话表示将设备的 XYZ 三个轴归零。如果用户想把设备的某个运动轴进行移动操作,可以这样写:
move G.X,200
这句话表示将设备的X轴移动到200mm的地方,这里的200就是一个坐标。这些都还没有结束,除此之外,用户也可以定义变量,比如:
Define startX=100
move G.X,startX
第一句定义了一个变量,叫 startX
,并且给它赋值为200,第二句话将X轴移动到 startX
的位置。
基于这些,其实还不能开发更高级的或者更复杂的功能,比如用户重复执行某个命令100次,总不能将这个命令复制粘贴100次,所以我让脚本支持了循环结构,循环可以这样写:
loop 100:
home G.X
move G.X,200
endloop
字面意思也很好理解,loop 100
表示执行100次,endloop
和 loop
成对出现并使用,类似于 JavaScript 里的花括号需要成对出现一样。这是一个循环结构,循环体就是 home G.X
和 move G.X,200
,是不是很好理解。
再看一个完整的点阵测试脚本:
Define xLine=20
Define yLine=20
Define xMargin=100
Define yMargin=100
// 使用 1 号头打印,使用 Right 列
Define line1_ziyq=[16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]
// 起始位置
Define startX=100*1000
Define startY=20*1000
Define startZ=10*1000
// 工作速度
Define speedXY=100*1000
Define speedZ=10*1000
// 归零
home G.X
home G.Y
home G.Z
setSpeed G.X,speedXY
setSpeed G.Y,speedXY
setSpeed G.Z,speedZ
setMotionMode G.X,G.ABSOLUTE_MODE
setMotionMode G.Y,G.ABSOLUTE_MODE
setMotionMode G.Z,G.ABSOLUTE_MODE
move G.X,startX
move G.Y,startY
move G.Z,startZ
loop 20:
// 打印一行
loop 20:
printDataLine 1,10,200 line1_ziyq
setMotionMode G.X,G.RELATIVE_MODE
move G.X,xMargin
endloop
// X回到起始位置,准备开始下一行打印
setMotionMode G.X,G.ABSOLUTE_MODE
move G.X,startX
// Y轴步进
setMotionMode G.Y,G.RELATIVE_MODE
move G.Y,yMargin
endloop
// 结束后的动作
setMotionMode G.X,G.ABSOLUTE_MODE
setMotionMode G.Y,G.ABSOLUTE_MODE
move G.X,startX
move G.Y,startY
// Z轴抬高,方便取出玻片
move G.Z,startZ-20*1000
所以有了以上脚本解释器,就可以定义很多新功能,这些新功能无需嵌入式工程师去开发,也无需桌面端软件去实现,用户自己就可以完成,大大节省了测试时间。