☰
开源短波电台控制网关OpenRig:统一管理串口、PTT与天线
2026/11/2 5:36:12 网站建设 项目流程

如果你玩过两台以上短波电台,大概能体会到那种“线比天线还多”的崩溃感。我自己的设备房就是这样:FT-857D、IC-7300、外置声卡、旋转器、天调,每个设备都有一根串口线或 USB 线,而日志软件、SSTV 软件、FT8 软件又各自都想抢占同一个 COM 口。为了彻底解决这个乱象,我做了个开源项目 OpenRig——一套把电台控制、音频切换和天线控制统一起来的软硬件方案。这篇博客就是它的完整复盘,包括架构设计、硬件选型、软件配置和我在调试过程中踩过的所有坑。

OpenRig 的目标很朴素:让任何一台电脑上的任何软件,都能像直接连接电台一样工作;同时让旋转器、天调、功放和天线切换器这些“外围设备”也纳入同一个控制平面。无论你是刚入门的短波新人,还是已经在搞 contest 的老手,这套思路都能帮你省掉不少反复插拔线材的时间。

1. 从“串口不够用”到决定自己造轮子

1.1 真正的痛点不是端口数量,而是端口所有权

很多人一开始以为,设备多了无非就是加一个 USB 扩展坞。我最早也这么想,直到打开 WSJT-X 摆摊 FT8,顺手又开了 N1MM+ 准备打个比赛,结果第二个软件直接弹出“端口被占用”。

问题在于,串口是独占式资源。传统电台的 CAT 控制口一次只能被一个进程打开,Windows 下常见的“COM 口被锁”就是这样来的。你可以用 com0com 之类的虚拟串口软件把同一路串口复制给多个程序,但虚拟串口只是做了数据分发,完全不管两个程序同时给电台发命令时的时序冲突。日志软件在轮询频率,SDR 软件也在轮询,两边乒乓发指令,几秒钟电台就开始不响应了。

所以,OpenRig 的第一个设计原则就是:电台只认一个“上级”,其他软件都去找这个上级。

1.2 我在市面上翻到的现成方案,为什么都放弃了

先说说我调研过的几个路线:

  • USB 扩展坞 + 一大堆线:线材更乱,串口独占问题依旧。
  • 虚拟串口共享工具:免费版有限制,日志软件和数字模式软件同时工作时容易指令冲突。
  • 专业电台共享器:类似 microHAM 那样的设备确实好,但价格感人,而且固件封闭,想加一个天线切换功能得再买周边。
  • 直接给电台加蓝牙串口模块:延迟不稳定,偶尔掉线,对 FT8 这种时序敏感的模式不够友好。

这些方案要么不解决本质问题,要么把问题从“硬件层”挪到“钱包层”。我最后决定自己造轮子,名字就叫 OpenRig,硬件的 PCB、外壳文件和全部软件代码都开源。

2. OpenRig 的总体架构:把所有设备当成一个“虚拟电台”

2.1 控制总线:CAT 指令在串口与 TCP 之间流转

OpenRig 的核心理念可以概括成一句话:在电台和软件之间,插入一个“控制服务层”。传统接法里,软件直接读写串口;在 OpenRig 里,软件连接到一个 TCP 端口,这个端口背后才是真正的串口。

整个数据流是:

  1. 日志软件 / FT8 软件作为 TCP 客户端,连接到树莓派上的 OpenRig 网关。
  2. 网关解析并排队这些 CAT 指令,按顺序发送给电台的 CAT 串口。
  3. 电台的应答原路返回给对应的客户端。

这相当于把电台的串口从“物理资源”变成了“网络服务”。同一时间可以挂多个软件,网关负责仲裁。我测试过同时挂 WSJT-X、N1MM+ 和一个自写的频率显示小程序,电台侧完全没有出现指令打架的情况,因为网关靠一个简单的互斥锁和超时机制:任何客户端发出的指令在收到应答或者超时之前,后续指令都会在队列里等待。

2.2 除了 CAT,还有 PTT、PTT 时序和波段电压

如果你只控制频率和模式,CAT 就够了。但短波台站从来不是一台电台的事。外接功放需要 TR 切换信号,旋转器需要独立的 RS-232 控制,天线切换器需要一组继电器信号。

