http://www.rigexpert.com/index?s=articles&f=aas で紹介されている回路を一通り自分の中で整理してまとめました。詳しい動作は今まで書いた各エントリにして、ここではそれぞれの特徴を書いてみます。

「アンテナアナライザー」と書いていますが、これをさらに発展させて入出力ポート両方で測定するようにすればネットワークアナライザになるはずです。

ダイオードディテクタ

  • ダイオードで検波するので、小電力時の非直線性が問題になり (誤差が多い) キャリブレーションが必要になる

抵抗1本タイプ

[tech] アンテナアナライザの回路 シリーズ抵抗1本型 | Tue, Mar 1. 2016 - 氾濫原

入力電圧・負荷電圧・負荷電流

  • 回路が簡単
  • 電流検出部で小さな電圧を測ることになる
  • リアクタンスの符号は不明

ブリッジタイプ

[tech] アンテナアナライザの回路 ブリッジ型 | Tue, Mar 1. 2016 - 氾濫原

入力電圧・負荷電圧・負荷電流・平衡電圧

  • 電圧反射係数を別途測っているので、SWR の精度があがる (特に1.0付近)
  • リアクタンスの符号は不明

ログアンプ検波

[tech] アンテナアナライザの回路 - ブリッジの三つの電位差を測るタイプ | Thu, Mar 3. 2016 - 氾濫原

AD8307 を使って検波するタイプ。

入力電圧・負荷電圧・平衡電圧

  • キャリブレーション不要
  • 差動接続のためブリッジの平衡部に直結できる
  • リアクタンスの符号は不明

ログアンプ+位相検出

[tech] アンテナアナライザの回路 ー 位相検出器を使ったタイプ | Fri, Mar 4. 2016 - 氾濫原

AD8302 (ログアンプ+位相差) を使って検波するタイプ

方向性結合器 複素電圧反射係数

  • キャリブレーション不要
  • 移相器を使うものは移相器の調整が必要だがリアクタンスの符号がわかる

複素入力電圧・複素負荷電圧

  • キャリブレーション不要
  • リアクタンスの符号がわかる
  • DDS が2台必要

ヘテロダイン系

[tech] アンテナアナライザの回路 ー ヘテロダインを使ったタイプ | Fri, Mar 4. 2016 - 氾濫原

  • より高い周波数を扱う場合に検討の余地あり
  • 回路はより複雑
  • DSPが必要

雑感

ダイオードディテクタを使う場合、現実的には後段にオペアンプによるバッファ回路を検出電圧分だけつける必要があり、部品数がかなり増加する。

AD8307 で検波する場合、ほかの部品は殆どいらずMCUなどのADCに接続できる。しかも精度が高い。アナログ部分が格段に少なくなるので設計しやすい。値段が高いのだけが問題。

AD8302 で検波する場合、リアクタンス符号がわかるのが嬉しい。しかし AD8302 はかなり高い。そしてDDSも2台必要。

作るなら

これまでを踏まえて、〜50MHz ぐらいまでを対象に、コスト的にそこそこで楽に作れてよさそうというのは AD8307 とブリッジを使うタイプだと思う。

コストをもう少しかけていいのなら、AD8302 + DDS2台 も十分に簡単な回路で作りやすそう。リアクタンスの符号まで知りたいならこれが一番簡単そうに思う。


リアクタンスの符号までわからなくても、現実的にはあまり問題にならないことのほうが多そう。アンテナの調整を目的とする場合リアクタンスは「同調しているかどうか」の判断に使うなら符号はいらないし、調整してリアクタンスが増えるか減るかでも符号を推測できる。

  1. トップ
  2. tech
  3. アンテナアナライザーの回路 ー まとめ

AD8302 (ログアンプ+位相検出器) を使った系です。

方向性結合器の出力を AD8302 に直接入れるタイプ

http://www.rigexpert.com/index?s=articles&f=aas

方向性結合器から進行波と反射波をとりだし、それを直接AD8302に入れるタイプのものです。

AD8302 にはログアンプであるとともに、2信号間の0〜180度の位相差の測定もできます。

位相差も測っているからリアクタンスも符号もわかると言いたいところですが、AD8302 の位相差は基準に対し0〜180度なので、この構成だと符号の区別はつきません。

AD8302 は AD8307 よりもさらに高価 (AD8302 はログアンプが2個と位相検出器が入っているので当然ですが) なので、リアクタンスの符号がわからないのはかなり残念な構成だと思います。正直、AD8302 を使って実装する価値はなさそうです。

計算

測定値として電圧反射係数 Γ の絶対値と位相角度 α がわかります。ということで反射係数の実部と虚部は簡単に求められます。

Γと伝送路インピーダンス・負荷インピーダンスの関係は


分母を有理化しつつ R + j X の形になるように (rectform()) していきます

ということで の形になったので R と X はそれぞれ

となります。計算上 X の符号は失われていませんが、そもそも最初の位相が正しかとれていないので符号がわかりません。

方向性結合器の出力の進行波側の位相を90度シフトしてから AD8302 に入れるタイプ

http://www.rigexpert.com/index?s=articles&f=aas

基準となる進行波の位相をフェーズシフターで90度進めることで、AD8302 の位相検出範囲を -90〜+90度にし、リアクタンス符号を計れるようにしたタイプです。

負荷インピーダンス自体は直接入れるタイプと同じように計算できます。こちらは符号が有効に出てきます。

広い周波数で正確にフェーズシフターを動かすのが難しいところだと思います。

抵抗ブリッジのリファレンス電圧と負荷電圧を計るタイプ

http://www.rigexpert.com/index?s=articles&f=aas

ブリッジのリファレンス複素電圧と、負荷の複素電圧を計るタイプです。AD8302 の片方には90度位相シフトした元の波形を入力し、位相検出範囲を -90〜+90度 にしています。

位相シフトした基準信号はDDSで作ります。つまりブリッジ入力用の信号源と、基準信号用の信号源とで DDS が2台必要です。しかし DDS なので広い周波数で正確な90度信号を作りだせます。

調整がいらないのが最大のメリットだと思います。

反射係数を直接測っておらず、基準電圧と負荷電圧を測っています。

E_{LOAD} と E_{REF} の絶対値と角度がわかっているので

電圧反射係数 Γ は

あとは上記の複素電圧反射係数から R と X を求める形でいけそうです。

  1. トップ
  2. tech
  3. アンテナアナライザの回路 ー 位相検出器を使ったタイプ

ヘテロダイン(周波数変換)を使ったタイプ

http://www.rigexpert.com/index?s=articles&f=aas

この方法の利点は信号を選択できることで、矩形波の高調波も信号源とできることだと思われます。つまり低い周波数しか発振できなくても、高調波を使うことで広い周波数を測定できます。

アンテナの入力に適当な信号を入力し、測定したい周波数 + f の周波数を出力に合成して、低い周波数 (中間周波数) f に測定したい周波数を変換します。この中間周波数にバンドパスフィルタをかければ目的信号を選択できます。

十分低い固定の周波数に変換されるので、実際の検波処理・位相差検出はADCとソフトウェア処理で行えます。

ダイレクトコンバージョンを使ったタイプ

http://www.rigexpert.com/index?s=articles&f=aas

ヘテロダインの一種ですが、目的周波数自体と、位相差90度の信号を出力に合成して、I/Q 信号として直接 0Hz にコンバートします。実際の検波処理・位相差検出はADCとソフトウェア処理で行います。

  1. トップ
  2. tech
  3. アンテナアナライザの回路 ー ヘテロダインを使ったタイプ

http://www.rigexpert.com/index?s=articles&f=aas

ブリッジの50Ω/50Ωで分圧したほうの電位 、負荷側の電位 、ブリッジ間の電位差 を測っているタイプです。

完全差動ログアンプのAD8307で検波を行っているのでダイオード検波にあるような非直線性を回避しつつ、外部にSPDT RFスイッチを2つだけ配置して高価なログアンプを1台ですませていて、このページの中だと一番おもしろい感じがします。

このタイプはなかなか理解できませんでした。

計算

ダメパターン

入力電圧を 1 としたとき、 の電圧は50Ωの と、負荷インピーダンス で分圧した形になりますから、

にかかる電圧は入力電圧から をひいて

