測定器の SCPI-telnet 接続と自動測定

# 1. はじめに
測定器を使って決まった測定を行うとき、
いちいちフロントパネルで設定するのは面倒ですし、時間がかかります。
手動でやっていると、設定忘れやミスも誘発します。

PC から自動設定できれば、間違いを起こさず、
毎回同じ条件で即座に測定を始められます。

昔からあるのは GPIB を使った SCPI 自動測定ですが、
最近の測定器は LAN や USB での接続が可能です。
Excel から VB で制御して、自動でグラフまで描く例がありますが、
Socket とか VISA COM ライブラリがとっつきづらいです。

一部の LXI 対応測定器では、LAN から telnet 接続で SCPI 制御ができます。
使い慣れた Teraterm で設定や操作ができると、簡単に設定ができます。
マクロを使って、自動測定することも可能です。

>Scpi-telnet
https://www.lxistandard.org/About/LXI-Protocols.aspx

今回は、Keysight 社の周波数カウンタ、53230A を例にしてみます。
https://www.keysight.com/jp/ja/product/53230A/350-mhz-universal-frequency-counter-timer-12-digits-s-20-ps.html


# 2. 参考資料
Keysight 53220A/53230A Frequency Universal Counter/Timer Programmer's Reference
https://www.keysight.com/gb/en/library/manuals/programming-and-syntax-guide/53220a53230a-frequency-universalcountertimer-programmers-reference-1971001.html
※リンク切れているようです。修正依頼を出しておきましたが、
　治るまでは野良サイトで見るしかない模様...
https://www.manualslib.com/manual/1656865/Keysight-53220a.html

LAN測定器をソケットで制御するときのポート番号は? (Keysight FAQs)
https://edadocs.software.keysight.com/kkbopen/lan-609460767.html


# 3. Teraterm での操作例

53230A の IP アドレスを、192.168.1.7 に設定して、LAN 接続します。
Teraterm で Port: 5024 に telnet 接続して、SCPI ポートを開きます。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/647b8495-9832-23b8-3fbb-c99c76a787b6.png)

Teraterm の設定は下記です。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/7d43efb1-960f-4e71-5b54-dfd6b760c0a6.png)


プロンプトが表示されますので、*IDN? と入力すると、
測定器の識別情報が返ってきます。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/2b8c457b-71d8-6258-2786-4a5454bdc22b.png)


SCPI コマンドは沢山ありますので、
各測定器の Programmer's Reference を参照してください。


# 4. マクロを使った操作例

## 4.1. 周波数測定

下記の設定で、10MHz の周波数を測定します。

>表示桁数: 15桁
>入力: チャンネル1
>ゲートタイム: 0.1秒
>測定サンプル回数: 100回
>入力カップリング: DC
>入力インピーダンス: 50Ω
>自動レベル調整: オフ
>入力スレッショルド: 0V (オフセット0V の AC クロック入力)
>ヒストグラム表示のスパン: 10 MHz ± 5Hz (±0.5ppm)

__操作方法: 数値を入力して ENTER__
>0: 再測定
>1: 測定結果の一覧表示
>2: ヒストグラム表示
>3: トレンド表示
>98: エラー読み出し
>99: 終了

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/606f2b40-9b6d-60a2-f2a6-96b08aa6f657.png)

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/af198c17-6f98-3364-b26f-c7e12fab0d62.png)


