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

このページが面白いので、1つ1つ見ていきたいという気持ちがあります。まずは一番上の Analyzers based on diode detectors のうち、抵抗1本を検出に使うものです。

やってることは負荷インピーダンスを電流と負荷電圧から求め、さらに入力電圧との関係からリアクタンスの絶対値まで求めるものです。

計算

1 を 、2 を 、3 を という名前にします。

負荷 に対し、それぞれの電圧を としとき、負荷 にかかっている電圧 の絶対値(検波値) は

回路全体にかかる電圧

(1) の式を について解いて

(3) を (2) に代入する。

これを について解く

(3) の式のルートをとって を求めると

また、回路全体の電流

負荷 はそれぞれ

となり、抵抗成分とリアクタンス成分の絶対値が求まる (容量性か誘導性かはわからない)

  1. トップ
  2. tech
  3. アンテナアナライザの回路 シリーズ抵抗1本型

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

ブリッジタイプ (図の右側。2番)

これはリターンロスブリッジを使う形のものです。

  • 1を
  • 2を
  • 3を
  • 4を

とすると

から電圧反射係数が求められます。 で入力電圧を求め、 で得た電圧反射係数を正規化するイメージ)

から負荷インピーダンスの絶対値がわかります。

ブリッジのイメージをつかむ

一番問題なのはブリッジに接続されている がどのようになるかです。負荷側の電位は50Ωと負荷インピーダンスとの分圧、もう片方は50Ωと50Ωの分圧で固定になっています (すなわち入力電圧の0.5倍が基準点)。

ここでもし負荷インピーダンスが50Ωであれば、負荷側の分圧も入力電圧の0.5倍になり、ブリッジ部分の電位差はゼロになります。ブリッジの平衡状態です。

負荷インピーダンスが25Ωになると、25/(25+50)=0.333... で電位差が -0.1666...、100Ωになると 100/(100+50)=0.666... で電位差が 0.1666... になります。つまりここの電位差は基準インピーダンス50Ωに対しての比になります。

もし入力電圧が1Vだとしたら、この電位差の2倍がすなわち電圧反射係数になります。(反射係数には複素数の場合、角度が出てくるが、位相は計っていないのでこれはわからず、この反射係数は絶対値です)

ブリッジ電位差が反射係数になっていることを確かめる

ブリッジ中の負荷インピーダンスを とし、それ以外のインピーダンス値を とすると、入力電圧が1Vのときのブリッジの電位差 E は以下のようになります。ここで、 をブリッジの50Ω/50Ωで分圧された側の電位、 を負荷側の電位としています。

電圧反射係数は

なので、1Vのとき、ブリッジの電位差は反射係数の半分になっています。また、 は入力の半分の電圧になりますから、ブリッジ電位差 で正規化することで反射係数そのものを求められます。

反射係数の大きさと、負荷インピーダンスがわかると、負荷の成分がわかる

反射係数の大きさと、負荷インピーダンスがわかると、まず負荷の抵抗成分を求められます。

反射係数の大きさ 、伝送路インピーダンス 、負荷インピーダンス の関係は以下の通りです。

は 50Ω なので 50 で置き換え、Z は R + jX に置き換えます。

絶対値同士の比なので分子分母とも絶対値にします

負荷インピーダンスの絶対値が既知ですから

(2) を (1) に代入します

難しいので maxima で解かせて

R が求められれば 、Z との関係から X の絶対値も求められます。

あれ? VSWR って簡単な比で求められなかったけ?

VSWR は以下のような式で求められますが、これは負荷インピーダンスが純抵抗な場合 (jX = 0) だけで、純抵抗でなければ反射係数を一旦求める必要があります。

この式を前提にインピーダンス比がSWRになる(インピーダンスがSWRに直接関連づく)と覚えていると、SWRと負荷インピーダンスの値から R が求められる理屈がわからなくなります。

インピーダンス比からSWRを求めた場合、純抵抗を想定してSWR値を求めたわけですから、このSWRと負荷インピーダンスからRを逆算すると、必ず jX の項は0になります。

別の説明をすると、たとえ同じ絶対値の負荷インピーダンスでも、リアクタンス成分でSWRは上がります。Z = 50 であっても、50 + 0j の場合と 0 + 50j の場合では違うよということで、前者のSWRは1ですが後者は無限です。

  1. トップ
  2. tech
  3. アンテナアナライザの回路 ブリッジ型

リターンロスブリッジを買ってみたので、手元にあるいろんなものを測ってみました。

測定方法

普通のリターンロスブリッジなので、DUT をオープンしてノーマライズ、DUT に測定対象を接続してリターンロスを読みます。

ダミーロードたち

SMA コネクタの小電力ダミーロードたちです

ちょっとだけ長いやつ (耐電力 2Wのもの)

短いやつ 1W か 0.5W

もうひとつ短いやつ

ダミーロードが悪いのかリターンロスブリッジが悪いのかよくわかりませんが、そこそこまでしか測れなそうです。実用上はまぁまぁ使える感じでしょうか…

アマチュア無線用の M コネクタ定格15Wダミーロードです

第一電波工業 ダイヤモンド ダミーロード DL50A - ダイヤモンドアンテナ

ダイヤモンドアンテナ

4.0 / 5.0