の抵抗値は分っているので、電流値 を求めてみると

から を求めてみると

(2) を変形して (1) に代入すれば一発ですが、一旦電流を経由しています。

しかし測定している が絶対値なので、リアクタンスがある場合、 これでは正確に を求めることはできなそうです。

似たような方法で測定していて、上記のように説明しているページが見つかりましたが純抵抗で校正検証してるようでよくわかりませんでした……

http://www.kn9b.us/cloud-concept

じゃあどうするか

このパターンだと、ブリッジ間の電位差も測っています。この電位差は じゃないの? という感じで一見無駄のように見えますが、リアクタンス成分がある場合、検波するまでは複素数なので、同じにはなりません。

イメージとしては、 を測っているときと、オフセットされた との差の関係を見るという感じでしょうか。

複素電圧の関係を図にすると以下にようになります。青のベクトルが 、赤のベクトルが 、緑のベクトルが を表しています。

半径の円の交点の座標がわかれば の複素電圧がわかることが見てとれます。

負荷電圧と反射係数だけから負荷の複素インピーダンスを求める

(複素インピーダンスといってもリアクタンスは例によって絶対値だけです)

図形的に複素電圧がわかりそう、ということは複素インピーダンスもわかりそうだ、ということで、数式をいじくって解いてみます。

まず とブリッジの入力電圧である の関係を確認しておきます


の絶対値を式にすると

の絶対値を式にすると

(1) と (2) の連立方程式から を求めます。あきらかに面倒なので maxima で解きました。

と、やたら複雑ですが解くことができました。もっと綺麗な式になるかもしれませんが……

余談ですが maxima に連立方程式を解かせる場合、sqrt() を分解してくれないことがあるので、そこだけ自力でやったりすると解けたりします。

シミュレーションで確かめる

LTSpice でブリッジと負荷を構成し、作った負荷と、実際にシミュレーションして得た電圧から上記で求めた複素インピーダンスを比較して確認します。

以下のような回路です。

.meas を使って各ポイントの電圧を求めています。RMSを検波出力としています。こんな感じでログに出ます。

ログの出力をいちいちコピペして計算するのもダルいので、このログの出力をパースして上記式で解いてみる Ruby スクリプトを書いてみました。

コードは末尾に置きますが、結果だけコピペすると以下の通りでした。(ltspice simulated voltages) から求めたのが calculated で、calculated error に計算されるべき値との差が入っています。だいたい計算はあってそうです。

ruby 2.0.0p645 (2015-04-13 revision 50299) [universal.x86_64-darwin15]
Condition:
	{:r=>25.0, :x=>1591.5494309189535, :z=>1591.74576834947}
complex v:
	{:v_r=>0.9985228396122859, :v_i=>0.031346316992564995}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.9990147410405821, :e_diff=>0.49950737052029104}
(ltspice simulated volatages):
	{:e_ref=>0.350149, :e_load=>0.699604, :e_diff=>0.3498}
calculated:
	{:r=>25.2897097114912, :x=>1591.5067030422704, :z=>1591.7076224124105}
calculated error:
	{:r=>-0.2897097114911986, :x=>0.042727876683102295, :z=>0.038145937059425705}

Condition:
	{:r=>50.0, :x=>1591.5494309189535, :z=>1592.3346353886939}
complex v:
	{:v_r=>0.9980338412035863, :v_i=>0.03129238913528186}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.9985242920457066, :e_diff=>0.49901595225182244}
(ltspice simulated volatages):
	{:e_ref=>0.35015, :e_load=>0.69926, :e_diff=>0.349455}
calculated:
	{:r=>50.32437181406401, :x=>1589.9247651730511, :z=>1590.7210004614456}
calculated error:
	{:r=>-0.3243718140640084, :x=>1.6246657459023481, :z=>1.613634927248313}

Condition:
	{:r=>75.0, :x=>1591.5494309189535, :z=>1593.3155968164137}
complex v:
	{:v_r=>0.9975477257601216, :v_i=>0.03122332536748392}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.9980362524558889, :e_diff=>0.4985264641481664}
(ltspice simulated volatages):
	{:e_ref=>0.350146, :e_load=>0.69891, :e_diff=>0.349107}