OpenRig 把这些分成三条独立通道:

  • CAT 通道:走串口,负责频率、模式、带宽、S 表等数据。
  • PTT 通道:走 GPIO,配合一个简单的时序电路控制收发切换。由于功放的收发切换通常比电台慢,OpenRig 在 PTT 引脚上加了可配置的前置延时和释放延时。
  • 辅助控制通道:通过 I2C 或串口连接一个 MCU 子板,MCU 再控制天线切换继电器和旋转器。

这样设计的好处是即使 CAT 串口被某个软件长时间占用,PTT 和天线仍然可以独立工作,不至于出现“频率控制正常但天线指向还是老位置”的尴尬。

2.3 整套系统的部件清单

部件型号/规格参考作用
控制主机树莓派 Zero 2 W 或树莓派 4B跑 OpenRig 网关和 Web 面板
USB 扩展带外部供电的 USB Hub给电台串口适配器、音频设备提供稳定连接
串口适配器CP2102 或 FT232RL,按电台接口选把电台的 CAT 口转为 USB
PTT 时序板Arduino Nano + 光耦隔离提供 PTT、功放 TR 切换和延时
旋转器控制器支持串口控制的 G-450 类控制器负责天线方位角
继电器板5V/12V 双路继电器模块天线切换、天调旁路
外壳3D 打印 + 接线端子台整理所有线缆,避免搭棚焊接

这套配置的成本大约是一台中档串口共享器的三分之一,而且所有逻辑都可以按自己的需求改。

3. 硬件搭建:材料、接线和首次通电

3.1 控制主机为什么选树莓派而不是单片机

有些人问我,为什么不用 ESP32 直接搞定,便宜又轻量。我的回答是:ESP32 适合做“控制器”,不适合做“网关”。OpenRig 需要同时管理 USB 设备的枚举、TCP 服务、Web 面板、日志存储,这些活儿交给带 Linux 的树莓派要省心得多。

我选的是一块树莓派 Zero 2 W,性能够用,功耗低,塞在接线盒里几乎不发热。如果你的电台 USB 设备比较多,建议换成树莓派 4B,USB 带宽更充裕,避免多个串口适配器同时大流量读写时掉设备。

3.2 电台侧的接线方案

电台侧的接线是整个搭建里最需要小心的地方,不同厂家的 CAT 接口长得完全不一样。

先说 IC-7300。这机器直接把 USB 口拿出来当 CAT,接上树莓派就是一个 /dev/ttyUSB0,常见参数是 115200 波特率,CI-V 地址默认 0x94。树莓派系统里一般不需要额外装驱动,CP210x 系列芯片内置在机器里,插上就能识别。

然后是 FT-857D、FT-450D 这类老机器。它们的 CAT 用的是 mini-DIN 8 针接口,里面同时有 CAT 的 RX/TX、线性放大器控制的 TX-G/GND,还有 PTT 信号。这里千万别直接把 GPIO 的 3.3V 信号接进去,老机器的 CAT 标准是 RS-232 电平,需要用一个 MAX232 电平转换,或者像我这样用一个现成的“电台数据接口盒”来对接。稳妥起见,我用的是 CP2102 转 RS-232 的成品线,再配合一条 DB9 转 mini-DIN 的数据线,机器侧不用任何改装。

波段电压和功放控制线:FT-857D 的 ACC 口会输出随波段变化的模拟电压,我用一个 ADC 模块读这个电压,在 OpenRig 里转换成当前波段号。这样切换天线时,系统能自动把对应波段的振子接进去。

3.3 旋转器和天线切换的接入

旋转器我用的是一座支持 RS-232 串口控制的 G-450 类控制器。它本身有配套软件,但那个软件只能在 Windows 上跑,而且一次只能控制一台。OpenRig 里我用一个串口转 TCP 的小代理,把旋转器控制器也映射成网络端口,这样电脑端的 Log4OM、DXLab 都能通过通用协议读取方位角。

天线切换器更简单,就是一个双路继电器板。树莓派的 GPIO 直接驱动继电器模块(模块上自带三极管和续流二极管,可以直连 3.3V 引脚),我在 Web 面板里做了一个开关,点击对应波段按钮,继电器就切到预设的那根天线。

