#author("2020-11-20T14:45:26+09:00","default:LabMember","LabMember")
[[コンピュータ関連>ComputerRelated]]

* Pythonでネットワーク経由のGPIB機器制御 [#i206168c]

#contents

** Introduction [#j8762587]
*** ネットワークとGPIB [#n49f901e]
GPIBは多くの計測器機に内蔵されている、汎用の制御バスである。GPIBを通じてコマンドを送ることで、リモートから測定を開始したり、得られたデータをダウンロードしたりできる。
従来、PCからGPIB機器を制御する場合、PC用のGPIBボードやUSB-GPIB変換ボックスを用いていた。しかしこの方法では、PCと計測器機が物理的に近接している必要がある(GPIBケーブルの長さ程度)。また、GPIBボードやボックスのドライバが使用するOS用に提供されていなければならない。これはLinuxのようなOSを使う際、不利な条件である。そこで、このページでは[[Prologix社>http://prologix.biz/index.php]]製の[[GPIB-LAN変換Box>http://store.prologix.biz/gpiblan-controller.html]]を用いて、TCP/IPネットワーク経由でGPIB機器を制御する方法について述べる。

この方法では、ネットワーク経由なので、制御PCと制御対象機器が物理的に近い必要はない。Ethernet-無線LAN変換器を使えば、測定器にネットワークケーブルが刺さっている必要すら無く、実験室内を自由に移動させられる。さらに、単なるTCP/IPなので、特別なドライバーが無くても、TCP/IPが使えるOSならば何でも使える。

*** Python [#ub407eea]
この方法でGPIB機器を制御するには、TCP/IP通信を行う必要がある。もっとも簡単な方法は、telnetを利用する方法であり、直接GPIBコマンドを送信することができる。もう少し複雑な制御を行ったり、大量のデータを受信したりする場合はプログラムを組む必要がある。TCP/IP通信ができればいいので、ほぼどのようなプログラミング言語を用いても問題ないが、このページでは、Pythonを利用した例を説明する。

Pythonを利用する理由は、(1)スクリプト言語であり、手軽に使える、(2)オブジェクト指向なので、見通しが良く、再利用性の高いコードが書ける、(3) [[ここ>PythonForScience]]で解説されているように、科学技術計算向けの拡張モジュールが充実しており、ダウンロードしたデータをすぐに加工したりプロットしたりできる、等である。Pythonは対話的な利用にも優れているため、Matlab的な使い方ができる。従って、Python上からGPIB機器が制御できれば、測定、データダウンロード、解析、プロットまでが一つの環境で行えることになる。

** GPIB-Ethernet Converterの設定 [#v2f239fb]
Prologix製、GPIB-Ethernet Converter(以下GPIB Boxと呼ぶ)は、GPIBポートとEthernetポートを備えている。EthernetポートからTCP/IPの1234番ポートにアクセスすると、GPIB Boxに接続できる。
GPIB BoxのIPアドレスは、NetFinderというソフトで設定をする([[http://prologix.biz/resources.php]]からダウンロード可能)。このソフトはWindows用なので、IPの設定時にはWindowsが必要となる。~
(坪野研のGPIB BoxはすでにIPアドレスが設定済みである。本体にIPアドレスを示すラベルが貼ってあるので、それを参照すること。)

IPアドレスを設定したら、GPIB Boxを制御したいGPIB機器に接続する。GPIBケーブルを使ってディジーチェーンすることも可能である。

*** 基本コマンド [#f83b90d4]
GPIB-Boxは、TCP/IPで送られてくるアスキー文字列のうち、++で始まらないものはそのままGPIB機器に転送する。++で始まるものは、GPIB Boxに対するコマンドとして解釈される。
ここでは、GPIB Boxに対する基本的なコマンドを説明する。詳しくはマニュアル(&ref(PrologixGpibEthernetManual-1.pdf);)を参照。

- ++addr [number]: 通信相手のGPIBアドレスを指定する。例えば、++addr 10 とすれば、以後GPIBアドレス10番の機器と通信を行う。数字を指定しなければ、現在のGPIBアドレスが返される。

- ++auto [0|1]: Auto modeをON/OFFする。Automodeでは、コマンド送信後、自動的に相手のGPIB機器をTalkモードにし、その出力を読み込む。

- ++read : GPIB経由でデータを読み込む。

** Pythonでのアクセス [#z8896f54]
PythonからGPIB Boxにアクセスするためのクラスを実装した。このクラスを使えば、PythonからGPIB Box経由で簡単にGPIB機器を制御できる。

*** インストール [#saae78f5]
&ref(netgpibdata.zip);をダウンロードし、展開してできたディレクトリを適当な場所に置く。~
環境変数PYTHONPATHに、上記ディレクトリを追加する。これで、Pythonからnetgpibモジュールが読み込み可能になる。~
簡単なテストのためには、展開してできたディレクトリの中からpythonを起動すれば良い。

[[インストールの詳細>PythonGPIBInstall]]
*** netGPIBクラスの使用方法 [#vbfa3143]
GPIB Boxにアクセスするには、netgpibモジュールを読み込む。

 import netgpib

次に、GPIB Boxに接続する。
 dev=netgpib.netGPIB('192.168.2.3',10)
この例では、IPアドレス192.168.2.3のGPIB Boxに接続された、GPIBアドレス10番の機器と通信を開始する。devは、netGPIBクラスのインスタンスで、このオブジェクトを通して、GPIB機器との通信を行う。

GPIBコマンドを送信するには、
 dev.command('GPIBCOMM')
というように、commandメソッドを用いる。'GPIBCOMM'の部分をGPIBコマンドの文字列で置き換える。commandメソッドは、答えが返ってこないタイプのコマンドを送るのに使う。従って、コマンド送信後にGPIB機器はTALKモードに設定されない。もし、答えが返ってくる(Queryタイプの)コマンドをcommandメソッドで送った場合、以後の動作がおかしくなることがある。

何らかのデータが返されるようなコマンド(query)を送信するには、
 answer=dev.query('GPIBQ',100)
とする。最初の引数は、GPIBコマンド文字列である。二番目の100という引数は、バッファサイズを指定する。デフォルトは100バイトである。ここにはGPIB機器から返されるデータを充分格納できるだけのサイズを指定しなければならない。受け取ったデータは、answerに代入される。

GPIB機器との通信を終了するには、
 dev.close()
を実行する。

*** R9211クラス [#h000ecde]
netgpibdata.zipにはR9211というモジュールが含まれる。このモジュールは、AdvantestのサーボアナライザーR9211シリーズと、GPIB Boxを介して通信するためのクラスが含まれる。
(このクラスを利用するには、numpyモジュールが必要である。)

使用方法は以下のとおり。
 import R9211
とした上で、
 dev=R9211.R9211('192.168.2.3',8)
のように、接続を開く。最初の引数はIPアドレスで、次にGPIBアドレスを指定する点は、netGPIBクラスと同様である。

R9211クラスでは、netGPIBと同様に、command()やquery()メソッドが利用できる。
また、データを指定されたディスプレイからダウンロードするメソッドとして、getdata()というものが使える。
 (data,hdr)=dev.getdata(disp=[1,2],verbose=1)
この例では、ディスプレイ番号1番と2番から、データをダウンロードする。verbose=1オプションを付けると、ダウンロードの進捗状況が表示される。dataは指定したディスプレイの
数と同じサイズを持つリストである。各要素は、(x,y)というTupleになっており、x,yはnumpy arrayである。x,y等の単位は、hdrに代入される。

現在のR9211の設定を取得したい場合は、
 (cparams,dparams)=dev.getparams(disp=[1,2], verbose=1)
とする。cparamsとdparamsは、どちらも設定パラメータ値が入った辞書である。cparamsには、ディスプレイに依らない共通の設定値が入り、dparamsにはディスプレイ毎の設定値が入る。

取得したデータやパラメータをファイルに保存したい場合は、
 mcol = dev.saveData('dataFileName.dat',data)
 dev.saveParam('paramFileName.par',cparams, dparams, hdr, mcol, disp=[1,2])
というようにする。mcolは、データファイルがmulti columnで保存されたかどうかを示すフラグで、True or Falseである。これは、saveData()メソッドの戻り値である。
saveData()は、もしdataの各ディスプレイが同じ長さのデータを持っているときは、multi-column形式でテキストファイルに書き出す(各行に、全てのディスプレイのデータがx-data,y-dataの順番で並んでいる)。ディスプレイ間でデータ長が違う場合、このような形式では書き出せないので、x,y二列のデータを、ディスプレイ毎に順番に書き出していく(mcol=False)。

R9211では、startというGPIBコマンドを送ると、測定が始まる。測定中であるかどうかを調べるには、isAveraging()メソッドを使う。このメソッドの戻り値がTrueであれば、測定中である。測定終了まで待つには、waitAvg()メソッドを使う。
 dev.command('start') #Start averaging
 dev.isAveraging()  #Ask if it is still averaging
 dev.waitAvg()  #Wait until the averaging is complete

R9211との接続を終了するには、
 dev.close()
を実行する。

*** dlR9211.pyスクリプト [#d537c19d]
R9211からデータのダウンロードとセーブを一気に行うためのスクリプトが、dlR9211.pyである。これは、独立したpythonスクリプトなので、例えばターミナルから次のように使う。
 python dlR9211.py --ip 192.168.2.3 -a 8 -f filename -d 1,2 
この例では、IPアドレス192.168.2.3, GPIBアドレス8番のR9211から、ディスプレイ1と2の内容をダウンロードし、filename.datにデータを、filename.parにパラメータをセーブする。
 python dlR9211.py --ip 192.168.2.3 -a 8 -f filename -d 1,2 --plot
というように、--plotオプションを付けると、ダウンロードしたデータをプロットする。ただし、この機能を使うには、matplotlibが必要である。

その他のオプションについては、
 python dlR9211.py --help
とすれば説明が表示される。

*** その他のGPIB機器 [#db1d9f40]
- SR785: LIGO等で使われている、Stanford Research SystemsのSR785サーボアナライザ。データをダウンロードするには、netgpibdata.pyコマンドに、-d SR785 オプションを付けて起動する。また、TFSR785.py, SPSR785.py, TSSR785.pyを利用することで、伝達関数、スペクトル、時系列測定がそれぞれ行える。詳細はそれぞれのコマンドに--helpオプションを付けて表示されるヘルプ参照。

- Agilent 4395A: Agilent製のネットワークアナライザ。このアナライザからデータをダウンロードするには、netgpibdata.pyコマンドに、-d SR785オプションを付ける。

** python3へ移植 [#b9d79221]
netgpib.pyのみpython3へ移植した.基本的には
- python2型の構文をpython3型へ
-- print "hoge" → print("hope") など
-python2では文字列がバイトだがpython3ではstrなので,送受信される文字列周りの構文を直す
-- send("foo") → send("foo".encode())
といった修正をした.修正したファイルはここ&ref(netgpib.py);
- [[netgpib.py>>]]

** TO DO [#efaee214]
*** R9211の自動測定スクリプト [#b6a75282]
SR785の場合のように、伝達関数やスペクトルの測定を簡単に行えるスクリプトを書いておくと、繰り返し測定する時等に便利。

*** 小野測器CF-5220Z [#aca49201]
坪野研にあるCF-5220ZにもGPIBポートが付いているので、リモートからデータの吸い出しが可能なはず。誰かがGPIBマニュアルを読んで、CF5220Zクラスを書くべし。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS