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
DATA:POINts?          現在までに読み取ったデータ数の確認

                 数字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分ほど動かしていましたが、エラーなく動いていました。