Строим графики КСВ с помощью Mini60S и Python

19 июня 2019

Один из недостатков антенного анализатора Mini60S заключается в том, что им неудобно смотреть изменение параметров антенны на широком интервале частот (например, от 1 до 30 МГц). Приложение Open60 позволяет строить такие графики, но делает это с большим шагом (около 1 МГц), из-за чего картина получается смазанной. Другой недостаток заключается в том, что иногда приложение подключается к устройству по Bluetooth не с первого раза. Было решено попробовать исправить оба недостатка при помощи небольшого набора скриптов.

Mini60S является клоном открытого антенного анализатора SARK-100, созданного испанским радиолюбителем Melchor Varela, EA4FRB. Оригинально SARK-100 можно было приобрести в виде набора для сборки. К сожалению, с октября 2011 наборы больше не выпускаются, а сам проект был объявлен устаревшим в пользу более продвинутого (и дорогого) анализатора SARK-110. Однако архив сайта SARK-100 до сих пор доступен онлайн вместе с прошивкой, схемой и пользовательским мануалом. Сейчас нас особенно интересует последний.

На странице 35 мы можем узнать, что устройство имеет USB-UART интерфейс, и что его скорость — 57600 бод. В свою очередь «Appendix I: PC Command Interface» на странице 77 содержит список поддерживаемых команд. Давайте проверим. Подключаем Mini60S к компьютеру через USB, нажимаем SET → PC Link. На компьютере говорим:

sudo cu -l /dev/tty.usbserial-00000000 -s 57600 -h

Попробуем ввести какую-нибудь команду:

>>scan 7000000 7200000 25000
Start
1.27,57,0,58
1.28,58,0,59
1.29,59,0,60
1.30,60,0,61
1.32,62,0,63
1.35,63,0,64
1.38,63,16,65
1.43,65,16,67
End

Хм… выглядит чем-то рабочим. Теперь дело за малым — автоматизировать сбор данных и их визуализацию.

За сбор будет отвечать скрипт mini60scan.py:

#!/usr/bin/env python3 -u
# vim: set ai et ts=4 sw=4:

import serial
import argparse

parser = argparse.ArgumentParser(
    description='Scan antenna parameters using SARK100/Mini60'
    )
parser.add_argument(
    '-b', '--begin', metavar='N', type=int, required=True,
    help='Frequency to start from, Hz')
parser.add_argument(
    '-e', '--end', metavar='N', type=int, required=True,
    help='The end frequency, Hz')
parser.add_argument(
    '-s', '--step', metavar='N', type=int, required=True,
    help='Step size, Hz')
parser.add_argument(
    '-d', '--device', metavar='D', type=str, required=True,
    help='Serial port device name (e.g. /dev/tty.usbserial-00000000)')
parser.add_argument(
    '-r', '--baudrate', metavar='N', type=int, default=57600,
    help='Baud rate (default 57600)')
args = parser.parse_args()

with serial.Serial(args.device, args.baudrate) as conn:
    cmd = "scan {} {} {}".format(args.begin, args.end, args.step)
    conn.write((cmd+"\r\n").encode('ascii'))
    freq = args.begin
    print("Freq,SWR,R,X,Z")
    while True:
        line = conn.readline().decode('ascii').strip()
        if line == '':
            continue
        elif line == 'Start':
            continue
        elif line == 'End':
            break
        swr, r, x, z = line.split(',')
        print("{},{},{},{},{}".format(freq,swr,r,x,z))
        freq += args.step

Пример использования:

sudo ./mini60scan.py -b 1500000 -e 30000000 -s 25000 \
  -d /dev/tty.usbserial-00000000 | tee double-vertical.csv

Скан от 1.5 МГц до 30 МГц с шагом 0.25 МГц дает достаточно точную картину и занимает 2 минуты 30 секунд. Если вы желаете просканировать тот же диапазон с шагом 0.1 МГц, это займет у вас 6 минут 10 секунд.

Для рисования графиков входного сопротивления и КСВ антенны воспользуемся библиотекой Matplotlib. Код скрипта mini60plot.py:

#!/usr/bin/env python3 -u
# vim: set ai et ts=4 sw=4:

