基于 Milkv Duo 和国产手台的 APRS IGate

2024-04-11

自动位置回报系统(APRS)是一种基于业余无线电在本地进行实时信息交换的数字通信协议,这些信息可以包含 GPS 定位、气象站数据、短消息等。

APRS 在中国国内通常用于实时位置分享,而 APRS IGate( APRS 网关)则是一种 APRS 接收电台,它将接收到的 APRS 数据包解码并传输到 APRS 服务器上。 APRS 服务器上的数据将被显示在 APRS 地图上供查阅。常用的 APRS 地图有 aprs.fiaprs.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 $?

手台的配置

  1. 带宽设置为宽带;反正不要设置为窄带就对头
  2. 静噪等级设为 0,即一直接收;在 UV-66 上设置 SQL 为 0
  3. 关闭双频守候,特别在单通道电台上;在 UV-66 上关闭 TDR
  4. 关闭接收亚音,包括模拟亚音和数字亚音;在 UV-66 上关闭 R-DCS 和 R-CTCS
  5. 关闭所有提示音;在 UV-66 上需要关闭 BEEP 和 VOICE 两种
  6. 关闭省电模式;在 UV-66 上静噪为 0 时其实也无所谓,在 SAVE 菜单关闭

尾声

测试该方案时 Wifi 使用了 RTL8188FTV USB 模块,可以直接焊接在 Milkv Duo 背面。

该方案在二楼阳台使用 SG-7900 天线就能有较好的接收效果。

这里是桜風の狐,将美好的 73 送上。

4 Likes

太棒了!!!!!!!
我们希望能看到更多的实际应用,希望duo能帮到你~