calculated:
	{:r=>75.577314946581, :x=>1592.1658690154652, :z=>1593.9586208532223}
calculated error:
	{:r=>-0.5773149465809979, :x=>-0.6164380965117289, :z=>-0.6430240368085833}

Condition:
	{:r=>25.0, :x=>159.15494309189532, :z=>161.10647383201098}
complex v:
	{:v_r=>0.8788575625045866, :v_i=>0.25707223660794654}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.9156837609164615, :e_diff=>0.45784188045823077}
(ltspice simulated volatages):
	{:e_ref=>0.350146, :e_load=>0.6411, :e_diff=>0.320345}
calculated:
	{:r=>25.333147144876502, :x=>159.41449698716028, :z=>161.4148388281985}
calculated error:
	{:r=>-0.3331471448765022, :x=>-0.25955389526495765, :z=>-0.308364996187521}

Condition:
	{:r=>50.0, :x=>159.15494309189532, :z=>166.8241466652368}
complex v:
	{:v_r=>0.858478400162449, :v_i=>0.22523862168419417}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.8875345628445539, :e_diff=>0.4233665079824152}
(ltspice simulated volatages):
	{:e_ref=>0.350147, :e_load=>0.6215, :e_diff=>0.296282}
calculated:
	{:r=>50.449523403617995, :x=>159.4899517034167, :z=>167.27880650581648}
calculated error:
	{:r=>-0.44952340361799514, :x=>-0.3350086115213742, :z=>-0.4546598405796658}

Condition:
	{:r=>75.0, :x=>159.15494309189532, :z=>175.9411717324414}
complex v:
	{:v_r=>0.8473945832635346, :v_i=>0.19430325132965703}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.8693856067486138, :e_diff=>0.39804114103710525}
(ltspice simulated volatages):
	{:e_ref=>0.350147, :e_load=>0.608911, :e_diff=>0.278669}
calculated:
	{:r=>75.55035761860219, :x=>159.54194370186138, :z=>176.52616898484652}
calculated error:
	{:r=>-0.5503576186021917, :x=>-0.38700060996606567, :z=>-0.5849972524051168}

Condition:
	{:r=>25.0, :x=>15.915494309189533, :z=>29.636176526432088}
complex v:
	{:v_r=>0.36206078079200993, :v_i=>0.1353749068388477}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.38654155583759237, :e_diff=>0.19327077791879618}
(ltspice simulated volatages):
	{:e_ref=>0.350148, :e_load=>0.271725, :e_diff=>0.135173}
calculated:
	{:r=>25.089881853395678, :x=>16.0713690194714, :z=>29.7958230894429}
calculated error:
	{:r=>-0.08988185339567778, :x=>-0.15587471028186783, :z=>-0.15964656301081348}

Condition:
	{:r=>50.0, :x=>15.915494309189533, :z=>52.471925437378836}
complex v:
	{:v_r=>0.5123522615159288, :v_i=>0.0776115480673238}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.5181972522832335, :e_diff=>0.07858836273879492}
(ltspice simulated volatages):
	{:e_ref=>0.350148, :e_load=>0.363498, :e_diff=>0.0557211}
calculated:
	{:r=>50.08913489974573, :x=>16.133109401993394, :z=>52.62317601572157}
calculated error:
	{:r=>-0.08913489974572997, :x=>-0.21761509280386093, :z=>-0.15125057834273292}

Condition:
	{:r=>75.0, :x=>15.915494309189533, :z=>76.67009168577957}
complex v:
	{:v_r=>0.6063811091086553, :v_i=>0.0501171137437655}
(calculate with 0.5):
	{:e_ref=>0.5, :e_load=>0.6084486622335925, :e_diff=>0.11759534627353731}
(ltspice simulated volatages):
	{:e_ref=>0.350148, :e_load=>0.426484, :e_diff=>0.0828987}
calculated:
	{:r=>75.08881154062821, :x=>16.196121314941593, :z=>76.8156492144165}
calculated error:
	{:r=>-0.08881154062821395, :x=>-0.28062700575205923, :z=>-0.14555752863692817}

検証コード

require 'pp'