import matplotlib as mpl
# for MacOS, see https://stackoverflow.com/a/21789908/1565238
mpl.use('TkAgg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import sys

if len(sys.argv) < 3:
    print("Usage: " + sys.argv[0] + " input.csv output.png")
    sys.exit(1)

infile = sys.argv[1]
outfile = sys.argv[2]
swr_color = 'green'
z_color = 'red'
freqs = []
values = { 'swr' : [], 'z': [] }
nline = 0
min_freq, max_freq = 9999, 0
max_swr, max_z = 0, 0

with open(infile, newline = '') as f:
    for line in f:
        nline += 1
        if nline == 1: # skip title
            continue
        f, swr, r, x, z = [ float(x) for x in line.strip().split(",") ]
        f = f / 1000000
        print("f = {}, swr = {}".format(f, swr))
        freqs += [f]
        values['swr'] += [ swr ]
        values['z'] += [ z ]
        max_swr = max(swr, max_swr)
        min_freq = min(f, min_freq)
        max_freq = max(f, max_freq)
        max_z = max(z, max_z)

dpi = 80
fig = plt.figure(dpi = dpi, figsize = (512 / dpi, 384 / dpi) )
mpl.rcParams.update({'font.size': 10})

ax1 = fig.add_subplot(111)
lns1 = ax1.plot(freqs, values['swr'], color=swr_color,
                linestyle = 'solid', label = 'SWR')
ax1.set_xlabel("Freq (MHz)")
ax1.set_xlim(min_freq, max_freq)
# ax1.set_ylabel("SWR", color = swr_color)
ax1.yaxis.label.set_color(swr_color)
ax1.tick_params(axis='y', colors=swr_color)
ax1.spines['left'].set_color(swr_color)
ax1.spines['right'].set_color(z_color)
ax1.set_ylim(1, max_swr)

# highlight amateur radio bands
for band in [ [1.8, 2.0], [3.5, 3.8], [7.0, 7.2], [10.1, 10.15],
              [14.0, 14.35], [18.068, 18.168], [21.0, 21.45],
              [24.89,24.99], [28.0,29.7] ]:
    ax1.axvspan(band[0], band[1], color='grey', alpha=0.3)

ax2 = ax1.twinx()
lns2 = ax2.plot(freqs, values['z'], color=z_color,
                linestyle = 'solid', label = 'Z (Ω)')
# ax2.set_ylabel("Z", color = z_color)
ax2.yaxis.label.set_color(z_color)
ax2.tick_params(axis='y', colors=z_color)
ax2.spines['left'].set_color(swr_color)
ax2.spines['right'].set_color(z_color)
ax2.set_ylim(0, max_z)

lns = lns1 + lns2
labs = [ x.get_label() for x in lns ]
ax2.legend(lns, labs, framealpha = 1, loc = 'upper right')

fig.savefig(outfile)

Пример использования:

./mini60plot.py ./double-vertical.csv ./double-vertical.png

А так выглядит результат:

График КСВ и входного сопротивления антенны

Можно догадаться, что здесь мы смотрим на вертикал, описанный в недавнем посте Походная антенна-вертикал на диапазоны 15, 20 и 40 метров.

В данном контексте следует сказать пару слов о том, как именно следует производить измерения. В идеале антенный анализатор следует подключать прямо к месту запитки, или напрямую к балуну / запорному дросселю, если он предсмотрен в антенне. Использование даже пары метров коаксиального кабеля вносит заметные искажения.

Тому есть ряд причин. В частности, ни один запорный дроссель не избавляет от синфазного тока на 100%. Следовательно, кабель всегда немножечко, но все-таки излучает. Кроме того, линия никогда не бывает идеальной, а значит в ней всегда есть какие-то потери. В случае с КСВ это особенно критично, потому что сначала сигнал ослабевает по пути в одну сторону, какая-то часть ослабленного сигнала отражается, и идет до КСВ-метра, ослабевая на обратном пути. В итоге КСВ-метр видит стоячую волну, образованную исходным сигналом и ослабленным отражением ослабленного сигнала. Добавьте сюда прочие факторы — волновое сопротивление кабеля, немного отличное от 50 Ом, не совсем точную калибровку устройства, и так далее, и можно легко увидеть КСВ 3-4 вместо КСВ 5-10 при использовании всего лишь нескольких метров RG58.

Fun fact! Двухпроводные линии с высоким волновым сопротивлением (от 300 до 600 Ом) имеют очень небольшие потери на КВ, поэтому написанное относится к ним в меньше степени. Однако при использовании такого фидера возникают другие нюансы — согласование импеданса, необходимость в отсутствии металлических предметов или земли на расстоянии от линии, равном десяти расстояниям между ее проводами, и так далее.

Такие дела. Теперь, когда 1) соединение с устройством действительно надежно, без этих ваших модных беспроводных протоколов, 2) сканирование диапазона можно производить с любым желаемым шагом и 3) мы выяснили, как правильно производить измерения, КСВ-метром прям стало можно пользоваться.

Дополнение: См также обзоры антенного анализатора EU1KY и NanoVNA.

Метки: , , .


Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.