3.4 接地、屏蔽和外壳

这一步容易被新手忽略:树莓派、电台、电脑三者的地如果不统一,会出现很强的接地环路噪声,尤其在使用外置声卡的时候,容易听到 50Hz 交流声。

我的做法是:所有设备的地线接到接线盒里的一个汇流铜排上,再单独一根粗线去接电台机壳的接地螺栓。树莓派电源用一个高质量 5V/3A 适配器,串口线全部用带磁环的屏蔽线,电脑侧尽量用 USB 隔离器。实测下来,接地处理前后,声卡的底噪从 S5 左右降到了 S1。

外壳我直接用 3D 打印机做了个带接线端子台的盒子,所有进来的串口线、USB 线、控制线都压在端子排上,后续要维护哪个设备,拔对应端子就行,不用拆盒子。

4. 软件落地:rigctld、网关和 Web 面板

4.1 最小可用的 rigctld 配置

软件部分的第一层,我用的是 Hamlib 自带的 rigctld。它能直接把电台抽象成一个 TCP 服务,客户端只要写 rigctl 命令就能操作电台。

先确认你的电台在 Hamlib 里的型号编号:

rigctl -l | grep -i "7300"

然后启动 rigctld:

rigctld -m 3060 -r /dev/serial/by-id/usb-Icom_IC-7300_0000000000-if00 -s 115200 -t 4531 &

解释一下参数:-m是电台型号编号,-r是串口设备路径,-s是波特率,-t是监听的 TCP 端口。这里有个我强烈推荐的细节:设备路径不要写/dev/ttyUSB0,而是用/dev/serial/by-id/下的稳定名称,否则树莓派重启后 USB 设备顺序一变,路径就漂移了。

启动之后可以用echo "f" | nc localhost 4531测试,正常会返回当前频率。到这里,任何支持 rigctl 协议的软件,只要把连接方式设为“Hamlib NET”,主机填树莓派 IP,端口填 4531,就能工作了。

4.2 多客户端网关:用 Python 写一个轻量转发器

rigctld 虽然能同时接受多个连接,但它在内部其实是按“最后注册的客户端”来响应的,两个软件同时轮询时会互相踢。所以我需要一个更高层的网关来排队和仲裁。

这个网关我写成了一个小型 Python 服务,核心逻辑大概是:

import socket, serial, threading, queue class SerialGate: def __init__(self, port='/dev/ttyUSB0', baud=115200): self.ser = serial.Serial(port, baud, timeout=0.1) self.lock = threading.Lock() self.answer_q = queue.Queue() def exec(self, cmd, timeout=1.0): with self.lock: self.ser.reset_input_buffer() self.ser.write(cmd) answer = self.ser.read(256) return answer gate = SerialGate('/dev/serial/by-id/usb-...', 115200) # 对每个 TCP 客户端:读一行指令,交给 gate.exec,把结果写回该连接

这个版本去掉了繁琐的广播逻辑,保留了最核心的互斥。实际测试,同时挂四个客户端时,指令应答成功率在 99.9% 以上,偶尔超时是因为电台本身忙于发报没有回复,这属于正常现象,重试一下就好。

4.3 Web 面板:让整个台站状态一眼可见

控制层跑通之后,我再加了一个简单的 Web 面板,用 FastAPI 做了几个只读接口:电台频率、模式、驻波比、当前天线、旋转器方位角。前端就是一个刷新式页面,没有用重量级框架。

这个面板最大的好处是:人在院子里调天线时,掏出手机就能看到电台是不是真的切到了正确频率,不用再跑回设备房看屏幕。

4.4 用 systemd 管好开机自启

树莓派作为无人值守设备,所有服务都要能开机自启。我给 rigctld、网关和 Web 面板各写了一个 systemd unit,并且在网关的 unit 里加了After=rigctld.service和Requires=rigctld.service,保证启动顺序。

5. 调试记录:五个坑,每一个都让我多花了两个晚上

5.1 权限问题:dialout 组和 udev 规则