result = <<-EOS
.step r=25 c=1e-11
.step r=50 c=1e-11
.step r=75 c=1e-11
.step r=25 c=1e-10
.step r=50 c=1e-10
.step r=75 c=1e-10
.step r=25 c=1e-09
.step r=50 c=1e-09
.step r=75 c=1e-09


Measurement: e_ref
  step	RMS(v(ref))	FROM	TO
     1	0.350149	0	3e-06
     2	0.35015	0	3e-06
     3	0.350146	0	3e-06
     4	0.350146	0	3e-06
     5	0.350147	0	3e-06
     6	0.350147	0	3e-06
     7	0.350148	0	3e-06
     8	0.350148	0	3e-06
     9	0.350148	0	3e-06

Measurement: e_load
  step	RMS(v(load))	FROM	TO
     1	0.699604	0	3e-06
     2	0.69926	0	3e-06
     3	0.69891	0	3e-06
     4	0.6411	0	3e-06
     5	0.6215	0	3e-06
     6	0.608911	0	3e-06
     7	0.271725	0	3e-06
     8	0.363498	0	3e-06
     9	0.426484	0	3e-06

Measurement: e_diff
  step	RMS(v(load)-v(ref))	FROM	TO
     1	0.3498	0	3e-06
     2	0.349455	0	3e-06
     3	0.349107	0	3e-06
     4	0.320345	0	3e-06
     5	0.296282	0	3e-06
     6	0.278669	0	3e-06
     7	0.135173	0	3e-06
     8	0.0557211	0	3e-06
     9	0.0828987	0	3e-06
EOS

steps = []
name = nil
result.split(/\n/).each do |line|
	case line
	when /^\.step r=(?<r>\d+) c=(?<c>.+)/
		r = Regexp.last_match[:r].to_f
		c = Regexp.last_match[:c].to_f
		steps << {
			r: r,
			c: c,
			data: {}
		}
	when /^Measurement: (?<name>.+)/
		name = Regexp.last_match[:name]
		steps.last[:data]
	when /^     (?<n>\d+)	(?<value>[\d.]+)	0	3e-06/
		n = Regexp.last_match[:n].to_i - 1
		value = Regexp.last_match[:value].to_f
		steps[n][:data][name] = value
	end
end

Z_0 = 50.0
freq = 10e6;

def Math.pow(a, b)
	a ** b
end

steps.each do |step|
	farad = step[:c]
	resitance = step[:r];
	reactance = 1 / (2 * Math::PI * freq * farad);
	z = Math.sqrt(reactance * reactance + resitance * resitance);
	expected = {r: resitance, x: reactance, z: z}
	puts "Condition:\n\t#{expected}"

	e_ref = 0.5
	e_load = Math.sqrt( (resitance * resitance + reactance * reactance) / (Math.pow(resitance + Z_0, 2) + reactance * reactance) ) * 2 * e_ref;
	e_diff = Math.sqrt(
		(Math.pow(resitance - Z_0, 2) + reactance * reactance) /
		(Math.pow(resitance + Z_0, 2) + reactance * reactance)
	) * e_ref;

	v_r = (Math.pow(e_ref, 2)+Math.pow(e_load, 2)-Math.pow(e_diff, 2))/(2*e_ref);
	v_i = Math.sqrt(-Math.pow(e_ref, 4)+2*Math.pow(e_load, 2)*Math.pow(e_ref, 2)+2*Math.pow(e_diff, 2)*Math.pow(e_ref, 2)-Math.pow(e_load, 4)+2*Math.pow(e_diff, 2)*Math.pow(e_load, 2)-Math.pow(e_diff, 4))/(2*e_ref);
	puts "complex v:\n\t#{{v_r: v_r, v_i: v_i}}"

	puts "(calculate with 0.5):\n\t#{{
		e_ref: e_ref,
		e_load: e_load,
		e_diff: e_diff,
	}}"

	e_ref = step[:data]["e_ref"]
	e_load = step[:data]["e_load"]
	e_diff = step[:data]["e_diff"]

	puts "(ltspice simulated volatages):\n\t#{{
		e_ref: e_ref,
		e_load: e_load,
		e_diff: e_diff,
	}}"

	r = ((Math.pow(e_ref, 2)-Math.pow(e_diff, 2))*Z_0) / (2*Math.pow(e_ref, 2)-Math.pow(e_load, 2)+2*Math.pow(e_diff, 2));
	x = Math.sqrt(-Math.pow(e_ref, 4)+2*Math.pow(e_load, 2)*Math.pow(e_ref, 2)+2*Math.pow(e_diff, 2)*Math.pow(e_ref, 2)-Math.pow(e_load, 4)+2*Math.pow(e_diff, 2)*Math.pow(e_load, 2)-Math.pow(e_diff, 4))*Z_0/(2*Math.pow(e_ref, 2)-Math.pow(e_load, 2)+2*Math.pow(e_diff, 2));
	z = Math.sqrt(r * r + x * x)
	puts "calculated:\n\t#{{r: r, x: x, z: z}}"
	puts "calculated error:\n\t#{{r: expected[:r] - r, x: expected[:x] - x, z: expected[:z] - z}}"

	puts
