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')