DC-1GHz まで使える (1.15以下 (DC-800MHz) 1.20以下 (800-1000MHz) というスペックですが、1.15=23.13dB / 1.20=20.83dB なのでスペック通りの測定はできてない感じです。

ハンディ機用ホイップアンテナ

144MHz/430MHz 帯用のホイップアンテナです。1/4λなので人体アースしながら測っています。アースしないと全然違う帯域に同調していました。

モービル用マルチバンドホイップ

ベランダに設置してあるホイップです。最近調整してませんが… 2014年の10月あたりの記録はこれです 500 Can't connect to lowreal.net:443 (certificate verify failed)

なぜかちょっとずつズレているようにみえます。

ちなみに DSA815 には VSWR モードがあって、実はリターンロスからVSWR換算を自動でやってくれます。これを使って 21MHz 帯を見てみました。

7MHz も見てみました。

アンテナアナライザーでも測ってみました。

アンテナアナライザーとTG付きのスペクトラムアナライザー

リターンロスブリッジを使えばTG付きのスペクトラムアナライザーはスカラー型のネットワークアナライザと似た機能を持つようになります。しかし位相は測れないので決してベクター型ネットワークアナライザの代わりはできません。

アンテナアナライザーはベクター型ネットワークアナライザのアンテナ特化版です。(ベクター型ではないアンテナアナライザーもありますが…) なので R + jX を分けて表示することができ、

  • アンテナが共振しているのに抵抗成分のミスマッチでVSWRが高い (トランスをつかえば解決)
  • アンテナが共振していなくてVSWRが高い (アンテナ自体の調整が必要)

という原因をわけて解析することができます。


50MHz 帯まではアンテナアナライザーがあるのでスペアナでリターンロスを測る機会はまずなさそうです。しかしそれ以上高い周波数ではスペアナ+リターンロスブリッジが活躍できそうです。

  1. トップ
  2. tech
  3. スペアナとリターンロスブリッジを使ってSWRを測ってみる

やりたいことに対して時間が足りなすぎる。

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 なのは本当なのか」という不安を解消するのに数式が役立ってくれるように感じる。

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 で紹介されている回路を一通り自分の中で整理してまとめました。詳しい動作は今まで書いた各エントリにして、ここではそれぞれの特徴を書いてみます。

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

ダイオードディテクタ

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

抵抗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. アンテナアナライザーの回路 ー まとめ

複素インピーダンスの場合、実数部は抵抗成分・虚数部はリアクタンス成分とわかれているので、イメージしやすいですが、電圧と電流の虚数部とは何なのでしょうか? と疑問に思ったので考えた結果をメモしておきます。

位相情報も含めた電圧・電流

実際のところ、位相も含めた電圧と電流は実数体で表現できます。つまり時間 、角周波数 、初期位相α、電圧振幅 E としたとき、時刻 t のときの電圧 v を表現するには

となります。この式は位相情報も完全に含んでいます。

ということで、位相を扱うには複素数が必須というわけではないわけで、なぜ複素数が必要なのかという気持ちになります。

しかし実数体で位相情報を含めて表現すると、上記のように三角関数を使うことになり、実際の計算はとても面倒になります。そこで、計算を便利にするために複素数の概念を入れます。

このとき使うのがオイラーの公式で、この場合、 三角関数が面倒なので指数関数にしてしまおう、そのためには電圧・電流表現を複素数体に拡大しよう、という感じのようです。

指数関数にするためにはこのような形式にする必要があるので、

と、電圧波形の式を複素形式にして (単に複素数部を付け加えているだけです。波形を表現するだけなら cos/sin はどっちがどっちでも良いので、オイラーの公式の形にあわせているだけです)

と指数関数に変換します。この形式で計算することで、オームの法則を使った普通の計算ができるようになって計算が楽になります。

例えばここでインピーダンスを考えると

e についている指数の割り算は指数同士の引き算になるので

指数の中を整理する

時間変数が消えてしまい、電圧と電流それぞれの初期位相 の位相差によって決まる定数がかかっている状態になります。この定数をまたオイラーの公式で戻してみると

この Z はインピーダンスなので、実数部は抵抗成分、虚数部はリアクタンス成分となっています。

はすなわち位相差なので、電圧と電流の位相差の cos() と sin() が単純な E と I との比にかかって複素インピーダンスを構成していることになります。

で、複素電圧と複素電流の虚数部は何なの?

複素電圧と複素電流の虚数部は何なのかというと「なんでもない」が答えのようです (単体では初期位相と関係しますが)。というのも、電圧にしろ電流にしろ負荷との関係をもって「電圧と電流の位相差」が現われるので、負荷との関係を考えない状態での、単体の複素電圧・複素電流の虚数部は何の意味もないということです。

インピーダンスは定義からして「電圧と電流の比」という関係の表現ですから、この関係の中に位相差が表現されるのは自然なことです。

  1. トップ
  2. tech
  3. 複素電圧・複素電流とはなんなのか

オイラーの公式とは一生無縁だと思っていた

げんきの絵本 おかあさんといっしょ かぞえてんぐ はって はがせる シールえほん - 講談社

講談社

3.0 / 5.0

横山だいすけおにいさんは「かぞえてんぐ」をやってるときが一番キてる(キてるとしか言いようがない)と思うので、一番かぞえてんぐが面白い。

「かぞえてんぐ」は数を数えたくて数えたくて辛抱たまらん!というキャラなのだけど、数えおわったあと絶頂とともにいきりたったところから「何か」が出てくる。

つまり数フェチで、周囲を巻き込んで数を数えるというオナニーをしたうえ絶頂するという完全なる変態である。NHK で放送されていいものなのか不思議なぐらいの変態なんだけど、実績からすると合法っぽいので、汚れちまった人間にだけ変態に見えるということなのかもしれない。

このへんのエントリの続きです

2014年に作ったSWR計でしたが、先月あたりセンサー部分の作りなおしをしてみて、前よりもよさそうだという感触を得られたので、一旦常用できるように仕上げることにしました。というのも、デスク上にバラックで積んであるブレッドボードと液晶がさすがに邪魔だからです……

PCB Milling で基板作成

今回 PCB-GCode という Eagle のプラグイン (ULP) を使ってみました。前に PCB Milling したときは謎の GCode 生成 ULP を使いましたが、こちらのほうが良くできていそうです。

こんな感じの基板を作って

PCB-GCode はこんな感じで

こんな感じの GCode をつくって

GrblServer で切削させて、実装しました。0.8T の基板なので配線が透けています。

片面切削だけにしたかったので、できるだけ Via をつかわず配線しています。そのため、DIP のピンとピンとの間を通すラインがあり、これがうまくいくか不安でしたが今回はうまくいきました。これぐらいなら 0.1mm 単位ぐらいの雑な調整でもなんとかなるようです。

CNC 切削で基板を作る場合、この程度の規模だと時間的にはユニバーサル基板で雑に実装するのとそれほど変わりません。しかし配線を Eagle 上でやって ERC にかけているのをそのまま切削しているので「配線ミス」というのが起きず、安心して実装できます。ユニバーサル基板での実装は結構気を使って疲れるので、ちょっと面倒でも切削でつくるのが気は楽です (ケースバイケースですが)。

インターフェイス

前に作ったものの中身をそっくり入れかえただけで、液晶も昔のものを再利用しています。バラック状態のときと違うタイプの液晶なので、ライブラリのAPIを適当にあわせたりして対応させました。

本当はせっかくなのでもっと格好いいケースに入れたいのですが、ひとまずこのような形におさめました。

ほかにも、高SWR時にブザーを鳴らす機能だとか、送信中にオンになるオープンドレイン出力だとか、シリアルに常時SWRを出力する機能なども実装してあるのですが、使ってません。

  1. トップ
  2. tech
  3. 自作SWR 計を一旦仕上げ

そういえば KX3 の源発振はDDSではなくて Si570 とかいうプログラマブルオシレータだよな、ということを思い出し、どうやって90度違いのI/Qを作ってるのが気になりました。

回路図を見ると以下らへんです。左側からきているのが Si570 からのクロックです。

NC7SB3257 はマルチプレクサ、74VHC4040 はカウンタで、ここはバイパス可能な1/8分周器なのでI/Qには関係ありません。

次に出てくる 74LVC74 は Dフリップフロップで、ここでI/Qのクロックを作っているようです。CLKc CLKs がそれぞれ In-phase と Quadrature のようです。

LTSpice でシミュレーションしてみる

LTSpice に入ってるデジタル素子でシミュレーションしてみました。この素子は理想素子なので、そのまま使うとシミュレーションできませんでした。適当に伝送路に遅延を入れるとなんかそれっぽい波形が出てきました。

4クロックで1つのI/Qクロックに変換される様子がわかります。

源発振の分周比を思い出す

KX3 で無線局免許を更新するとき、送信機系統図に源発振と出力周波数の関係を書いたことを思い出しました。これは電波法の規定で書かなければらないのですが、あまり深く考えていませんでした。以下の表です。

Dフリップフロップを使ったI/Qクロックは上記の通り4分周に相当するので、ここで書いてある表も殆どのケースで 1/4 の分周率になっているのでしょう。

1.8/1.9MHz だと4倍すると7.6MHzぐらいですが、Si570 が 10MHz〜 の発振器なのでさらに分周している、という話のようです。マルチプレクサとカウンタの分周は1.8/1.9MHz用というわけのようです。

DフリップフロップによるI/Qクロック生成のメリット/デメリット

メリット

  • 実質デジタル処理なので広い帯域で正確に90度位相差を得られる
  • クロック発信源が1つだけで良い

デメリット

  • 欲しい周波数の4倍の源発振器が必要
  • 矩形波出力 (デメリットかどうかは場合による)

200MHz ぐらいまでの発振器は安いのがいくらでもあるのですが、ここを超えると急に高価になる気がするので、50MHz で使うかどうか、DDS2台にするかどうか大きく判断が別れそうです。とはいえ、基本的にはDDS2台よりも安価で省電力そうです。

  1. トップ
  2. tech
  3. Dフリップフロップによる I/Q クロック生成

京都は住むのに心地良いところだったなあと思う。長く住んだらそうではないのかもしれないが、圧倒的に神社が充実していたし、気が滅入ったときに明確に休息のポイントがあった。

自分はどこにいても「余所者」扱いされていると感じるので、観光客という余所者が多いところはかえって孤独を感じず、心地が良く感じる気がする。鎌倉とかも良かった。東京も絶対数としては観光客は多いと思うが、圧倒的にクソみたいに馴染んでいる人間が多いのでクソが支配的でクソだと思う。

特に関東の中でも渋谷という土地は知っている中では最悪中の最悪で、どうしようもない。品川とか大崎とか、あるいは悪くとも新宿も比較的綺麗で落ちついている面もあるが、渋谷はどんなに新しいビルでもタバコ臭く、清潔感がない。どこを歩いてもドブの臭いがする。どこにいっても汚ならしいおっさんと汚ならしい若者が同時に存在しており混沌としている。谷底なせいで悪い空気が漂っているとしか思えない。

「コイルとコンデンサは電圧と電流の位相差を90度進めさせる/遅れさせる」という説明を良く見ますが、どうも直感的に理解できていませんでした。電圧と電流の位相差が±90度か0度しかとらないという話ではないだろうし、「途中の位相はないの?」と思ってしまうのです。この説明の意味がわからない、という意味です。

疑問の詳細

コイルとコンデンサの組合せで共振回路をつくった場合、電圧と電流の位相差はゼロになるはずです。ではすこしだけ共振していない場合はどうなるのでしょうか? 現実的には殆どの場合共振していないはずです。

「すこしだけ共振していない状態」であっても回路全体としてはインダクティブであるかキャパシティブであるかのどちらかであり、±90度の位相差は起こっているはずです。

でも現実問題としては回路全体で観測できる電圧と電流の位相差は必ずしも±90度ではありません。少しだけ共振していない場合は殆ど位相はずれていません。

途中の位相はどこいった?

式を使って「このように位相がずれます!!」というのは置いといて「途中の位相はどこいった?」という疑問だけ解決します。


純リアクタンス成分に関していえば、確かに±90度の位相差を常に起こしています。これはコイルとコンデンサだけで構成された回路なら回路全体に対してもあてはまります。「少しでも」コイルやコンデンサがあれば必ず±90度の位相差が起こっています。コイルとコンデンサの複合回路でも、共振していなければ必ず±90度の位相差が起きます。これはシミュレーションでも確認できます。

しかし実際の観測される位相は抵抗成分も含めて考える必要があります。これにより回路全体を見たときの位相差は任意の角度をとります。

全体として、抵抗成分が少なければ少ないほど-90度か+90度に近付き、リアクタンス成分が少なければ少ないほど、0度に近付いていきます。

複素平面上で見たときも、純リアクタンス成分は全体としても±90度にしかならないが、抵抗が加わった瞬間、合成された絶対値はいろんな別の角度をとりうることがわかります。

つまり

「コイルとコンデンサは電圧と電流の位相差を90度進めさせる/遅れさせる」というような説明は、純粋にそのコンポーネントの理想的な電圧の電流の関係をいっていて、抵抗成分を含めたことは言ってないわけでした。この説明、何度も何度も目にしてきたのに、何を言ってるのかわかりませんでしたが (途中の位相もあるよな?と思っていた)、ようやく意味がわかった気がします。

そして思いますが、この説明の仕方は筋が悪いと思います。現実のコイルやコンデンサには必ず無視できないほどの抵抗成分がありますから、これらのコンポーネントだけで回路を構成したとしても必ずしも位相差は±90度のどちらかになるというわけではないはずです。コイルやコンデンサと言うのではなくて「純リアクタンス成分は〜」とかで書いたほうが正確だと思いました。

  1. トップ
  2. tech
  3. 「コイルとコンデンサは電圧と電流の位相差を90度進めさせる/遅れさせる」とはどういう意味なのか

AーDコンバータ活用成功のかぎ―変換のメカニズムと性能の引き出し方 (アナログ・デザイン・シリーズ) - 松井 邦彦

松井 邦彦

5.0 / 5.0

これを読みました。ほぼデジタル回路しか触らないぞと決めていたとしても避けて通れないのはADCです。

ΔΣ型や逐次比較型の説明ももちろんですが、他の構成(全く知らなかった)のADCについても解説がありました。

一番面白いというか役に立ちそうなのは精度に関するところで、何が支配的になって精度に関わってくるか、補正しにくい誤差はデータシートのどこの項目なのかが詳しく書いてあります。こういうノウハウはなかなか知る機会がないのでわくわくしました。

「何が支配的で何に影響を与えるか」は何を考えるときにも大事なところで、「コツ」の言語化だと思うので、こういうことがひたすら書かれた書籍を読みたいところです。

ちょっと針が動いて楽しいアナログ計が欲しいなと思っても、昨今ではラジケータ(ラジオ用の精度の低い電流計の総称)もかなり高価で、秋葉原だと安くても500円〜という感じです。この値段だと、インターフェイスの味つけ程度のために買おうとは思いません。

ふと思いたって ebay で analog panel meter で検索してみると、100円程度で売られているものがありました。仕様的には AC 0-300V と、かなり高圧のフルスケールのものです。とはいえ、どうせ抵抗が入ってるだけなので、ちょっと改造すれば使えそうだと思い買ってみました。

仕様

見ての通りパネル全面にダイオードと抵抗がついています。簡単にはずせそうで便利ですね。このダイオードと抵抗は無視して、電流計本体のフルスケールと内部抵抗を測りました。

フルスケールはだいたい1500uA(1.5mA)ぐらいのようです。このとき、電圧は 620mV でしたので、内部抵抗は約413Ωです。


あまり格好いいメータとはいえませんが、スケールを貼り替えてカバーを塗装すれば多少マシになるかもしれません。ただ針の振れかたも安っぽく、ヒゲゼンマイのトルクがいまいちという感じがします。

とはいえ、ちょっとしたケースでデジタルPWMに繋いでアナログ表示させてみるみたいなケースでは使えそうです。3.3V なら 1.8kΩ、5V なら 2.9kΩ を直列に繋げばちょうどよさそうです。

  1. トップ
  2. tech
  3. 100円ぐらいで売られている中華ラジケータ(アナログパネルメータ)を試す

先日

最初は 3.3V で動かしていたのですが、どうしても途中から出力電圧が上がりませんでした。定格上では 3.3V でも +10dBm までは入力可能のはずなのですが、-2dBm ぐらいから出力が上がらなくなり、全くよくわかりませんでした。

http://lowreal.net/2016/02/22/1

と書きました。これの原因のちゃんと調べてみました。

まずAD8307 のデータシートには以下のような記述があります。

In most applications, the signal is single sided and can be applied to either Pin 1 or Pin 8, with the other pin ac-coupled to ground. Under these conditions, the largest input signal that can be handled by the AD8307 is 10 dBm (sine amplitude of ±1 V) when operating from a 3 V supply; 16 dBm can be handled using a 5 V supply. The full 16 dBm can be achieved for supplies down to 2.7 V, using a fully balanced drive.

要約すると、

  • シングルエンドアプリケーション時 (入力の片方のピンがAD8307のGNDに接続されている場合) は 3V のとき 10dBm までの入力が可能。
  • 差動接続の場合は2.7Vでも16dBmまでの入力が可能

と書いてあります。

これを見て 3V でも +10dBm まで使えそうだな、と思ってしまいました。

出力が頭うちに

しかし実際 3.3V で使ってみると、10dBm 入力しても想定した出力がでません。よくよく調べてみると、英語版の最新データシートだと以下のような記述がありました。

Note that while the AD8307 can operate down to supply voltages of 2.7 V, the output voltage limit is reduced when the supply drops below 4 V. This characteristic is the result of necessary headroom requirements, approximately two VBE drops, in the design of the output stage.

要約すると 出力回路に2つのトランジスタがあるので、4V未満ではこれらの 分出力が低下するよ、という感じのようです。出力回路の制限なわけですね。

が 0.7V とすれば2つで1.4V、電源電圧が3.3Vなら、出力電圧は1.9Vまで低減されます。これを入力 dBm に換算すると-8dBm付近になります (実際の によります)。

が -84 dBm、 が 25mV/dB で が 1.9Vだと -8dBm になります。

ということで、実測だと 3.3V 時に出力が頭うちになるのは完全に「仕様」なのでした。

結論

つまり、3.3V で使う場合で、-8dBm 以上入力させたいなら、傾きの調整が必須なのです。

傾きを 20mV/dB にすれば、 1.9V で +11dBm になります。20mV/dB に設定する方法はデータシートにそのまま載っていて、32.4kΩの抵抗と50kΩの可変抵抗を直列にして AD9807 の OUT と COM に接続 (内部の出力抵抗と並列に接続) して調整すれば良いようです。

といっても調整するのが面倒なんですが…

  1. トップ
  2. tech
  3. AD8307 を 3.3V で動かすときの罠

はぁほんと心底 Spring とか嫌だ…… なんでこんなクソなことをしないといけないのか。普通に書きたい……

中華AD8307をいくつか手に入れてみたので、ちゃんんと使えるのか実験してみました。というのも、値段的にどう考えてもコピー品だからです (単価50円ぐらい)

回路とボードレイアウト

回路はAD8307のデータシートに記載がある以下の「基本的な接続」の回路ほぼそのままです。電源のデカップリング用の 4.7Ω はフェライトビーズに変え、入力抵抗 52.3Ωは100 // 110Ωで作っています (が、手元に110Ω抵抗がなかったため100 // 220 // 220 Ω)

ボードレイアウトは以下のようにしました。PCB Milling で作るため必ずしも理想的とはいえません。

測定

手元にある信号発生器だと、スペアナのトラッキングジェネレータ出力が一番信用できるので、これを使いました。ただし出力が-20dBm〜0dBmまでを1dB単位でしか出せないので、出力がもうすこし大きくなって飽和近くになったときどうなるかはわかりません。周波数は10MHz固定です。

ということでこのようになりました。確かにログアンプになっているようで、綺麗に dB に対して直線になっています。

傾きは 24mV/dB (= (2230-1750)/20 ), インターセプトは -92.9dBm ぐらいにあります。

AD8307 本来の仕様的にはインターセプトは -87〜-77dBm なのですが、これはずれています。原因はよくわかりません。入力インピーダンスが正確に50Ωになっていない(アンテナアナライザーで測ると約52Ω)影響かもしれません。

追記

500MHz まで段階的にはかりました。

広い範囲にしてみてみると、傾き 25.5mV/dB、インターセプト-87dBm ぐらいに見えます (10MHz時)。こんなもんなのかもしれません。

まとめ

ひとまずログアンプとしては動いているようなので使えそうです。インターセプトのずれは実装の問題なのかICの問題なのかはよくわかりませんのでとりあえず保留としようと思います。自分の場合出力を必ずADCに接続するので、ここが多少ずれていても大丈夫ではあります。

余談

表面実装品のテストにPCB Millingをはじめて使ってみました。PCB Millingとしては、こういう使いかたをするのが一番の目的だったので、ひとまずうまく実験できて良かったです。SOIC は割と足の間隔が広いので、あまり細かいことができないPCB Millingでも十分いけることがわかりました。

  1. トップ
  2. tech
  3. 中華AD8307を使ってみる

25dB で SMA 入出力のアッテネータが欲しくなったので作ってみました。アッテネータを作ってみるのは初めてです。

回路

アッテネータの計算機 を使って必要な抵抗値を求め、抵抗計算のサイトでどうやって近い値を作るかを調べ、このようにπ型のアッテネータ回路にしました。

ボードレイアウト

小さくつくりたかったので全部縦に並ぶようにしてみましたが、入出力が近くなるので、こう実装するのはあんまり良くなさそうな気がします。

結果

挿入損失

300MHz ぐらいまではそこそこフラットにみえます。

リターンロス

300MHz ぐらいまでなら SWR=1.2 未満になりそうです。

  1. トップ
  2. tech
  3. 高周波用アッテネータを作ってみる

中華AD8307のテストをしてみましたが、これはうまくいけばモジュールとして使えるようにピンヘッダを立てて作りました。

テストした感じでは使えそうなので、まずパワー計として動かしてみることにしました。

といっても、MCUのADCで読んで計算するだけです。

ただ、AD8307 そのままだと入力範囲が -76dBm〜+16dBm と、普段使うには電力範囲が小さいほうに寄りすぎているため、25dB のアッテネータを前段に挿入し、-51dBm〜+41dBm の範囲としました。

耐電力の大きなアッテネータは面倒なので、1/2W 抵抗を使い、定格1W程度、極めて短時間なら10W程度というイメージです。

使用感

実際10W入力すると3秒ぐらいでかなり発熱するのでこわいです。5W ぐらいまでなら〜5秒耐えられそうです。

確度

アッテネータの絶対的な誤差は簡単な校正で消せます (インターセプトが移動してるだけなので) 。AD8307 自体のログとの一致性は±1dB。

ただ、入力周波数によって出力電圧が結構変わりますので、確度を求めるなら周波数カウンタ機能をつけて、周波数も変数にして校正したほうが良さそうです。

例えば10MHzと500MHzだと、出力電圧にほぼ固定で10dB分の差があります (1ケタ!!)。一応、この差は周波数に応じてほぼ固定なので、入力周波数がわかっていれば簡単に補正はできます。

↓ はデータシート記載のものと、実測のもの


今回は周波数を測ってない以上、全域での絶対的な確度はあまり期待できません。

計測できた電力値が実際より大きい分にはあまり問題ではありませんが、実際よりも小さい値が表示されると、これを信じて他の機器につないだときに過大入力になることがあり、よくありません。安全策としては上限周波数で校正をかけることでしょう。

ただし、前段についているアッテネータの特性的に300MHzぐらいが上限です

用途

明確な出力が不明な信号源の場合、直接スペアナに繋ぐまえに、一旦チェックする用として使いたい気持ちです。瞬間的になら10W入力できますし、これなら壊れても痛くありません。

コード

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "interval.hpp"

static const float SLOPE = 26.367;
static const float INTERCEPT = -63.51879243;


LiquidCrystal_I2C lcd(0x27, 16, 2);
String formatWatts(const float watts) {
	if (watts < 1e-3) {
		return String(watts * 1e6) + "uW";
	} else
	if (watts < 1e-1) {
		return String(watts * 1e3) + "mW";
	} else {
		return String(watts) + "W ";
	}
}

void setup() {
	Serial.begin(115200);
	Serial.println("init...");

	Wire.begin();

	lcd.begin();
	lcd.backlight();
	lcd.setCursor(0, 0);
	lcd.print("Hello, World");
	lcd.setCursor(0, 1);
	lcd.print("TEST");
}

void loop() {
//	interval<1000>::run([]{
//		Serial.println("1000ms");
//	});

	uint16_t adc_raw = analogRead(0);
	Serial.print("ADC Got = "); Serial.println(adc_raw);
	float adc = static_cast<float>(adc_raw) / 1024 * 5;

	Serial.print("ADC Voltage = "); Serial.println(adc * 1000);

	float dBm = (adc * 1000 / SLOPE) + INTERCEPT;
	Serial.print("dBm = "); Serial.println(round(dBm));

	float watts = pow(10, dBm / 10) / 1000;
	Serial.print("W = "); Serial.println(watts);
	Serial.print("mW = "); Serial.println(watts * 1000);

	lcd.setCursor(0, 1);
	lcd.print(round(dBm));
	lcd.print("dBm");
	lcd.print("                ");

	lcd.setCursor(0, 0);
	lcd.print(formatWatts(watts));
	lcd.print("                ");

	delay(500);
}
  1. トップ
  2. tech
  3. 中華AD8307をデジタル電力計にしてみる

ほんとにイライラすることばかりが起きる。なんでこんなめにあうのか。本当の意味がわからない。

いくら自分から面白いことを探そうとしても、ひたすらに不幸が追いかけてくる。嫌なことは自動的に毎日起き続けるのに、面白いことは追いかけても逃げていく。


とにかくこの毎日嫌なことばかりが起きるのをなんとかしたい。

自分の中からはただただやりたいことが沸いてくる。大半の嫌なことは他人に起因していて、

  • 嫌なことを言われる
  • 嫌なことを言われると予期される
  • 嫌なことをやらされる

となる。しかし他人に起因することは自分にどうすることもできない。無力。原因が解決しないので、運用でカバーとするしかないが、運用力がない。

もっと果てしないスルー力があれば解決するかもしれない。どのようにしてそれを手に入れればいいかはわからない。他人の重要性をもっともっと下げていきたい。お前らとかどうでもいいと思えるようになりたい。他人の評価を全て無視したい。

とにかくなんとかしてストレス解消したい。最近とことん些細なことでイライラする。

精神的余裕がないのに、追い討ちをかけるような事態しか起きない。ひどいめにあうということしかない。インターネットのほうがまだ安全ではないか。

自分は自分のルールで生きており、つまりこのルールは道徳ないし宗教なので、他人にどうこう言われるようなものではない。ただ生きてるわけでもなく、自分のルールに従って生きている限り、それをどうこう言われる筋合いは全くない。

事情を知らない人間はクソなことを言ってくる。お前の事情なんてこちらとしても存じあげない。コミュニケーションをしないやつに、コミュニケーション能力が低いと罵られる意味はなんだ。

切削を2回ぐらい失敗したあと、そこそこ良さそうなのができたので、実装してみました (まだ途中ですが)。右側でブリッジしているような部分がありますがこれは設計上の意図的なもので、右側はほぼ完璧です。

マクロで撮るとスケール感がわかりにくいので右側に SOIC のパッケージのものも入れています。ほぼ同じサイズで約2倍のピンが並びます。

残念ながらプレッシャーフットなどがないのでワークのZ軸に傾きがあり、これがどうしても消せませんでした。左側は低くて、右側は高い (といっても0.1mm〜0.2mm程度の傾き) という状態です。ほとんど基板に触れない状態から切削を開始して、ダメそうなら 0.02mm ずつZを下げていきました。これ以上下げるとTSSOPの部分のパッドが消滅しそうなのでやめました。

左側は手作業でショート部分を削ったのでだいぶ汚ないです。

一応 TSSOP も実装できそうです。しかし、このサイズ (30mmx23mm程度) でも傾きがこれほど問題になるので、もっと大きな基板では現状のセッティングではまず無理そうです。プレッシャーフットを自作するか、あるいは基板を固定しているジュラコンを精密に水平出しをすればいけるのかあるいは設定を詰めればいけるのか、よくわかりません。プレッシャーフットも万能ではないのでなんともいえなそうです。


やはり気楽にやれる範囲は SOIC ぐらいだと思います。実装の点でも SOIC まではルーペなしで実装可能ですが、TSSOP ぐらいからルーペ確認が必須になってきます。

主要ピン幅

  • DIP : 2.54mm
  • SOIC: 1.27mm
  • TSSOP: 0.65mm
  • MSOP: 0.5mm

先端 0.1mm、60度のVカッターだと0.1mm の深さで幅 0.215mm。

ソルダーマスク

このように PCB Milling で普通に作るとソルダーマスクがないので、ハンダブリッジをとても起こしやすい状態になります。

いくつか作って実装してみてわかりましたが、表面実装品ではソルダーマスクがなくても案外ブリッジしません。一方でリード品をハンダづけすると高確率でブリッジします。

これはおそらく使用するハンダの量の違いだと思います。また、リード品だとリードが邪魔で正確にコテ先をあてにくいのも一因としてありそうです。

TSSOPでもパッドがしっかり成形できていれば、ハンダ付け自体にはそれほど困難に感じません。ただしフラックスは必須です。

「リード部品のほうがハンダ付けしやすい」という刷り込みを持っていたので、意外な発見でした。

  1. トップ
  2. tech
  3. PCB Milling で TSSOP

/**
zun-doko-kiyoshi in ARM Linux EABI
 */

.section .text
.global _start

.macro sys_write
        mov r7, $0x04
        svc $0x00
.endm

.macro rand_init
        /* using all high resiters for rand: r8-r12 */
        /* set seed from time */
        ldr r0, =time
        /* sys_time */
        mov r7, $0x0d
        svc $0x00
        ldr r0, =time
        ldr r8, [r0]
        /* load constant for rand */
        ldr r9, =1103515245
        ldr r10, =12345
        ldr r11, =2147483647
.endm

.macro rand
        /* random update r8 */
        mov r12, r8
        mla r8, r12, r9, r10
        and r8, r8, r11
.endm


_start:
        rand_init
        /* r6 is current zun count */
        mov r6, $0

loop:
        rand
        /* check bit / eq = zun, ne = doko */
        tst r8, $0x80
        adreq r1, zun
        moveq r2, #zun_len
        addeq r6, $1
        adrne r1, doko
        movne r2, #doko_len
        mov r0, $0x01
        sys_write
        bne check_kiyoshi
        b loop

check_kiyoshi:
        /* now this is doko state and check zun count */
        cmp r6, $5
        /* zun count is greater than 5 */
        bge call_kiyoshi
        /* failed to call kiyoshi and reset state */
        mov r6, $0
        b loop

call_kiyoshi:
        /* now this is kiyoshi state */
        adr r1, kiyoshi
        mov r2, #kiyoshi_len
        mov r0, $0x01
        sys_write
        mov r0, $0x00
        /* sys_exit */
        mov r7, $0x01
        svc $0x00

zun:
        .string "ズン\n"
zun_len = . - zun
        .align 2

doko:
        .string "ドコ\n"
doko_len = . - doko
        .align 2

kiyoshi:
        .string "キヨシ\n"
kiyoshi_len = . - kiyoshi
        .align 2


.section .data
time: .word 0

cross compile

 arm-linux-gnueabi-as ./sketch.s -o sketch.o && arm-linux-gnueabi-ld -o sketch -e _start sketch.o && qemu-arm-static ./sketch
  1. トップ
  2. tech
  3. arm-linux-eabi でのアセンブリ ズンドコ

だいたい300円ぐらいのものです。MAX7219 というLEDドライバを使っていて、SPI で表示を変えられます。(正確には 7219 は SPI 対応とは書いてないのですが、CS の扱いが違うだけ? なのか、ほぼSPIと同じインターフェイスです。よくわかりません)

SPI を使ったことがなかったので一応自分で書いてみました。BCD のデコーダが入っており、数字ぐらいの表示なら自分でLEDとのマッピングを持つ必要はありません。

モードがいくつかあって

  • 全桁自分で制御 (7セグメント+ドットに対応するビットを自分で入れる)
  • 最下位桁だけBCDで残りは自分で制御
  • 上位4桁は自分で制御して、下位4桁はBCD
  • 全桁BCD

と選べます。7セグでアルファベット表示したい、みたいな場合は全桁自分でやる必要があります (マッピングすなわちフォント情報を持つ)

コード

書いたコードでは、全桁BCDでやるようにしてみました。マッピング持つのが面倒なのと、実質自分が使おうと思う用途だと数字以外表示しなそうだな、という気がしています (7セグでアルファベット表示させるのは視認性が悪いので好きじゃない)

SPI 通信はビット数のキリがいいのでハードウェアを使ってやっています。MAX7219 は 10MHz の SPI らしいのでそのようにしてみました。チップセレクトだけコンストラクタに渡すようにしています。

#include <Arduino.h>
#include <SPI.h>

#include <string.h>
class MAX7219 {
	uint8_t CS;

public:
	enum class ADDRESS : uint8_t {
		NOOP = 0b0000,
		DIGIT0 = 1,
		DIGIT1 = 2,
		DIGIT2 = 3,
		DIGIT3 = 4,
		DIGIT4 = 5,
		DIGIT5 = 6,
		DIGIT6 = 7,
		DIGIT7 = 8,
		DECODE_MODE = 0b1001,
		INTENSITY = 0b1010,
		SCAN_LIMIT = 0b1011,
		SHUTDOWN = 0b1100,
		DISPLAY_TEST = 0b1111,
	};

	enum class SHUTDOWN_MODE : uint8_t {
		SHUTDOWN = 0b0,
		NORMAL = 0b1,
	};

	enum class DECODE_MODE : uint8_t {
		NO_DECODE_FOR_DIGITS_7_0 = 0b00000000,
		CODE_B_DECODE_FOR_DIGIT_0_NO_DECODE_FOR_DIGITS_7_1 = 0b00000001,
		CODE_B_DECODE_FOR_DIGIT_3_0_NO_DECODE_FOR_DIGITS_7_4 = 0b00001111,
		CODE_B_DECODE_FOR_DIGIT_7_0 = 0b11111111,
	};

	MAX7219(uint8_t _cs) :
		CS(_cs)
	{
		pinMode(CS, OUTPUT);
	}

	void write(ADDRESS address, uint8_t data) {
		SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
		digitalWrite(CS, LOW);
		SPI.transfer(static_cast<uint8_t>(address));
		SPI.transfer(data);
		digitalWrite(CS, HIGH);
		SPI.endTransaction();
	}
	void begin() {
		SPI.begin();

		setDecodeMode(DECODE_MODE::CODE_B_DECODE_FOR_DIGIT_7_0);
		setScanLimit(7);
		setShutdown(false);

		setIntensity(8);

		for (int i = 0; i < 8; i++) {
			write(static_cast<ADDRESS>(i + 1), 1);
		}
	}

	void setDecodeMode(DECODE_MODE mode) {
		write(ADDRESS::DECODE_MODE, static_cast<uint8_t>(mode));
	}

	void setScanLimit(uint8_t limit) {
		write(ADDRESS::SCAN_LIMIT, limit);
	}

	void setIntensity(uint8_t intensity) {
		write(ADDRESS::INTENSITY, intensity);
	}

	void setShutdown(bool shutdown) {
		write(ADDRESS::SHUTDOWN, static_cast<uint8_t>(shutdown ? SHUTDOWN_MODE::SHUTDOWN : SHUTDOWN_MODE::NORMAL));
	}

	void print(const char* buf) {
		size_t len = strlen(buf);
		uint8_t digit = 0, dp = 0;
		for (size_t i = 0; i < len && digit < 8; i++) {
			const char c = buf[len - i - 1];
			if (c == '.') {
				dp = 1<<7;
				continue;
			} 

			uint8_t b;
			if (c == '-') {
				b = 0b1010;
			} else
			if (c == ' ') {
				b = 0b1111;
			} else
			if ('0' <= c && c <= '9') {
				b = static_cast<uint8_t>(c - '0');
			} else {
				continue;
			}

			write(static_cast<ADDRESS>(digit + 1), b | dp);
			dp = 0;
			digit++;
		}

		for (; digit < 8; digit++) {
			write(static_cast<ADDRESS>(digit + 1), 0b1111);
		}
	}
};


MAX7219 leds(10);

void setup() {
	leds.begin();
	leds.print("-1234.567");
	delay(3000);
}

void loop() {
	leds.print(String((float)micros() / 1000).c_str());
	delay(29);
}
  1. トップ
  2. tech
  3. MAX7219 8桁 7セグメント LED モジュール / Arduino

例によって ebay で300円ぐらいものです。絶対的な解像度はともかく TFT カラー液晶がこの値段だと 16x2 の LCD とかが情報量的にはゴミに思えてきます。(ライブラリサイズとかの兼ね合いもあってそのまま置き換えられるわけではないですが)

購入したものは ST7735 を使っているので、Adafruit-ST7735-Library でだいたい動く雰囲気なのです。以下の2つのライブラリを使える状態にしておく必要があります。

しかし、このモジュールが想定している仕様とは異なる仕様のモジュールのようで、微調整が必要でした。ただし Adafruit-ST7735-Library はクラス構造を private にしているので、残念ながらライブラリ側を無修正のままではどうしようもありませんでした。

最低限の修正に留めるようと、以下のように private を protected にしました。

diff --git a/Adafruit_ST7735.h b/Adafruit_ST7735.h
index 0598720..3b1aa97 100755
--- a/Adafruit_ST7735.h
+++ b/Adafruit_ST7735.h
@@ -152,7 +152,7 @@ class Adafruit_ST7735 : public Adafruit_GFX {
   void     dummyclock(void);
   */
 
- private:
+ protected:
   uint8_t  tabcolor;
 
   void     spiwrite(uint8_t),

実際に使う前に public 継承して初期化処理を奪っています。実際のコードでは冒頭の gif のように millis() を連続して表示させています。

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h> /* must modify private to protected */
#include <SPI.h>

class TFTST7735 : public Adafruit_ST7735 {
public:
	TFTST7735(int8_t CS, int8_t RS, int8_t RST = -1) :
		Adafruit_ST7735(CS, RS, RST)
	{
	}

	void init() {
		initR(-1);

		_height = 128;
		rowstart = 32;
		colstart = 0;
	}
};

#define TFT_CS     10
#define TFT_RST    9
#define TFT_A0     8

TFTST7735 tft = TFTST7735(TFT_CS, TFT_A0, TFT_RST);

void setup (void) {
	tft.init();
	tft.fillScreen(ST7735_BLACK);
}

void loop() {
	tft.setTextWrap(false);

	// font size is 5x7
	tft.setCursor(5, 5);
	tft.setTextColor(ST7735_RED);
	tft.setTextSize(1);
	tft.fillRect(5, 5, 128, 7, ST7735_BLACK);
	tft.println(millis());

	tft.setCursor(5, 20);
	tft.setTextColor(ST7735_WHITE);
	tft.setTextSize(2);
	tft.fillRect(5, 20, 128, 7*2, ST7735_BLACK);
	tft.println(millis());
	delay(24);
}

所感

128x128 は MCU で扱う解像度としてはかなり広く感じます。文字を dot by dot で表示させると 16x2 などの LCD モジュールと比べてかなり情報量が増えます。カラーなのでさらに情報量が増えます。

描画速度も 16x2 の LCD などよりは早いです。ただしバッファが1つなのであまり書き換えが早いとチラついてしまいます。

デメリットとしては制御コードが複雑になる (フットプリントが増える) ことだと思います。上記のコードはかなりシンプルに見えますがプログラムで23.3%、データで7.7%使っています。ライブラリ側の工夫でもうすこし縮められそうな気はしますが、テキスト表示するならフォントは持たざるを得ないので、16x2 と比べると確実にコード量が増えます。

  1. トップ
  2. tech
  3. ST7735 128x128 TFT カラー液晶モジュール

いろいろ回路の説明を見たりしていたのは自分で作ってみたかったからです。既製品を1つ持っていますが、海外製なので壊れたときに不安です。自分で作れれば既製品に頼る必要がひとまずなくなるので安心できますし、自分にニーズに応じてニッチな機能を足しやすくなります。

設計というほどではないですが、手軽に作れそうでベストな回路で作ってみることにしました。

構成

  • 発振器は AD9851 (DDS) のモジュール
  • 検波は AD8307 (ログアンプ)
  • 検出器はブリッジ
  • 計測ポイントは3つ
    • リファレンス電圧 (入力電圧の半分)
    • 負荷電圧 (アンテナの入力電圧)
    • 平衡電圧 (リファレンス電圧と負荷電圧の差

測れる原理はアンテナアナライザの回路 - ブリッジの三つの電位差を測るタイプ | tech - 氾濫原で確認しました。

実際の回路

センサー部

AD8307 は1つにします。というのも、AD8307 を複数使う場合、それぞれの特性があってないことを考慮する必要があって面倒だからです。キャリブレーションレスにしたいと思うと1つにするというのは必要要件です。

測定ポイントの切り替えはRFスイッチでやることにします。これには MASWSS0115 (digikey: 1465-1373-1-ND) を使いました。選定理由は

  • MASWSS0115 は単価約70円と安い
  • 電源電圧 2.3V〜5V
  • DC〜3GHz
  • アイソレーションが22dB @ 3GHz (データーシートのグラフを見ると、HF帯ではもっとある)

アイソレーションが低めなのが気になりましたがHF帯でしか使わないので大丈夫そうです。電源はスイッチ入力と共用です。

これを2つ使って、AD8307 の入力前に信号を切り替えます。

DDS+バッファ

このバッファ回路は再考の必要があります。やりたいことはただのバッファです。

MCU

MCU は LPC1114 を使っています。しかしやってることは

  • DDSの制御
  • ADC
  • シリアル通信

だけです。計算処理を入れるとROMにおさまらないので、コンピュータ側で計算します。この構成だとAVRのほうがリファレンス電圧を任意に設定できるのでアドバンテージがあります。Arduino ベースで作りなおしてもいいぐらいです。

書きこみが楽にできるようにピンヘッダを立ててあります。

使えるか

こんな感じで測定できています。なぜか波うっています。ADCの±1エラーもありそうですが、インピーダンスミスマッチでどこかで反射が起きているのかもしれません。外来ノイズ (アンテナなので普通に受信状態にある) も関係ありそうな気がします。よくわかりません。

VSWR の測定 (測定値2つの単純な割り算) では波うってないので、そんなに気にすることもないかもしれません。

既製品で測定した結果のリアクタンスを絶対値になおしたグラフが以下です。そこそこ一致しているように見えます。波うっているのさえなんとかなれば普通に信用にたる測定器がつくれそうです。

いくつかあった問題

RF バッファ

ほぼ唯一の半導体が絡むアナログ回路であるRFバッファ回路でかなり苦労しました。実際組んでみるとまともに出力がでず、かなり苦労しました。上記回路図中のバッファ回路は一応動いたレベルの定数です。どうしても正しくシミュレーションないし設計通りの計算ができず、試行錯誤しました。

  • トランジスタが思いがけず1つ壊れていた
    • ここに気付くまでだいぶ…
  • AD9851 モジュールのフィルタを通ってない出力を使っていた
    • 電流出力なので出力インタピーダンスがシミュレーションと全くあわなかった
    • フィルタ済みの出力にリワーク
  • 定数がおかしかった
    • よくわからないが試行錯誤してしまった

こんな回路もまともに組めないのか、という感じでつらい感じでした。

あとトランジスタの選定を失敗しました。無駄にfTが高いものを使っているのと、Ic が低く、SSM というパッケージだと他のものと互換性が低いので換えにくいです。

RFスイッチ

試していると、片方のRFスイッチで、信号がGND側に通りぬけて、出力レベルが下がっていることがわかりました。

RFスイッチの故障を疑ったりもしましたが、結局電源の接続がちゃんとできていなかったことが原因でした。かなり小さいICなのでなかなか気付きませんでした。

オープンドレインを出力につかっていた

基板のアートワークを作るときに、ピン配置を配線しやすいように変えたのですが、これがもとでうっかりオープンドレインピンを使うようにしてしまいました。当然動かずしばらく悩みました。リワークで対応しました。

まとめ

まだアプリケーションとしては途中ですが、ひとまず動きそうだぞというところまではできました。

測定結果が波うっているのは未解決です。また、RFバッファも微妙なのでもうちょっとマシにするか、素直にバッファICにしてしまいたいです。

  1. トップ
  2. tech
  3. 簡単かつ安く高精度なアンテナアナライザーを自作したい

前回はある程度うまくいきそうというところまでやりました。7MHz 帯のグラフが波うっているのが気になったので詳しく原因を探して解決しました。

いくつかのバンドで測定してみると、7MHz よりも上の周波数では該当する現象が起きないないし起きにくいことに気付きました。そこで 7MHz で固定発振させて出力波形を見てみると、なんとクリッピングしていました……

RFアンプの設計能力がなさすぎて完全にネックになっています。帰還抵抗だけ修正して増幅率を抑えてみました。

おそらく歪みが残っているとは思いますが見た目的には綺麗になっています。

出力が変わっていますがプログラム上では自動的に入力電力で正規化しているので回路の修正以外はいりません。

修正後の 7MHz のグラフ


まだちょっと変ですが大幅に改善されました。既製品と比べ R 成分が大きく観測されている現象もあったのですがそれもなくなっています。

他のバンドのグラフ

ついでに他バンドのグラフをはっておきます。7Mhz 以外は非常に綺麗にグラフが描けます

14MHz

18MHz



21MHz

28MHz


50MHz

抵抗負荷でのグラフ

以下は50Ωダミーロードを測ってみたグラフです。BNC SMA 変換コネクタ経由で、SMA 1W のダミーロードを繋いでいます。非常に綺麗にでます。 が、なぜか抵抗値が高くでています…

75Ωのカーボン抵抗をBNCコネクタに直接つっこんだグラフです。

同じく100Ωカーボン抵抗です。

さらに 150Ωカーボン抵抗。どうもインピーダンスがずれすぎるとだいぶおかしくなります。反射の影響でしょうか?

水晶発振子

目的外ですが水晶発振子の共振特性も見てみました。いずれも水晶単体をBNCコネクタに直接つっこんで見ています。思ったより綺麗にグラフにでました。

12MHz 水晶


20MHz 水晶

コンデンサ

0.1uF セラミック

0.01uF セラミック

47pF セラミック

インダクタ

円筒型の 10uH インダクタ

メモ

綺麗にグラフが書けないことがある。歪んでいるかなにかしてそう

  1. トップ
  2. tech
  3. 簡単かつ安く高精度なアンテナアナライザーを自作したい (2)

Re:Re:(初回生産限定盤)(DVD付) - ASIAN KUNG-FU GENERATION

ASIAN KUNG-FU GENERATION

5.0 / 5.0

「ASIAN KUNG-FU GENERATION New Single Re:Re:」ってCMが流れていて「おれはリバイバルしちまったか…」とみんな思ったんじゃないか。

全然ニューじゃないだろと思ったんですが、どうやらソルファ版のとは違っていて、アレンジ違い (ライブ版?) を再録しているようです。僕だけがいない街のOP聞いても昔の曲そのまんまだと思っていたので、再録と聞いてびっくり。

ソルファ - ASIAN KUNG-FU GENERATION

ASIAN KUNG-FU GENERATION

5.0 / 5.0

ソルファは2004年。もう12年前ってびっくりするなあ。2004年に生まれた子供はもう中学生になるって考えたら相当やばい感じがする。

以下、試さないで書きましたが、試してみたら全くダメでした。OS 10.11 対応とはなんだったのか? マジでムカついてます……

CaptureOnTouch Lite だとうまくいくことが判明。つまり Auto を On にして出てくる画面のソフトならいける。想像するに CaptureOnTouch DR-P208II は修正漏れなんじゃないか?


Q&A検索(よくあるご質問)|キヤノン

Canon ドキュメントスキャナ imageFORMULA DR-P208II - キヤノン

キヤノン

3.0 / 5.0

DR-P208II を使っているんだけど、El Capitan に OS をアップデートをしてからずっと使えない状態だった (固まる。正常にスキャンできない)。

3月15日付けで上記ページが更新されて「対応済み」に変わった。

ダウンロードページを見てみると確かに 3月14日付けで対応版がリリースされているようだ。

まだ試してないけど、ようやくかという感じすぎる。

El Capitan は 2015-06-09 にデベロッパープレビュー、2015-09-30 に正式リリースだが、2016-03-14 に対応されるまで数ヶ月もかかってる。

しかも「動かない」という致命的な不具合でこれだけかかっていて不思議。普通に考えたら、とりあえず動くバージョンをなんとかしてQAに通すと思うんだけど、リリースノート見ると OCR の精度向上とか比較的優先度低いだろというのも一緒に入ってて謎。


動かないハードウェアは、場所をとるという所有コストを払っている分の損を生み出している。

Ruby の serialport gemで Bluetooth SPP を使おうとすると Errno::EBUSY がでてうまく通信できず、なんでだろう、となりました。接続先の Bluetooth モジュールは Microchip の RN42です。

結論からいうと sleep するしかなさそうです。

begin
	@port = SerialPort.new(
		"/dev/tty.RNBT-68BF-RNI-SPP",
		115200,
		8,
		1,
		0
	)
rescue Errno::EBUSY
	sleep 1
	retry
end

今回のケース

  1. MCU と RN42 の TX/RX/GND を接続し、RN42 に 3.3V を供給 (接続はこれらのみ)
  2. この状態で Mac から RN42 をペアリングする。
    • /dev/tty.RNBT-68BF-RNI-SPP みたいなファイルができる。
  3. Ruby のプログラムで serialport gem を使って通信する

したがって MCU と RN42 の間にはフローコントロールはありません。

  1. トップ
  2. tech
  3. Ruby の serialport gem で Bluetooth SPP を使おうとすると Errno::EBUSY

なんか一時期 elecrow のサイトがさっぱり見れなかったので、PCB Way というのを使ってみました。

簡単かつ安く高精度なアンテナアナライザーを自作したい | tech - 氾濫原 の基板ができあがったそれです。


ガーバー提出

PCB Way は

  • ファイルを提出
  • レビューをうける
  • 支払い

というフローになっていて、レビューが通らないと支払いができません。

今回ちょっと微妙なケース(外形には2枚の基板に見えるが実際は繋がっていて1枚)のガーバーファイルを提出しましたが、1日以内にメールがきて「ここはどうするのか?」と聞かれました (英語です)。普通に回答して返信したらレビューを通してくれました。

あと支払い終了後に支払い失敗という表示になってあせりましたが、PCB Way上で再度確認するとトランザクションは完了してて、とりあえず問題なさそうでした。

リードタイム


DHL がデフォルト発送業者になっていますが、PCB本体よりも送料が圧倒的に高くなるので Hongkong Post での発送にしました。Hongkong Post だとリードタイム最大30日と書いてあってヒヨりますが、とりあえず急いでいないのと、さすがにそこまでかからないだろうという気持ちがあります。

発注から発送開始までは3日ぐらいでした。詳細なプログレスが表示されるのでなんかすごい感じがします。プログレスのビューにある Finished Time は中国時間のようなので、JST-1 です。

Delivery になってからも実際の Hongkong Post のサイトでトラッキングできるようになるまで3日かかりました。Delivery となっても実際投函しているわけではなく、ある程度溜ったのを一括で投函している?ようです。

Hongkong Post で引受状態になると日本郵政でもトラッキングできるようになります。ただ、国内に入るまでは Hongkong Post のサイトでトラッキングしたほうが詳細情報が見れます。引受状態になってから、実際に自宅にくるまでは4日でした。

ということで、発注から9日ぐらいで届きました。

価格

最大 10cm x 10cm のプラン5枚で本体が $13、送料が$9で、$22でした。

仕上がり

一部、細かいところでソルダーマスクが剥れている部分がありましたが致命的ではありませんでした。シルクの綺麗さも特に問題を感じるようなものではないと思います。

Elecrow と比較して

ぶっちゃけ好みな気はしますが、任意の色のソルダーマスクで10x10cmを作る場合は PCB Way のほうが安そうです。

値段以外だと PCB Way は作業状況がちくいちウェブで見れるのは面白いです。一方で Elecrow は発送時に写真をとって送ってくれるのは嬉しいサービスです。が、いずれにせよPCB本体には特に関係ありません。

サイトのできは PCB Way のほうがモダンで良くできている感じがします。支払いでエラーになったのがアレですが……

  1. トップ
  2. tech
  3. PCB Way を使ってみたよ

DIP だと思ったら 2mm ピッチでブレッドボードで使えなかったので PCB Milling で変換基板を掘りました……

変換する基板も売ってますが不必要に高いので雑に掘りました。

削るところを少なくするためにもベタGND にしたいので単純な変換基板ではなく GND がベタに繋がるようになっています。1pin のマーキングのためどこにも繋がらないViaを設置しました。

回路図はひかず Eagle のボード画面だけをCADとして使っています。

スルーホールができないので変換基板は工夫が必要です。細ピンヘッダを無理やり押しこんで片側によせています。ハンダ付け時にハンダをつけすぎるとブレッドボードに刺さらなくなるため結構気をつかいます。

気付いたとき失敗したなあと思いましたが接続状況がでるLEDがついてるのはとりあえずテストするには便利なのでこれはこれでいいと納得すうことにします。

  1. トップ
  2. tech
  3. 間違えて RN-42 の 2mmピッチ基板のやつを買ってしまった

あたりの続きです。

シリアル接続を Bluetooth にして、スマートフォンから接続して測定して結果を表示するようにしています。

Bluetooth モジュールは RN42 を使っています。基板上に載せることもできるようにしたのですが、コントロール側の基板が無駄に大きく、別途作りなおそうかとも思っているので、ひとまずブレッドボードで接続しています。

アプリケーション側

ネイティブで書く気はさらさら起きないため Apache Cordova を使っています。HTML + CSS + JS でアプリを書くやつですがいろんなところで実績があるので割と安心して使えそうです。何度か触ってますが Hello, World までしかやったことがなかったので、Cordova でまともなアプリケーションを作るのは初めてです。

Bluetooth SPP を使いたいので、cordova-plugin-bluetooth-serial を使っています。

全体的なフレームワークとして Polymer を使っています。とはいえレンダリングは canvas なので今のところあんまり Polymer 的機能はつかっていません。

割と普通に書いたら動いたので、それほどハマりどころはありませんでした。

その他

コードはそのうち公開します。

これでとりあえず、

  1. いくつかの設計候補からの設計方針の決定
  2. 実際の回路図起こし (Eagle)
  3. 基板のアートワーク・基板発注 (Eagle, PCB Way)
  4. 手実装
  5. ファームウェアの開発 (mbed)
  6. ソフトウェア開発 (Cordova, Polymer)

までを一通り一つのプロジェクトとして、ほぼ独りでできる見通しになりました。

自分で作ったハードウェアを自分で書いたソフトウェア、特にインターフェイス部分は HTML/CSS/JS という高レイヤーまで一通りできたぞという実感がようやく沸いてきたので嬉しいです。

  1. トップ
  2. tech
  3. 自作アンテナアナライザーのBluetooth化とアプリケーション

朝に悪心で眼が覚め、すこしすると連続した水下痢に。断続的に下痢が出続ける。

悪心もあるので寝ていようとしたが、寝ると夢の中でも下痢をしており、ケツから漏れるという夢を見て「ガタッ!!」と起きること数回、「夢は見るものではなく実現するもの」と言わんばかりに夢じゃなくなったので履いていたパンツは捨てて新しいのし、ズボンは漂白に。

一通り落ちついてきたので一旦会社に行ってしょぼいタスクをやって、やっぱキツいので帰宅して寝ていたが、不用意に寝ると漏れる夢を見るので落ちつかず。

最近子どもが胃腸炎だったので伝染ってきたようだ。妻も胃腸炎で死んでおり、家庭が崩壊している。なお子どもはもう割と元気。

驚異の防臭袋 BOS(ボス)Sサイズ大容量200枚入り 赤ちゃん用 おむつ 処理袋 (袋カラー:ピンク) - BOS

BOS

5.0 / 5.0

パンツ捨てるときはこれに入れた。ほんとこの袋は死ぬほど便利だ

:processDebugResources FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':processDebugResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Users/cho45/Library/Android/sdk/build-tools/23.0.1/aapt'' finished with non-zero exit value 1

こんなエラーで死んでしまいました。gradle 経由で実行されてるんですが、gradle へのコマンドラインオプションの渡しかたがわからず……

cordova clean したり rm -rf platforms/android しても解決しなかったのですが、Dropbox に入れておいたせいで、ソースツリー内に「www/src/app (xxxx 競合コピー 2016-03-30).js」のようなファイル(特に心あたりなし)ができており、これを削除したら解決しました。稀な例だと思いますが…

  1. トップ
  2. tech
  3. cordova run android --device でエラー