end
  1. トップ
  2. tech
  3. アンテナアナライザの回路 - ブリッジの三つの電位差を測るタイプ

ほんと保育園関連のアレコレが嫌すぎて嫌すぎてどうしようもない…… なんとかしてくれ……… こんな無限に時間がないのにクソどうでもいい(子供の保育に直接関係がない) ことで時間が無駄にとられるのが嫌で嫌でしかたない。そして必要以上のコミュニケーションを求められるのが嫌で嫌でしかたがない。朝子供を送って先生を挨拶をかわすのすら嫌なのに (これは仕方ないからやってるだけで嫌なのだ)、それ以上のことを本当に心の底からしたくない。

毎日最低8時間を仕方なしに嫌々として気分で過ごしているのに、それに加えて嫌々とした気分にさせられることが自動的に追加され、何をやるにしても嫌なことが発生し続ける。果たしてこれを打ち消すぐらいの良いことがあるだろうか? 果たしてこれを打ち消すぐらいの良いことがあるだろうか?

別にすぐに死ぬ病気があって生き急いでいるとかではないが、最大でも90歳程度、そしてどんどん頭が悪くなるのを考えれば、70歳程度が人生の限界と思える。もうあと40回ぐらい春がくれば生産的な人生はおしまいなのだ。

1年にひとつ、できることが増えたとしても、あと40個しかできることは増えない。そして死ぬ。定年が65だとしたら、フルタイムで時間がとれるのはたったの5年。しかも劣化した頭の5年。始めるのに遅すぎるということはないが、決して納得いくレベルまでいかずに死ぬことになる。こういう事実にどう向きあえばいいだろうか?

この問題は生の問題であって、社会的な問題ではない。仕事に無駄に時間をとられているという点では社会的な問題だが、本質的には人間としての寿命の話だ。自分の中で納得して死ねるか、満足できるぐらいの技術力を獲得し、おれは頑張ったと思って死ねるか。そういう話だ。


よく「面白くなってきた」というところで変なことが起きて水を差されることがある。そして「せっかく面白くなってきたのに」という台無しな気分にさせられる。人生の終盤では寿命によって水を差される。

最近ちょっと数学がおもしろい。数学といってもレベルが低いことしかしてない (なんといっても僕は微分積分を高校で習っておらず、微分積分の解きかたすらしらないのだ)。

元々方程式を立てたりするのは嫌いではない。というのも機械的な操作で (つまり頭をつかわずに) 答えを導きだせる方法論として面白いからだ。行列も、連立方程式を機械的に解く方法と考えると親近感がわく。

しかし解くのは好きではない。ある操作が正しい操作かどうか、いちいち自信を持てないからだ。単に慣れてないというだけではあるけれども、ストレスになる。maxima を使うようになってからこのストレスは著しく軽減された。「これで正しんだっけ?」と思ったとき、maxima に解かせれば必ず正しいことがわかる。僕は自分を信用しておらず、機械を全面的に信頼している。


数式を読むのは英語を読むような感覚に似ている。ネイティブで理解することはできないが、頑張って読もうとすると読めることがある。読めると「そういうことか」と思うことがある。

「xx が xx なのは本当なのか」という不安を解消するのに数式が役立ってくれるように感じる。