はじめに
ADVANTEST R6452Aを使っていたのですが、「アナログで高精度なサーモスタットを安価で作成したかった」やリチウムイオン電池の放電試験でデータロガー的な使い方をしたかったのでRS-232Cでの通信を試してみることにしました。
ADVANTESTの同時期のデジタルマルチメータ、R6451A、R6452A、R6441A、R6441B、R6441C、R6441Dでも使えるはずです。
デジタルマルチメータ側の設定
ディフォルトだと対話モードになっているのでトークオンリモードにします。トークオンリモードだと、自動的に現在表示されている値を出力してくれます。また、計測モードを示すヘッダ出力もOFFにします。詳しくは取扱説明書を読んでほしいのですが、一応下で説明します。
I/Fを押して、SCI(RS-232Cの意味)がonになっていることを確認し、SHIFTを押すとH_ SCIと表示されます。H_はヘッダーあり対話モードの意味で、Hoにすると、ヘッダーありのトークオンリモードになります。点滅して(選択されて)いるHをAUTOボタンで_が点滅する状態にし、DOWNかUPを押してHoにします。あとは、SHIFTを連打していれば下の画面に戻ります。
コード
LinuxとPythonの組み合わせでやってみました。
# please setting talkonly mode with header
import serial
import datetime
import time
import sys
args = sys.argv
noheader = False
if len(args) == 1:
print("Select Port", file=sys.stderr)
print("ex. python3 R644x5xTALKONLY.py /dev/ttyUSB0", file=sys.stderr)
exit()
if len(args) == 3:
if args[2] == 'noheader':
noheader = True
port = args[1]
baud_rate = 9600
def extract_value(response):
return response[3:]
def extract_header(response):
return response[:3]
def split_data(response):
return [item.strip() for item in response.split(',')]
# init
try:
ser = serial.Serial(port, baud_rate, timeout=1)
except serial.SerialException:
print("fail to open Serial port", file=sys.stderr)
exit()
# print data
try:
header = ''
double = False
while ser.in_waiting < 1:
time.sleep(0.01)
data = ser.readline().decode().strip()
double = False
spdata = split_data(data)
if len(spdata) == 1:
header = extract_header(spdata[0])
if noheader == False:
print(f"day,hour,minute,second,msec,{header}")
elif len(spdata) == 2:
header = [extract_header(spdata[0]), extract_header(spdata[1])]
double = True
if noheader == False:
print(f"day,hour,minute,second,msec,{header[0]},{header[1]}")
else:
print(data, file=sys.stderr)
print("invalid header", file=sys.stderr)
while True:
if ser.in_waiting > 0:
data = ser.readline().decode().strip() # read serial
timestamp = datetime.datetime.now().strftime('%d,%H,%M,%S,%f')[:-3] # timestamp
spdata = split_data(data)
if double:
if header != [extract_header(spdata[0]), extract_header(spdata[1])]:
print("header was changed", file=sys.stderr)
break
print(f"{timestamp},{extract_value(spdata[0])},{extract_value(spdata[1])}")
else:
if header != extract_header(spdata[0]):
print("header was changed", file=sys.stderr)
break
print(f"{timestamp},{extract_value(spdata[0])}")
except KeyboardInterrupt:
print()
finally:
ser.close()
使い方
RS-232Cが/dev/ttyUSB0でhoge.csvに出力したい場合は以下のコマンです。
sudo python3 -u R6441x5xA_TALKONLY.py /dev/ttyUSB0 | tee hoge.csv
先程のコードにはファイルに保存する機能までは含まれていません。そのため、teeを使ってファイルに流し込んでます。エラーは標準エラー出力に出るようになっているので保存されません。uオプションを付けないと、標準出力がバッファリングされてしまい、表示されなくなってしまいます。iret.media「Python スクリプトの標準出力をパイプでつなぐ時に気をつけたいこと」
出力は、
day,hour,minute,second,msec,DI
15,03,28,11,216,+00.0008E+0
15,03,28,11,616,+00.0006E+0
15,03,28,12,017,+00.0007E+0
︙
R6452やR6451で2ch使用した場合は、
day,hour,minute,second,msec,DV ,DV
15,02,51,24,717,+00.0040E+0,+00.0009E+0
15,02,51,25,532,+00.0030E+0,-00.0020E+0
15,02,51,26,346,-00.0003E+0,+00.0043E+0
︙
のように、はじめの1行に各列の説明が入り、その先はタイムスタンプとともに出力されます。ヘッダですが、取扱説明書によると以下の通りだそうです。
ctrl+cで終了できます。また、測定モードが変わって、受信したヘッダが変化すると自動で終了します。
Excelでの処理
タイムスタンプを計測開始からの秒に変換したいときは、
=24*60*60*(A2-$A$2)+60*60*(B2-$B$2)+60*(C2-$C$2)+(D2-$D$2)+(E2-$E$2)/1000
を貼り付けて、下に引っ張ればいいです。
ボツ
トークオンリーモードでなく、対話モードでも作ったりしてました。MD?というコマンドを送ると計測値の返答が帰ってきます。しかしながら、1秒ごとに正確に取得するのが少し面倒だったり、2ch使っていると、たまにコマンドが認識されなくなったりと、面倒だったのでやめました。
「アナログで高精度なサーモスタットを安価で作成したかった」のグラフの取得はこれでやってたりします。
おわりに
これでデジマルをデータロガー的な使い方ができるようになりました。リチウムイオン電池の放電試験に使用できます。httpで動作するスイッチと組み合わせて規定電圧以下になったら自動で放電を中止するとかもできそうです。