2024-04-11
自动位置回报系统(APRS)是一种基于业余无线电在本地进行实时信息交换的数字通信协议,这些信息可以包含 GPS 定位、气象站数据、短消息等。
APRS 在中国国内通常用于实时位置分享,而 APRS IGate( APRS 网关)则是一种 APRS 接收电台,它将接收到的 APRS 数据包解码并传输到 APRS 服务器上。 APRS 服务器上的数据将被显示在 APRS 地图上供查阅。常用的 APRS 地图有 aprs.fi 和 aprs.tv 等。
常见的 IGate 使用 RTL-SDR 接收信号,这种设备灵敏度较低,需要很好的接收条件才能获得理想的接收效果;高灵敏度的 SDR 则伴随着高价格。本文采用 Milkv Duo 配合小黄鱼三十元随便收的国产宝峰 UV-66 手台,制作具有较高灵敏度的 IGate。
总体思路
整体思路为手台接收信号,将音频输出给 Milkv Duo,由 Direwolf 解码并上传。
Direwolf 依赖 ALSA 与 ncurses;另外调整过程中还需要 amixer
调整 ALSA 输入设备的音量大小,并用 arecord
命令录音检查手台音量输出电平是否合适。
二进制的交叉编译使用 RUYI 包管理器安装的工具链,环境的配置参考这篇文章。
Milkv Duo 的镜像使用带 RTL8188 无线网卡驱动的镜像,该镜像的构建参考这篇文章。无线网卡使用 RTL8188 系列 USB 无线网卡或模块。
线路连接
这是一个只收不发的 IGate,故只需要从手台 K 头的 2.5mm 音频接口通过衰减线与 Milkv Duo 的麦克风输入相连。
衰减线路的取值并不是最优但还算适合,手台只需要很小的音量输出。
构建 alsa-lib
alsa-lib 是 alsa-utils 和 Direwolf 的前置依赖。
不建议直接从仓库克隆,除非明白这意味着什么。 DESTDIR
根据实际情况修改。
$ wget http://www.alsa-project.org/files/pub/lib/alsa-lib-1.2.11.tar.bz2
$ tar -jxvf alsa-lib-1.2.11.tar.bz2
$ cd alsa-lib-1.2.11/
$ ./configure CC="riscv64-plct-linux-gnu-gcc" CFLAGS=-O0 --enable-shared=no --enable-static=yes --host=riscv64-linux
$ make -j4
$ make install DESTDIR=<ruyi_venv_dir>/ruyi-venv/venv-duo/alsa-lib
-O0
的原因见 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109809,不过我对这个说法并不确信,因为后面使用了 -static
达到了同样的效果。总之可以认为是 GCC 的 bug。
由于默认安装目录是 /usr/lib
,这个路径被 <ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib/libatopology.la
引用,故需要手动更正其中的 dependency_libs
字段。
构建 ncurses
ncurses 是 alsa-utils 的前置依赖。 DESTDIR
根据实际情况修改。
$ wget https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.4.tar.gz
$ tar xvf ncurses-6.4.tar.gz
$ ./configure CC="riscv64-plct-linux-gnu-gcc" CXX="riscv64-plct-linux-gnu-g++" INSTALL="/usr/bin/install --strip-program=riscv64-plct-linux-gnu-strip" --enable-shared=no --enable-static=yes --enable-widec --host=riscv64-linux
$ make -j4
$ make install DESTDIR=<ruyi_venv_dir>/ruyi-venv/venv-duo/ncurses
构建 alsa-utils
构建, <ruyi_venv_dir>
根据实际情况修改。
$ wget http://www.alsa-project.org/files/pub/utils/alsa-utils-1.2.11.tar.bz2
$ tar -jxvf alsa-utils-1.2.11.tar.bz2
$ ./configure CC="riscv64-plct-linux-gnu-gcc" CFLAGS=-static NCURSESW_LIBS="-L<ruyi_venv_dir>/ruyi-venv/venv-duo/ncurses/usr/lib -lncursesw" NCURSESW_CFLAGS="-I<ruyi_venv_dir>/ruyi-venv/venv-duo/ncurses/usr/include -I<ruyi_venv_dir>/ruyi-venv/venv-duo/ncurses/usr/include/ncursesw" --with-alsa-inc-prefix="<ruyi_venv_dir>/venv-duo/alsa-lib/usr/include" --with-alsa-prefix="<ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib" --host=riscv64-linux --disable-alsaconf
$ make -j4 LIBTOOLFLAGS=-all-static
LIBTOOLFLAGS=-all-static
的本意是得到静态链接的二进制,实际则报错 libtool: error: unrecognised option: '-all-static'
。我不知道为什么,只能 make -j4
后手动静态链接二进制了。
下面这段仅供参考,构建命令可以阅读前面的 make
输出。
$ cd aplay
$ riscv64-plct-linux-gnu-gcc -I<ruyi_venv_dir>/venv-duo/alsa-lib/usr/include -o aplay aplay.o -L<ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib <ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib/libasound.a -lrt -lm -lpthread -static
$ cd ../alsamixer
$ riscv64-plct-linux-gnu-gcc -D_GNU_SOURCE -I<ruyi_venv_dir>/venv-duo/ncurses/usr/include -I<ruyi_venv_dir>/venv-duo/ncurses/usr/include/ncursesw "-DCURSESINC=<ncurses.h>" -I<ruyi_venv_dir>/venv-duo/alsa-lib/usr/include -o alsamixer alsamixer-card_select.o alsamixer-bindings.o alsamixer-cli.o alsamixer-colors.o alsamixer-curskey.o alsamixer-configparser.o alsamixer-device_name.o alsamixer-die.o alsamixer-mainloop.o alsamixer-mem.o alsamixer-menu_widget.o alsamixer-mixer_clickable.o alsamixer-mixer_controls.o alsamixer-mixer_display.o alsamixer-mixer_widget.o alsamixer-proc_files.o alsamixer-textbox.o alsamixer-utils.o alsamixer-volume_mapping.o alsamixer-widget.o -L<ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib -lformw -lmenuw -lpanelw -L<ruyi_venv_dir>/venv-duo/ncurses/usr/lib -lncursesw <ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib/libasound.a -lrt -lm -lpthread -static
$ cd ../amixer
$ riscv64-plct-linux-gnu-gcc -D_GNU_SOURCE -I<ruyi_venv_dir>/venv-duo/alsa-lib/usr/include -o amixer amixer.o volume_mapping.o -L<ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib <ruyi_venv_dir>/venv-duo/alsa-lib/usr/lib/libasound.a -lrt -lm -lpthread -static
构建完成后启动 Milkv Duo,启动后将二进制传送。
$ scp -Or aplay/aplay amixer/amixer alsamixer/alsamixer <ruyi_venv_dir>/venv-duo/alsa-lib/usr/share/alsa root@192.168.0.46:~
ssh
到 Milkv Duo 并将二进制和文件安装在正确位置。
# mv alsa /usr/share/
# mv aplay amixer alsamixer /usr/bin/
# ln -s aplay /usr/bin/arecord
检查设备。
# amixer contents
numid=1,iface=MIXER,name='ADC Power'
; type=BOOLEAN,access=rw------,values=2
: values=on,on
numid=3,iface=MIXER,name='ADC Capture Mute'
; type=BOOLEAN,access=rw------,values=2
: values=off,off
numid=2,iface=MIXER,name='ADC Capture Volume'
; type=INTEGER,access=rw------,values=2,min=0,max=24,step=0
: values=0,0
调节输入音量到最大。
# amixer cset numid=2 24
录音,检查是否能够正常采集。
# arecord -d 30 -r 44100 -c 1 -f S16_LE -t wav test.wav
注意在 Milkv Duo 刚启动完成时, arecord
可能会报 Segmentation fault
,稍等一会在尝试便会正常。
录音文件可以使用 Audacity 等软件打开查看波形,调整手台音量输出使波形足够强但又不至于被削波。 Direwolf 建议让大部分台站的音量在 50% 左右,不过并不太清楚高于 50% 有啥实际影响。
构建 Direwolf
构建, <ruyi_venv_dir>
根据实际情况修改。
$ git clone https://github.com/wb2osz/direwolf.git
$ cd direwolf/
$ mkdir build
$ cd build/
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=riscv64-plct-linux-gnu-gcc -DCMAKE_EXE_LINKER_FLAGS="-static" -DCMAKE_FIND_ROOT_PATH=<ruyi_venv_dir>/venv-duo/alsa-lib -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY
$ make -j4
$ make install DESTDIR=../destdir
$ cd ..
$ scp -Or ./destdir root@192.168.0.46:~
ssh
到 Milkv Duo 并将整个 destdir
目录安装到 /opt/direwolf
。
# mv destdir /opt/direwolf
Direwolf 的配置文件放置可以在 /etc/direwolf.conf
,这里给出一个示例配置。
# 输入设备和输出设备,其实物理上输出没有接任何东西
ADEVICE default:CARD=cv182xaadc default:CARD=cv182xadac
ACHANNELS 1
CHANNEL 0
FULLDUP OFF
# 呼号及 SSID, 10 代表互联网网关设备
MYCALL BB5CCC-10
# APRS-IS 服务器
IGSERVER china.aprs2.net
#IGSERVER asia.aprs2.net
# APRS-IS 认证呼号 SSID 及 Passcode
IGLOGIN BB5CCC-10 46464
# 网关自身信标,让其他人知道你的APRS iGate处于工作状态
# every 为自身信标上报间隔时间, lat 和 long 为经纬度, height 为高度
# 由于只收不发, power 和 gain 不设置
# comment 为说明信息
PBEACON sendto=IG delay=1 every=10 symbol=/r lat=30^00.00N long=120^00.00E height=5 freq="144.390" comment="Sakurakaze No Kitsune Testing UV-66 iGate"
LOGDIR /var/log/direwolf
关于频率,中国国内大部分地区使用 144.640MHz,浙江省使用 144.390MHz。
给出一个 Direwolf 的启动脚本 /opt/direwolf/start_direwolf
,在网络和声卡采样正常后启动 Direwolf。
#/bin/sh
echo Check Internet Connection
while ! ping -c 1 bing.com 2>&1 > /dev/null; do
sleep 5s
done
echo Check NTP time update
wt=1
while [ `date '+%Y'` = 1970 ]; do
wt=`expr $wt + 1`
if [ $wt -ge 30 ]; then
echo Wait NTP timeout 30s
break
fi
try $wt
sleep 1s
done
echo Check sound device
while ! arecord -d 1 -r 44100 -c 1 -f S16_LE -t wav /tmp/test.wav; do
sleep 1s
done
echo Start Direwolf
/opt/direwolf/usr/local/bin/direwolf -c /etc/direwolf.conf
前面提到, Milkv Duo 刚启动不久时 arecord
会段错误,故先用 arecord 测试,直到能够正常采样。
调整自启动脚本
编辑 S99zuser
文件,开机自动调整输入音频并启动 Direwolf。
#!/bin/sh
${CVI_SHOPTS}
#
# Set eth0 speed
# Start wpa_supplicant
# Set input audio
#
set_network() {
if [ -f /mnt/system/ko/8188eu.ko ]; then
echo Insmod 8188eu.ko
insmod /mnt/system/ko/8188eu.ko
sleep 1s
fi
if /sbin/ip link | grep eth0; then
echo Set eth0 to 10Mbps
ethtool -s eth0 speed 10
fi
if /sbin/ip link | grep wlan0; then
echo Check wifi config
[ -f /etc/wpa_supplicant/wpa_supplicant.conf ] && wpa_supplicant -B -Dnl80211 -iwlan0 -c/etc/wpa_supplicant/wpa_supplicant.conf
fi
}
case "$1" in
start)
set_network 2>&1 > /var/log/mylog
echo Set input audio >> /var/log/mylog
amixer cset numid=2 24
/opt/direwolf/start_direwolf 2>&1 >> /var/log/mylog &
;;
stop)
;;
restart|reload)
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
手台的配置
- 带宽设置为宽带;反正不要设置为窄带就对头
- 静噪等级设为 0,即一直接收;在 UV-66 上设置 SQL 为 0
- 关闭双频守候,特别在单通道电台上;在 UV-66 上关闭 TDR
- 关闭接收亚音,包括模拟亚音和数字亚音;在 UV-66 上关闭 R-DCS 和 R-CTCS
- 关闭所有提示音;在 UV-66 上需要关闭 BEEP 和 VOICE 两种
- 关闭省电模式;在 UV-66 上静噪为 0 时其实也无所谓,在 SAVE 菜单关闭
尾声
测试该方案时 Wifi 使用了 RTL8188FTV USB 模块,可以直接焊接在 Milkv Duo 背面。
该方案在二楼阳台使用 SG-7900 天线就能有较好的接收效果。
这里是桜風の狐,将美好的 73 送上。