KX3 と PC だけで SWR グラフにできたら便利なのになー と思っていたけど、少し前に調べたところ SWR を直接読む方法がなく、諦めていた。
しかし、KX3 Utility で Power Calibration を実行すると、SWR を読んでいるっぽい挙動が確認でき、読める方法があるということがわかった。KX3 Utility は親切にも全部のコマンドを出力してくれてるので、それを読んだだけでうまいこといけた。
やりかたとしては
- TUNE ボタンを押す (SWH16; スイッチホールド)
- ディスプレイに現在の SWR が表示される
- DS; で「ディスプレイに表示されている内容」を取得する
- SWR とれる
という感じだった。いろいろとコードを追加して、現在周波数の±を指定してSWRを取得するコードを書いてみた。結構いい感じ
require 'serialport'
@port = SerialPort.new(
"/dev/tty.usbserial-A402PY11",
38400,
8,
1,
0
)
@port.set_encoding(Encoding::BINARY)
TEXT_MAP = {
'<' => 'L',
'>' => '-',
'@' => ' ',
'K' => 'H',
'M' => 'N',
'Q' => 'O',
'V' => 'U',
'W' => 'I',
'X' => 'c-bar',
'Z' => 'c',
'[' => 'r-bar',
'\\' => 'λ',
']' => '',
'^' => '',
}
def get_swr(step=3)
ret = 0
step.times do
@port << "DS;"
data = @port.gets(";")
t, a, f = *data.match(/DS(........)(.)(.)/).captures
t = t.split(//).reduce("") {|r, i|
chr = (i.ord & 0b01111111).chr
r << ( ( (i.ord & 1<<7) != 0) ? ("." + chr) : (chr) )
}.gsub(Regexp.new(TEXT_MAP.keys.map {|i| Regexp.escape(i) }.join("|")), TEXT_MAP)
if m = t.match(/([\d]+.[\d]+)-I/)
swr = m[1]
else
return nil
end
ret += swr.to_f
end
ret / step
end
def get_freq
@port << "FA;"
res = @port.gets(";")
freq = res.match(/FA(\d{11})/)[1].to_i
end
def set_freq(freq)
@port << ("FA%011d;" % freq)
get_freq == freq or raise "Failed to set freq"
end
def bypass_atu(&block)
@port << "MN023;"
@port << "MP;"
current = @port.gets(";")
current =~ /^MP\d{3}/ or raise "Unknown Responde #{current}"
@port << "MP001;MP;"
res = @port.gets(";")
res == "MP001;" or raise "Failed to set KAT3 bypass: #{res}"
@port << "MN255;"
block.call
ensure
@port << "MN023;"
@port << current
@port << "MN255;"
end
def tune(&block)
@port << 'SWH16;'
sleep 0.5
@port << 'TQ;'
@port.gets(";") == 'TQ1;' or raise "Band END"
sleep 0.3
block.call
ensure
@port << "RX;"
sleep 0.5
@port << "TQ;"
@port.gets(";") == 'TQ0;' or raise "Failed to back to RX"
end
def scan_swr
result = []
@port << "PC;"
current_power = @port.gets(";")
@port << "PC001;PC;"
@port.gets(";") == "PC001;" or raise "Failed to set power"
bypass_atu do
freq = get_freq
step = 20e3
range = Range.new(freq - 100e3, freq + 100e3)
catch(:done) do
begin
set_freq(range.first)
tune do
range.step(step) {|n|
set_freq(n)
swr = get_swr(3)
if swr.nil?
throw :done
end
r = [n, swr]
p r
result << r
}
end
rescue => e
if e.message = "Band END"
range = Range.new(range.first + step, range.last)
retry
end
ensure
set_freq(freq)
end
end
end
result
ensure
@port << current_power
@port << "PC;"
@port.gets(";") == current_power or raise "Failed to back to power"
end
p scan_swr
- トップ
-
tech
-
KX3 でシリアルポートから SWR を読み出す