```53230A_10M_freq_measure.ttl
; 53230A で 10 MHz 基準クロックの周波数測定
; by kan573

sendln '*RST'
recvln
wait '53230A>'
sendln 'DISP:DIG:MASK 15'
recvln
wait '53230A>'
sendln 'CONF:FREQ (@1)'
recvln
wait '53230A>'
sendln 'FREQ:GATE:TIME .1'
recvln
wait '53230A>'
sendln 'SAMP:COUN 100'
recvln
wait '53230A>'
sendln 'INP:COUP DC'
recvln
wait '53230A>'
sendln 'INP:IMP 50'
recvln
wait '53230A>'
sendln 'INP:LEV:AUTO OFF'
recvln
wait '53230A>'
sendln 'INP:LEV1 0'
recvln
wait '53230A>'
sendln 'INP:LEV2 0'
recvln
wait '53230A>'
sendln 'CALC:STAT ON'
recvln
wait '53230A>'
sendln 'CALC:AVER:STAT ON'
recvln
wait '53230A>'
sendln 'CALC2:TRAN:HIST:STAT ON'
recvln
wait '53230A>'
sendln 'CALC2:TRAN:HIST:RANG:UPPer 10.000005E6'
recvln
wait '53230A>'
sendln 'CALC2:TRAN:HIST:RANG:LOWer  9.999995E6'
recvln
wait '53230A>'
sendln 'DISPLAY:MODE NUM'
recvln
wait '53230A>'
sendln 'INIT'
recvln
wait '53230A>'


:lp
InputBox '0:再測定, 1:測定値表示, 2:ヒストグラム表示, 3:トレンド表示, 98:エラー読出, 99:終了' '53230A 10 MHz 周波数測定'
str2int inputNUM inputSTR

if InputNUM = 0 then
	dispstr '-------- 再測定 : '
	sendln 'INIT'
	recvln
	wait '53230A>'
Endif

if InputNUM = 1 then
	sendln 'DISPLAY:MODE NUM'
	recvln
	mpause 100
	dispstr #13#10#10 '-------- 測定値表示: ' #13#10#10#10
	mpause 100
	wait '53230A>'

	dispstr #13 '平均周波数 (Hz) : '
	sendln 'CALC:AVER:AVER?'
	dispstr '  '
	recvln
	wait '53230A>'

	dispstr #13 'RMS Jitter (Hz) : '
	sendln 'CALC:AVER:SDEV?'
	dispstr '  '
	recvln
	wait '53230A>'

	dispstr #13 'p-p Jitter (Hz) : '
	sendln 'CALC:AVER:PTP?'
	dispstr '  '
	recvln
	mpause 100
	wait '53230A>'
	dispstr #13 '       ' #13#10#10

Endif

if InputNUM = 2 then
	dispstr '-------- ヒストグラム表示    : '
	sendln 'DISPLAY:MODE HIST'
	recvln
	wait '53230A>'
Endif

if InputNUM = 3 then
	dispstr '-------- トレンドチャート表示: '
	sendln 'DISPLAY:MODE TCH'
	recvln
	wait '53230A>'
Endif

if InputNUM = 98 then
	dispstr '-------- エラー内容読出      : '
	sendln 'SYST:ERR?'
	recvln
	wait '53230A>'
Endif

if InputNUM = 99 then
	dispstr '-------- 測定終了' #10#13
	sendln ''
	goto lp_end
Endif

goto lp

:lp_end
end

```


## 4.2. 周期とジッター測定

下記の設定で、10MHz の周期とジッターを測定します。

>表示桁数: 8桁
>入力: チャンネル1
>ゲートタイム: 0.1秒
>測定サンプル回数: 10000回
>入力カップリング: DC
>入力インピーダンス: 50Ω
>自動レベル調整: オフ
>入力スレッショルド: 0V (オフセット0V の AC クロック入力)
>ヒストグラム表示のスパン: 10 MHz ± 5Hz (±0.5ppm)

__操作方法: 数値を入力して ENTER__
>0: 再測定
>1: 測定結果の一覧表示
>2: ヒストグラム表示
>3: トレンド表示
>4: ヒストグラム表示のスパン: ±500ppm
>5: ヒストグラム表示のスパン: ±250ppm
>6: ヒストグラム表示のスパン: ±100ppm
>98: エラー読み出し
>99: 終了

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/7a6a8348-268b-baf9-5dc6-76c7673f27ad.png)

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/aa46611e-8e90-1c37-c4e3-b46566cbe4fd.png)


