Beginner.py

Pythonやその他のメモ

Pythonで測定器制御

オシロスコープやデジタルマルチメータ, 電源, etc.など測定器をPCから制御する場合は、
Excel VBAVisual BASIC/C++などでマクロを作る場合が普通です。
測定器メーカのサンプルプログラム例もあるしGUIも作成しやすく配布も楽です。

なんですがここではあえてPythonを利用した測定器制御について紹介しようと思います。
Pythonを推す理由としてはざっと以下です。

1.対話的な操作ができる。
2.スクリプトで思いつきをささっと試せる。
3.GUI, DB, Web系などもいける
4.測定後(データ収集)⇒解析(Scipy, Numpy)⇒可視化(Matplotlib)と一連の作業が統一してできる。

やり方は単純でPythonのctypesを利用してドライバのDLLから関数呼び出しを行うだけです。
※ctypesはPythonのための外部関数ライブラリで Cと互換性のあるデータ型を提供し動的リンク/共有ライブラリ内の 関数呼び出しを可能にします。
http://docs.python.jp/contrib/ctypes/tutorial_jp.html

今回は例として横河電機オシロスコープDLシリーズをUSB接続する場合を例に説明します。

①事前準備
あらかじめ横河電機のサイトからUSBドライバーを手順に従いインストールしておきます。
測定器とPCを接続しデバイスマネージャーより正しく認識されているか確認します。
http://www.yokogawa.com/jp-ymi/tm/F-SOFT/DLsoft/usb.htm

横河電機のサイトから通信用ライブラリのTMCTL, 操作コマンド表をダウンロードしておきます。
※tmcl.dllの関数を今後利用します
http://www.yokogawa.com/jp-ymi/tm/F-SOFT/DLsoft/tmctl.htm

③測定器の設定
前面操作パネルでI/F設定をUSB選択し, ID番号を設定します。
※ID番号は1とします

Pythonでコマンド送受信 ※付属のC言語サンプルをもとにDLLの関数へアクセスしていきます。

# ctypesモジュールをロード
from ctypes import *
# tmcl.dllをロード
tmcl = windll.LoadLibrary("tmcl.dll")

# USB接続確立と初期化
usb_control = c_int(3)
usb_adress = c_char_p("1")
device_id = c_int()
tmcl.TmcInitialize(usb_control, usb_adress , pointer(device_id))

# コマンド送信 *IDN?
tmcl.TmcSend(device_id, c_char_p("*IDN?"))

# コマンド受信
buf = create_string_buffer("", 1024)
bufsize = c_int(1024)
length = c_int()
tmcl.TmcReceive(device_id, buf, bufsize , pointer(length))

# 受信結果表示
print buf.value

# USB接続切断
tmcl.TmcFinish(device_id)

処理結果

'YOKOGAWA,*****,*,**.**\n'

コマンド送受信ができるようになりました!しかし、これではC言語のまんまで便利に感じれません。。。
そこでコマンド送受信用の簡易クラスを作成してみます。明示的に__del__を定義し接続切断処理を入れます。
※接続OPEN処理した後、必要なくなったらCLOSE処理しないといけませんがうっかり忘れがちになることが多いためです。

from ctypes import *

class TmclObject(object):
    # コンストラクタ
    def __init__(self, adress="1"):
        self.tmcl = windll.LoadLibrary("tmctl.dll")
        self.adrs = c_char_p(adress)
        self.id = c_int()
        self.tmcl.TmcInitialize(c_int(3), self.adrs, pointer(self.id))
    # デストラクタ
    def __del__(self):
        # 接続切断
        self.tmcl.TmcFinish(self.id)
        print "TMCL disconnect"
    # 送信メソッド
    def send(self, msg):
        ret = self.tmcl.TmcSend(self.id, c_char_p(msg))
        return ret
    # 受信メソッド
    def recieve(self, bufSize=1024):
        l = c_int()
        buf = create_string_buffer("", bufSize)
        ret = self.tmcl.TmcReceive(self.id, buf, c_int(bufSize),pointer(l))
        return ret, buf.value

利用例

>>> tmcl = TmclObject()
# コマンド送信
>>> res = tmcl.send("*IDN?")
# コマンド受信
>>> res, value = tmcl.recieve()
# 受信結果表示
>>> print value
'YOKOGAWA,*****,*,**.**\n'
# 終了(インスタンスがゴミになる時に接続切断処理が行われてる)
>>> tmcl = ""
TMCL disconnect

クラスを利用してだいぶすっきりしました。同様に他の種類の測定器についてもクラスを作成しておけば
インタープリタ上で複数の測定器を対話的に操作
・測定器を組合せた測定スクリプトを作成
など結構簡単に作成できます。