简单写点,抛砖引玉。
有用过小手台打卫星的ham一定有一边举着天线看着look4sat上显示卫星位置,一边留心调整多普勒频率,一边还要听辨和记录对方说了什么的手忙脚乱脑子不够用的体验。假如是线性转发器卫星就更要命:在没有完善CAT控制的时代,收发频率因为多普勒频偏,变化方向是相反的,没调整好一不小心就跟丢了甚至跑到频带外。手工操作固然彰显HAM技术,但计算机自动控制岂不更好?
实际上现代电台高度依赖计算机辅助收发,这是便利的地方,有了计算机参与,用鼠标拖动就能换频率,修改VFO,打卫星时的多普勒频偏可以自动弥补,你也能通过网络控制远程台。那么这些概念最终指向的术语就是CAT。
CAT(computer aided transceiver,计算机辅助收发),指通过串口或网络连接等方式,让计算机参与电台收发控制的技术。但它是一个很宽泛的概念,不是单一标准协议、甚至链路层/物理层也是各家搞各家的。比如ICOM用的是CI-V协议(半双工总线),其他家还是串口。YAESU(八重洲)虽然是第一个在80年代把CAT商品化、品牌化的,但他家每个型号命令格式差异很大,比如ft817、ft857、ft991互不兼容。YAESU用的是二进制(或者说十六进制)信令,而kenwood采用文本命令(elecraft好像也是类似的ASCII命令)。总而言之生态高度碎片化,一款HAM软件如果要支持所有电台,须为每个厂商甚至每个型号单独实现驱动。
以这两年很流行的开源电台uSDX为例,它采用了kenwood TS-480电台的CAT协议(虽然只实现了一部分,也就是子集)。简单来说,它是文本命令,分号结尾,波特率115200,8N1(8个数据位、无奇偶校验(parity)、停止位1位),还有DTR和RTS的行为(DTR 和RTS是串口规范RS-232的两个引脚,通信双方通过它电平高低来检测或决定要切换到接收或是发射状态——虽然这样说不够严谨;大家可以去WSJT-X或FT8CN的设置界面找找它的身影)。
uSDX实现的CAT命令举例如下。
| 命令 | 功能 |
FA; / FA00014195000; | 获取/设置频率(Hz) |
MD; / MDn; | 获取/设置模式(1=LSB, 2=USB, 3=CW, 4=FM, 5=AM) ,但uSDX不支持FM和AM发射 |
IF; | 获取电台状态(频率、模式等) |
TX0; | 进入发射状态 |
TX2; | 进入调谐状态 |
RX; | 进入接收状态 |
ID; | 返回电台 ID(固定返回 020,即 TS-480) |
其实还有一些扩展命令,比如CAT音频流,就是在同一个串口里同时传输控制命令和音频数据,这样就不用多插两根3.5mm音频线了,很多现代电台也有类似设计,比如通过USB线同时跑音频和CAT控制,/dev/ttyACM0这种。
Omnirig和Hamlib
所以各家电台的CAT协议五花八门,适配工作量大。那软件开发者咋整?根据解耦和抽象的理念,很容易想到把软件与电台设备通讯的这些麻烦事抽象出一个中间层,找一个专业翻译官做适配。这就是所谓“中间件”。中间件按我的观察,目前有两大主流生态,Omnirig和Hamlib。
这两者做的基本上是同一件事:连接电台的串口(有的串口可能是USB或者wifi上虚拟出来的)、并且在厂商的私有CAT协议 和通用的“标准接口语言”之间做转换。
除了处理CAT协议,Omnirig和hamlib还能控制RTS/DTR这种串口电平;hamlib还能支持VOX 也就是声控发射)
OmniRig ( https://github.com/VE3NEA/OmniRig )是VE3NEA开发的,设计目标就是"让 Windows 上的业余无线电软件,只需写一次电台控制代码,就能支持所有电台。"。说起来这个VE3NEA呼号看着是不是很熟悉,就是DX Atlas工具集的作者,比如说morse runner,还有CW skimmer,还有喜欢打卫星收遥测会用到的多功能集成软件skyroof也是这位的作品。
不过Omnirig目前只有windows版本,大概是开发比较早(21世纪前几年),不小心用了activeX/COM的万恶的微软技术栈。好在发展不错,成为了windows only的哪些HAM软件 传统上的事实标准。比如N1MM、logger32用的都是omnirig。
Omnirig本身没有主界面,它是系统级别的COM服务。配置也很有windows味道,它的核心引擎会读取INI文件,每个INI文件都是某个型号的电台的行为描述清单。用户如果新增设备,自己写一套对应的INI配置就行了,这就没必要不断给用户发新版本更新驱动库(尤其是在软件分发并不容易的前互联网时代!)
给一个配置文件的示例 (注意INI文件的备注是以英文分号起始,而不是双斜杠)
; Icom IC-7300
[Radio]
Name=IC-7300
; 波特率
BaudRate=115200
DataBits=8
Parity=None
StopBits=1
; 命令超时
Timeout=200
; 轮询间隔
PollRate=200
[Commands]
; 设置频率
SetFreq=FE FE 94 E0 05 <FreqBCD5> FD
; 获取频率
GetFreq=FE FE 94 E0 03 FD
; 设置模式
SetMode=FE FE 94 E0 06 <Mode> FD
; PTT 控制
SetPtt=FE FE 94 E0 1C 00 <Ptt> FD
是不是最后一部分挺抽象的,尤其是设置命令那里,全是十六进制,好在厂家高级手册里都会写明便于二次开发,这方面我更喜欢人类可读的文本命令……
现在就必须提到开源真神 · Hamlib:
Hamlib ( https://hamlib.github.io/ )相比omnirig的优点是跨平台,如果用linux、macOS上的火腿工具,或者要给嵌入式做适配(比如用树莓派+一块屏幕给FT891等传统电台引出的中频做频谱浏览和控制)几乎是唯一选择。
hamlib分为三层:后端、C API和命令行工具。后端就是一大堆电台型号的驱动库,C API给二次开发用的,一般用户用得更多的是它的命令行工具——rigctld、rotctld、ampctld,一看这ctld的后缀(control daemon)顾名思义就是分别控制电台的、控制旋转器的、控制放大器的。它之所以叫做control daemon,是因为本质上它能够开一个TCP监听端口(默认是4532),等着让不同的软件去发送命令(无状态短连接或长连接均可),是代理/守护进程。
举个例子,我们假设运行软件的同一台电脑上usb连接这一台IC-7300(在hamlib库里,IC-7300的型号代码373,这个对应关系可以通过 rigctl -l | grep -i "型号" 的方式查询,下面不再说明)
rigctld -m 373 -r /dev/ttyUSB0 -s 115200 & #linux下USB的设备路径写法
rigctld -m 373 -r COM3 -s 115200 & #windows下USB串口的写法
这样本机就有一个4532等着监听控制信号了。
然后家里楼下同一个局域网里有一台FT991,假设暴露的端口是8888,为了避免和上面冲突,我们需要换一个守护进程的监听端口,比如4531。
rigctld -m 135 -r 192.168.1.100:8888 -t 4531 &
那么此时就能分别查看两台电台的频率(以及进行其他控制操作),而且你不用管不同厂家原本的命令写法,用hamlib的标准命令就好。
# 客户端连接时指定端口
echo "f" | nc localhost 4532 # 查 IC-7300 频率
echo "f" | nc localhost 4531 # 查 FT-991 频率
这就很方便了,想象你用一台IC-705去在线性卫星RS-44上玩FT4通信,那就不得不同时用WSJT-X(FT4编解码)、gpredict(星历预测和轨道跟踪、多普勒调整)、甚至可能还有其他日志软件。那这些软件都可以通过独立的TCP连接和rigctld通信,rigctld把所有收到的信息流都组装到队列里,统一发给电台串口,就能让音频流双向流通、频率双向调节。
对了第二个rotctld,是负责天线旋转器的网络化管理代理,默认端口4533。这个我太熟了,因为最近在搓天线旋转器的开源固件,和它使劲打交道……说起来天线旋转器的控制协议也是百花齐放(乱七八糟),比较有名的是AMSAT(业余无线电卫星公司)搞的easycomm I/II,八重洲的GS-232A/B,Pstrotator(有同名的控制软件),基于二进制的SPID Rot2Prog,还有和天文望远镜赤道/寻星相关的 Celestron NexStar,噢对了国内还有用监控云台做旋转器的(尤其是301云台,亚安3040云台,因此沿用了原来云台厂家的控制信令)。不少资深HAM会用到BG6LQV开发的“业余卫星软件”来控制旋转器,它就实现了这两款云台协议和八重洲的GS232-B协议。你甚至还能看到在电台连接功能上直接集成了omnirig的组件:

说白了天线旋转器控制无非就是:方位角(航向角,AZ)几度,俯仰角(EL)几度。以及让旋转器上报自己目前的角度(以便得知状态)。比如easycomm核心命令集就这几个。 (easycomm II如果AZ 或者EL指令后不带参数,就是问旋转器:你现在是啥姿态?)
| 命令 | 说明 | 示例 |
AZ<角度> | 设置方位角 | AZ123.5 |
EL<角度> | 设置仰角 | EL45.0 |
UP | 向上转动 | |
DN | 向下转动 | |
ML | 左转 | |
MR | 右转 | |
SA | 停止方位转动 | |
SE | 停止仰角转动 | |
上下左右转以及停转是给手工控制用的(假如不依赖自动解算和闭环控制),闭环控制不需要手工停转,误差小于一定范围电机自动就不干活了。所以只需要前两个命令就够用了。这种简洁好实现的协议经常被拿来手搓旋转器里的固件,比如在arduino或esp32上跑解算和电机驱动。
我感觉说多了。这里需要澄清一下,omnirig和hamlib其实并不那么有存在感,这种中间件可能集成在软件内部,比如WSJT-X会让你选择电台型号(或控制指令集),本质上后台就是调用了hamlib;有的会让你配置串行端口。如果软件不支持远程电台,你也可以起一个守护进程去监听转发(这时相当于软件前面有一层透明代理)。甚至你可以让hamlib通过十六进制方式发送自定义指令(例如和天线电机那里的温度传感器交互)并且获取反馈。这就是hamlib的灵活之处。
希望这篇小文章能帮助广大火腿更好地理解ham设备与电脑(及一些手机端app,比如FT8CN,TX-5DR,IC705controller,look4sat)的通讯交互机制。