```53230A_10M_jitter_measure.ttl
; 53230A で 10 MHz 基準クロックのジッター測定
; by kan573

sendln '*RST'
recvln
wait '53230A>'
sendln 'DISP:DIG:MASK 8'
recvln
wait '53230A>'
sendln 'CONF:SPER (@1)'
recvln
wait '53230A>'
sendln 'SAMP:COUN 1E5'
recvln
wait '53230A>'
sendln 'INP:COUP DC'
recvln
wait '53230A>'
sendln 'INP:IMP 50'
recvln
wait '53230A>'
sendln 'INP:LEV:AUTO OFF'
recvln
wait '53230A>'
sendln 'INP:LEV1 0'
recvln
wait '53230A>'
sendln 'INP:LEV2 0'
recvln
wait '53230A>'
sendln 'CALC:STAT ON'
recvln
wait '53230A>'
sendln 'CALC:AVER:STAT ON'
recvln
wait '53230A>'
sendln 'CALC2:TRAN:HIST:STAT ON'
recvln
wait '53230A>'
sendln 'CALC2:TRAN:HIST:RANG:UPPer 100.5E-9'
recvln
wait '53230A>'
sendln 'CALC2:TRAN:HIST:RANG:LOWer 99.5E-9'
recvln
wait '53230A>'
sendln 'DISPLAY:MODE NUM'
recvln
wait '53230A>'
sendln 'INIT'
recvln
wait '53230A>'


:lp
InputBox '0: 再測定, 1: 測定値表示, 2:ヒストグラム表示, 3:トレンド表示, 4:±500ppm, 5:±250ppm, 6:±100ppm, 98:エラー読出, 99:終了' '53230A 10 MHz ジッター測定'
str2int inputNUM inputSTR

if InputNUM = 0 then
	dispstr '再測定 :              '
	sendln 'INIT'
	recvln
	wait '53230A>'
Endif

if InputNUM = 1 then
	dispstr '-------- 測定値表示:  '
	sendln 'DISPLAY:MODE NUM'
	recvln
	wait '53230A>'

	dispstr ' 平均周期 (秒) : '
	sendln 'CALC:AVER:AVER?'
	recvln
	wait '53230A>'

	dispstr ' 標準偏差 RMS Jitter (秒) : '
	sendln 'CALC:AVER:SDEV?'
	recvln
	wait '53230A>'

	dispstr ' ピーク p-p Jitter (秒) : '
	sendln 'CALC:AVER:PTP?'
	recvln
	wait '53230A>'
Endif

if InputNUM = 2 then
	dispstr 'ヒストグラム表示:     '
	sendln 'DISPLAY:MODE HIST'
	recvln
	wait '53230A>'
Endif

if InputNUM = 3 then
	dispstr 'トレンドチャート表示: '
	sendln 'DISPLAY:MODE TCH'
	recvln
	wait '53230A>'
Endif

if InputNUM = 4 then
	dispstr 'ヒストグラムSPAN ±500ppm:    '
	sendln 'CALC2:TRAN:HIST:RANG:UPPer 100.5E-9'
	recvln
	wait '53230A>'
	sendln 'CALC2:TRAN:HIST:RANG:LOWer 99.5E-9'
	recvln
	wait '53230A>'
Endif

if InputNUM = 5 then
	dispstr 'ヒストグラムSPAN ±250ppm:    '
	sendln 'CALC2:TRAN:HIST:RANG:UPPer 100.25E-9'
	recvln
	wait '53230A>'
	sendln 'CALC2:TRAN:HIST:RANG:LOWer 99.75E-9'
	recvln
	wait '53230A>'
Endif

if InputNUM = 6 then
	dispstr 'ヒストグラムSPAN ±100ppm:    '
	sendln 'CALC2:TRAN:HIST:RANG:UPPer 100.1E-9'
	recvln
	wait '53230A>'
	sendln 'CALC2:TRAN:HIST:RANG:LOWer 99.9E-9'
	recvln
	wait '53230A>'
Endif

if InputNUM = 98 then
	dispstr 'エラー内容読出:       '
	sendln 'SYST:ERR?'
	recvln
	wait '53230A>'
Endif

if InputNUM = 99 then
	dispstr '測定終了' #10#13
	sendln ''
	goto lp_end
Endif

goto lp


:lp_end
end


```


## 4.3. アラン偏差測定

