IoTで使うPython入門 Step4-Python3ソケット②DMM 34461A高速にデータを取得
SCPIコマンドはとてもたくさんあるので、事例集を探しました。Keysightのサンプル・プログラムをダウンロードします。
34460A/34461Aの入門SCPIシーケンス・サンプル
●FastDCV
サンプルの中にある、まとめて高速にデータを取得するSCPIコマンドの事例です。
| *IDN? 測定器のIDを取得
CONF:VOLT:DC 10, MAX; DCV、10V レンジに固定、分解能最大 SAMP:COUN 1000; SAMPle:COUNt。サンプリング・カウント1000回 INIT; 測定開始 SYST:ERR? エラー有無の確認 |
pythonで上記のコマンドの送信とデータを取得します。送る文字列はASCIIで、messageという文字列変数へ入れました。長いので、\ で分割しています。messageはmessage.encode()でバイト列にして送ります。
import socket
ipAddr = "K-34461A-16054.local"
ports = 5025
message = '*IDN\n'\
'CONF:VOLT:DC 10, MAX;\n'\
'VOLT:DC:NPLC MIN;\n'\
'VOLT:DC:ZERO:AUTO OFF;\n'\
'VOLT:DC:NULL:STAT OFF;\n'\
'\n'\
'SAMP:COUN 1000;\n'\
'TRIG:SOUR BUS;\n'\
'INIT;\n'\
'*TRG;\n'\
'DATA:REM? 1000, WAIT\n'\
'\n'\
'SYST:ERR?\n'
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((ipAddr, ports))
#print(message)
s.send(message.encode())
s = s.recv(16000)
#print(type(s),s)
ss = (str(s)[:-3])[2:]
#print(type(ss),ss)
sss = str(ss).split(',')
#print(list(sss))
f = [float(f) for f in sss]
print(f,len(f))
受け取った値は、
b'+2.49403830E+00, +2.49372795E+00, ではじまり、
,+2.49366361E+00\n'までの、1個のバイト列です。
1000個のサンプリング・データは、s.recv(16000)の読み取り数で1000個ぴったりです。このバッファが大きすぎると、存在しない領域を読み取ろうとして、
\n-113,"Undefined header"\n'
というエラーが出ます。バッファが小さいと、すべてのデータを読み切れません。したがって、このバッファを数字を試行錯誤で求めないと、適切な読み出しにならないので、プログラムとしては不完全です。
(str(s)[:-3])[2:]で、先頭のb'と末尾の\n'を削除しています。この結果、次の計測値だけのバイト列が得られます。
+2.49403830E+00, +2.49372795E+00, ... ,+2.49366361E+00
str(ss).split(',')は、カンマでそれぞれの測定値を分離し、リスト形式にします。測定値は、この状態では文字列です。
[float(f) for f in sss]は、内包形式のfor文で、文字列を数値に変更します。次の実行例のような数値データが得られます。
●改良
エラー・メッセージの’113’が受信したバイト列に入っていたら、そこまでのデータを出力するというように変更しました。
import socket
ipAddr = "K-34461A-16054.local"
ports = 5025
message = '*IDN\n'\
'CONF:VOLT:DC 10, MAX;\n'\
'VOLT:DC:NPLC MIN;\n'\
'VOLT:DC:ZERO:AUTO OFF;\n'\
'VOLT:DC:NULL:STAT OFF;\n'\
'\n'\
'SAMP:COUN 1000;\n'\
'TRIG:SOUR BUS;\n'\
'INIT;\n'\
'*TRG;\n'\
'DATA:REM? 1000, WAIT\n'\
'\n'\
'SYST:ERR?\n'
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((ipAddr, ports))
s.send(message.encode())
s1 = b''
i =0
while 1:
i= i+1
s0 = s.recv(16)
if '113' in str(s0):
break
s1=s1+s0
ss = (str(s1)[:-3])[2:]
sss = str(ss).split(',')
f = [float(f) for f in sss]
print(f,len(f))
DATA:REM? 1000, WAITは、FETC?でも同様に動作します。DATA:REM?はDMMの内部メモリを消去しています。FETC?は読み出すだけです。34461Aは、最大10,000個の測定値を保存できます。内部の読み値メモリがオーバフローすると 、保存された測定値のうち の最も古い値が新しい測定値によっ て上書きされ、常に、最新の測定値が維持されます。
(参考資料)
Keysight Truevolt デジタル・マルチメータ 操作およびサービ ス・ガイ ド
34410A/11A プログラミング-こんなとき、どんなコマンドを使う?
コラム ロギングを止める
プログラムの開発中には、DMM側のデータ・ロギングが動きっぱなしになっています。次のプログラムでクリアし、リモートを解除します。
import socket ipAddr = "K-34461A-16054.local" ports = 5025 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((ipAddr, ports)) s.send(b'*RST;*CLS\n') s.send(b'SYSTem:LOCal\n')
