IoTで使うPython入門 Step4-Python3ソケット③DMM 34461Aデータ連続読み出し
前回、決まった測定数を読み出しました。ここでは、連続測定の指定をしてDMMのメモリに残っている測定データをつぎつぎと読み出すことで、連続して測定&読み出しをするプログラムを作ります。
●SCPIコマンド
34410A/11A プログラミング-こんなとき、どんなコマンドを使う?- の「定期的に PC にデータを転送しながら高速連続データロギングを実施するには?」のサンプルをベースに直流電圧を測定します。
*RST;*CLS リセット、クリア CONF:VOLT:DC 10, MAX; DCV測定, 10Vレンジ、分解能最大 VOLT:DC:NPLC MIN; 積分時間を最小に VOLT:DC:ZERO:AUTO OFF; オートゼロOFF VOLT:DC:NULL:STAT OFF; TRIG:SOURce IMMediate; 内部トリガ TRIG:COUNt INFinity; トリガ・カウント無限大 TRIG:DEL 0; トリガ遅延 0 FORMat ASCii; データ・フォーマットをASCIIに設定 *OPC? 動作完了確認 Readyだと'1'が返る ループ 数バイト読み込んで1であれば、 INIT 数字nが返ってくる R? n 読み取った n データ分を問い合わせ データ受信 ループ・エンド |
●1回だけ読み取る
ASCIIデータは有効桁9文字固定です(34461Aではバイナリの設定はできない)。DATA:POIN? を送った後に、ヘッダ部分を含む10バイトを読み込みます。
b'#3558+2.
のようなバイト列が得られます。#の後ろの1文字は、そのあとに続くデータ数の桁数を表しています。この例だと3なので、558がデータ数の数値です。+2.は、1番目のデータの先頭部分が見えています。
データ数がわかったので、それらを読み込めば、1回分のループが終わります。ループの先頭に戻ると、DMMのメモリには、数百個の測定データが保存されているので、R?で読み出すことを繰り返します。
import socket #'DISP OFF\n'\ ipAddr = "K-34461A-16054.local" ports = 5025 message = '*RST;*CLS\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'\ 'TRIG:SOURce IMMediate;\n'\ 'TRIG:COUNt INFinity;\n'\ 'TRIG:DEL 0;\n'\ 'FORMat ASCii;\n'\ '*OPC?\n'\ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((ipAddr, ports)) s.send(message.encode()) s1 = b'' if s.recv(8): # 1=ready s.send(b'INIT\n') s.send(b'DATA:POIN?\n') c = s.recv(8) #print(c) cc = (str(c)[:-3])[3:] print('new data is ', cc) m = 'R? ' + str(cc) + '\n' #print('send ', m) s.send(m.encode()) s0 = s.recv(10) #print('received') #print(type(s0),s0) #s1=s1+s0 ss = str(s0)[3:] #print(type(ss),ss) #print('keta ', ss[0]) if ss[0] == '1': #print('1', ss[1:2]) nokori = len(ss[2:]) if ss[0] == '2': #print('2', ss[1:3]) nokori = len(ss[3:]) if ss[0] == '3': #print('3', ss[1:4]) nokori = len(ss[4:]) if ss[0] == '4': #print('4', ss[1:5]) nokori = len(ss[5:]) if ss[0] == '5': #print('5', ss[1:6]) nokori = len(ss[6:]) #print('nokori ', nokori) mojisuu = int(ss[1:int(ss[0])+1]) print('mojisuu is ', mojisuu) mojimax = mojisuu - nokori ss0 = s.recv(mojimax+1) #print(ss0) ss1 = str(ss[int(ss[0])+1:-1]) + str(ss0)[3:-1] sss = ss1.split(',') print(sss) f = [float(f) for f in sss] print(f,len(f))
●連続して読み出す①
while 1: がループ部分です。R? ですぐにデータを読み出すと、要求しているデータ準備できていないことがあるので、time.sleep(0.1) でちょっとだけ待ちます。
import socket import time ipAddr = "K-34461A-16054.local" ports = 5025 message = '*RST;*CLS\n'\ 'CONF:VOLT:DC 10, MAX;\n'\ 'SENS:VOLT:DC:APER 20E-6;\n'\ 'VOLT:DC:NPLC MIN;\n'\ 'VOLT:DC:ZERO:AUTO OFF;\n'\ 'VOLT:DC:NULL:STAT OFF;\n'\ '\n'\ 'TRIG:SOURce IMMediate;\n'\ 'TRIG:COUNt INFinity;\n'\ 'TRIG:DEL 0;\n'\ 'FORMat ASCii;\n' with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((ipAddr, ports)) s.send(message.encode()) s.send(b'*OPC?\n') while s.recv(2): # 1=ready s.send(b'INIT\n') print('init') break while 1: s.send(b'DATA:POIN?\n') c = s.recv(6) cc = (str(c)[:-3])[3:] print('new data is ', cc) m = 'R? ' + cc + '\n' s.send(m.encode()) s0 = s.recv(2) s1 = str(s0)[3:4] # keta s2 = int(s.recv(int(s1)) ) # read data para time.sleep(0.1) # need wait s3 = s.recv(s2 + 1) s4 = str(s3)[2:][:-1] # b' ' deleted #if s4[-1] == 'n': s5 = s4[:-2] # \n deleted sss = s5.split(',') f = [float(f) for f in sss] print(f, '\ntotal ', len(f), 'read') print('-----')
●連続して読み出す②
上記のプログラムを整理したバージョンです。
import socket import time ipAddr = "K-34461A-16054.local" ports = 5025 message = '*RST;*CLS\n'\ 'CONF:VOLT:DC 10, MAX;\n'\ 'SENS:VOLT:DC:APER 20E-6;\n'\ 'VOLT:DC:NPLC MIN;\n'\ 'VOLT:DC:ZERO:AUTO OFF;\n'\ 'VOLT:DC:NULL:STAT OFF;\n'\ '\n'\ 'TRIG:SOURce IMMediate;\n'\ 'TRIG:COUNt INFinity;\n'\ 'TRIG:DEL 0;\n'\ 'FORMat ASCii;\n' with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((ipAddr, ports)) s.send(message.encode()) s.send(b'*OPC?\n') while s.recv(2): # 1=ready s.send(b'INIT\n') print('init') break while 1: s.send(b'DATA:POIN?\n') cc = (str(s.recv(6))[3:-3]) print('new data is ', cc) m = 'R? ' + cc + '\n' s.send(m.encode()) s1 = str(s.recv(2))[3:4] # digit s2 = int(s.recv(int(s1))) # read data count time.sleep(0.1) # need wait s3 = str(s.recv(s2 + 1))[2:-3] # b' \n' deleted s4 = s3.split(',') f = [float(f) for f in s4] print(f, '\ntotal ', len(f), 'read\n-----')
実行中の様子です。DMMには基準電圧ICTL431の出力をつないでいます。20分ほど動かしていましたが、エラーなく動いていました。