下記の設定で、アラン偏差を測定します。

>表示桁数: 10桁
>入力: チャンネル1
>ゲートタイム: τとして可変
>測定サンプル回数: τに合わせて設定(3～10000回)
>入力カップリング: DC
>入力インピーダンス: 50Ω
>自動レベル調整: オフ
>入力スレッショルド: 0V (オフセット0V の AC クロック入力)

__操作方法: 数値を入力して ENTER__
>0: 測定値表示
>1-36: τをそれぞれ設定して測定実施
>98: エラー読み出し
>99: 終了

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/192198fb-85e0-5546-2189-47d4b8712309.png)

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/c9cb82f6-a298-37f9-add3-39955e9ec8c5.png)


```53230A_allan_measure.ttl
; 53230A で 10 MHz 基準クロックのアラン偏差測定
; by kan573

sendln '*RST'
recvln
wait '53230A>'
sendln 'DISP:DIG:MASK 10'
recvln
wait '53230A>'
sendln 'CONF:FREQ (@1)'
recvln
wait '53230A>'
sendln 'SAMP:COUN 10'
recvln
wait '53230A>'
sendln 'INP:COUP DC'
recvln
wait '53230A>'
sendln 'INP:IMP 50'
recvln
wait '53230A>'
sendln 'INP:LEV:AUTO OFF'
recvln
wait '53230A>'
sendln 'INP:LEV1 0'
recvln
wait '53230A>'
sendln 'INP:LEV2 0'
recvln
wait '53230A>'
sendln 'CALC:STAT ON'
recvln
wait '53230A>'
sendln 'CALC:AVER:STAT ON'
recvln
wait '53230A>'
sendln 'DISPLAY:MODE NUM'
recvln
wait '53230A>'
sendln 'INIT'
recvln
wait '53230A>'

:lp
InputBox '0:測定値表示, 1-36:測定実施, 98:エラー読出, 99:終了' '53230A アラン偏差 測定'
str2int inputNUM inputSTR

if InputNUM = 0 then
	dispstr '-------- 測定値表示: ' #10#13
	dispstr ' ' #10#13
	dispstr ' アラン偏差(Hz) : '
	sendln 'CALC:AVER:ADEV?'
	recvln
	wait '53230A'
Endif

if InputNUM = 1 then
	meas_tau = '1us'
	gate_time = '.000001'
	samp_count = '10000'
Endif

if InputNUM = 2 then
	meas_tau = '2us'
	gate_time = '.000002'
	samp_count = '10000'
Endif

if InputNUM = 3 then
	meas_tau = '3us'
	gate_time = '.000003'
	samp_count = '10000'
Endif

if InputNUM = 4 then
	meas_tau = '5us'
	gate_time = '.000005'
	samp_count = '10000'
Endif

if InputNUM = 5 then
	meas_tau = '7us'
	gate_time = '.000007'
	samp_count = '10000'
Endif

if InputNUM = 6 then
	meas_tau = '10us'
	gate_time = '.00001'
	samp_count = '10000'
Endif

if InputNUM = 7 then
	meas_tau = '20us'
	gate_time = '.00002'
	samp_count = '10000'
Endif

if InputNUM = 8 then
	meas_tau = '30us'
	gate_time = '.00003'
	samp_count = '10000'
Endif

if InputNUM = 9 then
	meas_tau = '50us'
	gate_time = '.00005'
	samp_count = '10000'
Endif

if InputNUM = 10 then
	meas_tau = '70us'
	gate_time = '.00007'
	samp_count = '10000'
Endif

if InputNUM = 11 then
	meas_tau = '100us'
	gate_time = '.0001'
	samp_count = '10000'
Endif

if InputNUM = 12 then
	meas_tau = '200us'
	gate_time = '.0002'
	samp_count = '10000'
Endif

if InputNUM = 13 then
	meas_tau = '300us'
	gate_time = '.0003'
	samp_count = '10000'
Endif

if InputNUM = 14 then
	meas_tau = '500us'
	gate_time = '.0005'
	samp_count = '7000'
Endif

if InputNUM = 15 then
	meas_tau = '700us'
	gate_time = '.0007'
	samp_count = '5000'
Endif

if InputNUM = 16 then
	meas_tau = '1ms'
	gate_time = '.001'
	samp_count = '2000'
Endif

if InputNUM = 17 then
	meas_tau = '2ms'
	gate_time = '.002'
	samp_count = '1000'
Endif

if InputNUM = 18 then
	meas_tau = '3ms'
	gate_time = '.003'
	samp_count = '1000'
Endif

if InputNUM = 19 then
	meas_tau = '5ms'
	gate_time = '.005'
	samp_count = '1000'
Endif

if InputNUM = 20 then
	meas_tau = '7ms'
	gate_time = '.007'
	samp_count = '1000'
Endif

if InputNUM = 21 then
	meas_tau = '10ms'
	gate_time = '.01'
	samp_count = '100'
Endif

if InputNUM = 22 then
	meas_tau = '20ms'
	gate_time = '.02'
	samp_count = '100'
Endif

if InputNUM = 23 then
	meas_tau = '30ms'
	gate_time = '.03'
	samp_count = '100'
Endif

if InputNUM = 24 then
	meas_tau = '50ms'
	gate_time = '.05'
	samp_count = '100'
Endif

if InputNUM = 25 then
	meas_tau = '70ms'
	gate_time = '.07'
	samp_count = '100'
Endif

if InputNUM = 26 then
	meas_tau = '100ms'
	gate_time = '.1'
	samp_count = '100'
Endif

if InputNUM = 27 then
	meas_tau = '200ms'
	gate_time = '.2'
	samp_count = '50'
Endif

if InputNUM = 28 then
	meas_tau = '300ms'
	gate_time = '.3'
	samp_count = '33'
Endif

if InputNUM = 29 then
	meas_tau = '500ms'
	gate_time = '.5'
	samp_count = '20'
Endif

if InputNUM = 30 then
	meas_tau = '700ms'
	gate_time = '.7'
	samp_count = '15'
Endif

if InputNUM = 31 then
	meas_tau = '1s'
	gate_time = '1'
	samp_count = '10'
Endif

if InputNUM = 32 then
	meas_tau = '2s'
	gate_time = '2'
	samp_count = '7'
Endif

if InputNUM = 33 then
	meas_tau = '3s'
	gate_time = '3'
	samp_count = '6'
Endif

if InputNUM = 34 then
	meas_tau = '5s'
	gate_time = '5'
	samp_count = '5'
Endif

if InputNUM = 35 then
	meas_tau = '7s'
	gate_time = '7'
	samp_count = '3'
Endif

if InputNUM = 36 then
	meas_tau = '10s'
	gate_time = '10'
	samp_count = '2'
Endif

;---

if InputNUM = 98 then
	dispstr 'エラー内容読出:    '
	sendln 'SYST:ERR?'
	recvln
	wait '53230A>'
	goto lp
Endif

if InputNUM = 99 then
	dispstr '-------- 測定終了' #10#13
	sendln ''
	goto lp_end
Endif

;---

if InputNUM != 0 then
	dispstr '-------- 測定: ' meas_tau ' -> '
	sendln 'SENS:FREQ:GATE:TIME ' gate_time
	recvln
	wait '53230A>'
	sendln 'SAMP:COUN ' samp_count
	recvln
	wait '53230A>'
	sendln 'init'
	recvln
	wait '53230A>'
Endif

goto lp


:lp_end
end


```


__ある GPSDO のアラン偏差を、手動で表にしたもの__
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/744e52b8-288c-ac2d-dbc0-d9e6e260adac.png)


__6種類の水晶発振器について、アラン偏差をプロットしたグラフ__
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/09c10f95-0e72-9da7-d3a1-66b7c05fe27b.png)

※これを測りたくて、自動測定に手をつけました ... 水色の GPSDO が、何かおかしい


# 5. まとめ
Teraterm から、SCPI を使って測定器の制御ができました。
Keysight 以外だと、Rohde & Schwarz や teledynelecroy でも
telnet で SCPI 制御できるようです。