第一次在树莓派上跑 rigctld,报错open: Permission denied。原因是 Linux 下操作串口需要用户在dialout组里。

sudo usermod -aG dialout $USER

改完要重新登录生效。如果是在没有密码的 headless 环境,直接在 systemd service 里加User=pi并确认 pi 在 dialout 组即可。

5.2 CI-V 地址冲突

IC-7300 默认 CI-V 地址是 0x94,但很多日志软件默认用 0x00(代表“所有电台”)去轮询,而 WSJT-X 会用自己的默认地址。如果两个地址同时在总线上,电台会对其中一个无响应。

排查方法:用 Hamlib 的rigctl手动发一条读频率指令,如果返回乱码或无响应,先把所有软件的 CI-V 地址统一改成 0x94,并关掉电台菜单里的“CI-V 自动写入”选项,避免软件设置的地址覆盖掉电台内部地址。

5.3 PTT 延迟引起的回波和自动断连

我在第一次联调时发现,FT8 发射时话音信号会有一个短促的“咔哒”声,听起来像继电器切换的声音。查了很久才发现是 PTT 时序问题:PTT 已经落下,但音频通道还没完全静音,导致了一个尖锐的瞬态。

我的解决办法是把 PTT 前置延时调到 80ms,释放延时调到 120ms,并且把音频通道的静音 PIN 也接入同一块 PTT 时序板。这样每一次收发切换都在完全安静的环境下完成。

5.4 电平转换:树莓派 GPIO 不是万能 5V

树莓派的 GPIO 是 3.3V 逻辑,直接去驱动某些 5V 继电器模块虽然能工作,但长期运行有风险,而且遇到没有续流二极管的廉价模块,很容易把 GPIO 烧掉。我后来全部换成了带光耦隔离的模块,树莓派侧只输出 3.3V 信号去点亮光耦,5V 侧完全隔离。功放的 PTT 输入也借光耦接到时序板,两边彻底电气隔离。

5.5 串口名漂移,写成 /dev/ttyUSB0 是大忌

第一版配置里我直接写了/dev/ttyUSB0,结果树莓派重启几次后,IC-7300 的串口名变成了/dev/ttyUSB2,网关就连不上了。

正确做法是用/dev/serial/by-id/下的稳定链接名。先插上设备,执行:

ls -l /dev/serial/by-id/

把生成的稳定路径填到配置里。即使物理 USB 口插拔顺序变了,这个名称也不会变,除非你换了设备型号。

6. 还能往哪走:OpenRig 的后续计划与实际建议

6.1 从“控制”到“自动化”

OpenRig 走到现在,已经能稳定解决“多软件共享一台电台”的问题。接下来的方向是自动化:根据当前 CAT 频率自动切换天线、根据旋转器方位角自动调用传播预测数据、定时自动开启和关闭电台电源。这些逻辑全部可以写进网关的插件机制里。

6.2 想加入的 MQTT 上报

最近我在给 OpenRig 加一个 MQTT 上报功能,把电台状态、天线位置、设备温度实时推送到 Home Assistant 上。这样一来,在家里任何一个有屏幕的地方都能看到设备房的状态,甚至可以通过自动化在夜深人静时自动把无线电切换到低功率模式,避免打扰邻居。

6.3 给想复刻的朋友的几句实在话

最后说点实在的。如果你想复刻这套东西,我建议先别急着一次装完。第一步只做 CAT 网关,用 rigctld 把 IC-7300 或任何一台手头的电台接到网络里,跑通 WSJT-X 和日志软件共享;第二步再加 PTT 时序板,解决功放和音频切换;第三步才轮到旋转器和天线切换,因为这些外围设备一旦接入,出问题的链路就多了。

我踩坑时有一个习惯:每改一个配置,就记到项目的 CHANGELOG 里,注明当时的现象原因和解决方式。这个习惯挽救了后面很多次折腾,因为有些问题半年后才再次出现,翻一下记录比重新排错快十倍。

如果你也在为满桌子的串口线发愁,OpenRig 的思路可以直接借走。代码和图纸我都放在开源仓库里了,欢迎去提 issue,把你自己的电台型号和奇怪需求加进来,这个项目就是靠各种“奇怪需求”才变得好用的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询