Analog Discovery 2 には波形発生器(Waveform Generator)とオシロスコープ(Oscilloscope)が搭載されており、任意の周波数・電圧の波形を出力したり、回路の電圧波形を観測したりできます。JavaScript による自動化機能を使えば、波形発生器の出力設定を変えつつオシロスコープで自動的に観測するようなことが可能です。例えば MOSFET の Id-Vgs 特性の測定ではゲート電圧を変えながらドレイン電流を測る必要がありますが、自動化機能を使って「ゲート電圧の変更」と「ドレイン電流の測定」を自動的に行えば、素早く多くのデータを得ることができます。
本記事では自動化の際に問題になり得ることとして、波形発生器の出力電圧が安定するまでの時間を検証しました。スクリプトから出力電圧を設定しても、実際の出力がその電圧になるまでには多少時間がかかります。どの程度の時間を待てば出力が安定するのでしょうか。
検証回路とスクリプト
検証回路は Analog Discovery 2 の端子を次の通り接続しました。
- C1+(橙) W1(黄)
- C1-(橙・白) GND(黒)
C1+ はオシロスコープのチャンネル 1 のプラス側、C1- はマイナス側です。W1 は波形発生器のチャンネル 1 の出力端子です。波形発生器の出力をそのままオシロスコープに入力して読み取る構成ですね。今回の測定では波形発生器の出力波形を DC とし、出力電圧をオシロスコープで読み取り、電圧が安定するまでの時間を計ります。
回路といっていいかどうか分からない単純さです。念のため写真も示します。
検証に用いたスクリプトは次の通りです。スクリプト処理の概要は Using the Script Editor - Digilent Reference が詳しいです。
var numMeasure = 201; // 測定点の数
var vRange = 10.0; // 測定電圧範囲(V)
var vOffset = 0.0; // 測定電圧オフセット(V)
var waitSecs = 0.01; // 1ループごとの待ち時間(S)
clear()
if (!('Wavegen1' in this) || !('Scope1' in this)) {
throw 'Please open a Scope and a Wavegen instrument';
}
if (!('plot1' in this)) {
throw 'Please open a plot';
}
function toPrecision(num, intDigits, fracDigits) {
var s = num.toPrecision(intDigits + 1 + fracDigits);
var dotPos = s.indexOf('.');
var spaces = ' '.slice(0, intDigits - dotPos);
return (spaces + s).slice(0, intDigits + 1 + fracDigits);
}
function printMeasure(i, v, v0, v1, vn, nWait) {
var err = ' ---- ';
if (v != 0) {
err = toPrecision(100 * (vn - v) / v, 2, 2) + '%';
}
print('[' + (' ' + i).slice(-3) + ']: ' +
'V=' + toPrecision(v, 2, 4) + ' ' +
'V0=' + toPrecision(v0, 2, 4) + ' ' +
'V1=' + toPrecision(v1, 2, 4) + ' ' +
'Vn=' + toPrecision(vn, 2, 4) + ' ' +
'Err=' + err + ' ' +
'N=' + nWait
);
}
var wav = Wavegen.Channel1;
wav.Mode.text = 'Simple';
wav.Simple.Type.text = 'DC';
wav.Simple.Offset.value = 0;
Scope1.Time.Base.value = 0.0005;
Wavegen.run();
Scope1.run();
wait(0.5);
var vMin = vOffset - vRange / 2;
function indexToVolts(i) {
return i / (numMeasure - 1) * vRange + vMin;
}
function isAccurate(target, real) {
if (isNaN(real)) {
return false;
}
target = Math.abs(target);
real = Math.abs(real);
if (target <= 1) {
// ±1V以下のときは±5mVに収まるかどうかを検査
return Math.abs(target - real) <= 0.005;
} else {
// ±1Vを超えるときは±0.5%に収まるかどうかを検査
return target * 0.995 <= real && real <= target * 1.005;
}
}
var nWaits = [];
for (var i = 0; i < numMeasure; i++) {
// 目標電圧 v
var v = indexToVolts(i);
// 波形発生器の出力電圧を設定
wav.Simple.Offset.value = v;
var v0 = Scope1.Channel1.measure('Average');
wait(waitSecs);
var v1 = Scope1.Channel1.measure('Average');
var running = true;
var nWait = 2;
var vn = NaN;
while (running = wait(waitSecs)) {
vn = Scope1.Channel1.measure('Average');
if (isAccurate(v, vn) || nWait >= 100) {
// 許容誤差に収まるまでのwaitの回数を数える
break;
}
nWait++;
}
if (!running) {
print('Canceled');
break;
}
nWaits.push(nWait);
printMeasure(i, v, v0, v1, vn, nWait);
}
wav.Simple.Offset.value = 0;
plot1.X.Units.text = 'V';
plot1.X.Range.value = vRange;
plot1.X.Offset.value = -vOffset;
plot1.Y1.AutoScale.checked = false;
plot1.Y1.Range.value = 10;
plot1.Y1.Offset.value = -5;
plot1.Y1.Units.text = 'Count';
plot1.Y1.data = nWaits;
このスクリプトは、vRange
で指定された範囲の電圧を出力し、それをオシロスコープで読み取り、出力が安定するまでの時間を計ります。W1 に出力する電圧の設定を行い、設定した出力電圧になるまで待ち、待った時間を記録するという処理を、出力電圧を少しずつ変えながら繰り返し実行します。
設定した電圧になったかどうかの判定は isAccurate
関数で行っています。Analog Discovery 2 Specifications - Digilent Reference によれば、波形発生器の精度は出力電圧(の絶対値)が 1V 以下の場合に「±10mV ±0.5%」、1V を超える場合に「±25mV ±0.5%」とあります。この表記の正確な意味が取れずにいるのですが、とりあえず次のように判定することとしました。
- 1V 以下のときは±5mV に収まれば真
- 1V を超えるときは±0.5% に収まれば真
皆さんの Analog Discovery では、経年劣化や個体差などにより、もしかするとこのままの実装では電圧が一向に収束せず、期待する測定ができないかもしれません。isAccurate
の判定基準を緩めて調整してみてください。
処理のメイン部分は後半の for
文です。ここに登場する変数を説明します。
変数名 | 役割 |
---|---|
nWaits |
待ち時間を記録する配列 |
v |
W1 に出力する電圧(V) |
v0 |
電圧設定後、すぐに読み取った電圧(V) |
v1 |
1 回だけ wait した後で読み取った電圧(V) |
vn |
nWait 回だけ wait した後で読み取った電圧(V) |
1 回の wait
で待つ時間は waitSecs
で設定します。今回は 10ms として実験しました。ですので、例えば nWait
=3 であれば 30ms 程度の時間が経過したことになります。もっとも、このような短い時間のタイマーは(Windows などの汎用 OS 上では)正確ではありませんから、今回の測定は全体的に参考値程度に考えてください。
測定結果
もし Analog Discovery 2 の波形発生器(とオシロスコープ)が理想的な動きをするのであれば、wav.Simple.Offset.value = v;
として W1 の出力電圧を設定した直後に同じ電圧が読み取れるはずです。ですが、実際に測定してみるといくらか時間を置かなければ設定した電圧にならないことが分かりました。
-5V から 5V まで、50mV ずつ上昇させながら測定した結果を示します。
大体の電圧で 3、4 回の待ちが発生しています。単純計算で 30ms~40ms の待ち時間、wait
の呼び出しやループ処理のオーバーヘッドを考えればそれより若干長い待ち時間です。波形発生器の出力電圧を設定してから 30ms~40ms 待たないと期待する電圧にならないということが分かりました。今回は 50mV ずつの変化ですが、もっと大きな変化をさせる場合はさらに待ち時間が伸びる可能性があります。
注目すべきはときどき長い待ち時間が発生していることです。トゲのような部分が 2 箇所ありますね。どの電圧で待ち時間が長くなるかは実行するたびに変わりますし、このようなスパイクが観測されないこともあります。待ち時間が毎回安定してくれていれば良いのですが、残念ながらそうではないようです。
実際の測定への応用
MOSFET の Id-Vgs 特性を測定する場合、100mA 以下くらいの Id の範囲なら WaveForms の標準機能である Curve Tracer で測定可能です。自分でスクリプトを書かずとも非常に簡単に測定できます。しかし、パワー MOSFET の特性測定など、100mA を超える大電流で Id-Vgs 特性を測りたいなら自動化スクリプトを書くことになるでしょう(外部の電源を使う場合に標準の Curve Tracer は使えませんので)。
Id-Vgs 特性の測定では、典型的には Vgs を少しずつ変化させながら Id を測定することになります。MOSFET のゲート端子に W1(あるいは W2)を接続し、DC モードで電圧を変えていきます。先の実験結果より、W1 の電圧が設定電圧に十分に近くなるまで待つ必要があるということが分かります。
何秒待てば良いかというのが安定しないため、最悪ケースを考えると Vgs をちょっと変えるたびに 0.3 秒くらい待つ必要があるでしょうか。もし、0V~5V の範囲を 10mV ずつ変化させて測定しようと思えば、500 ステップ× 0.3 = 150 秒もの時間が掛かってしまいます。
高速化のためには、W1 の出力を C1(あるいは C2~C4)で測定し、W1 の電圧が設定電圧に十分近づいたことを検出するのが良いでしょう。そうすれば、待ち時間は多くの場合 30ms~40ms 程度に短縮できますし、ときどき発生する安定までに長時間かかるケースにも対応できます。500 ステップで 20 秒程度に縮まる計算です。Curve Tracer など、WaveForms に組み込まれている測定機能群でも W1 や W2 には必ず C1~C4 のいずれかを接続する構成になっており、きっと同じような問題に対処しているんだろうなと思います。
投稿者の人気記事
-
uchan
さんが
2022/12/28
に
編集
をしました。
(メッセージ: 初版)
Closed
mipsparc
2022/12/28
2 件の返信が折りたたまれています
ログインしてコメントを投稿する失礼します。OSに関連する著書も執筆されているuchan様には釈迦に説法だと重々承知の上で質問させていただくのですが、
30msの測定について、「もっとも、このような短い時間のタイマーは(Windows などの汎用 OS 上では)正確ではありません」というのは少し疑問に感じました。
ご執筆なされた資料にもあるとおり、高精度タイマーによる割り込み命令はありますし、コンテキストスイッチ優先度を上げればかなり高精度な(非科学的な表現ですみません)タイマーを使えると思うのですが、いかがでしょうか。
重箱の隅をつつくようですみません、失礼いたしました、