National Instruments社(NI)のGPIBインターフェースボードをIgorProから使う方法について簡単に説明する。私(の関連研究室)ではNI社製のボードを所有していないが、1998年の秋にPCI-GPIBを借りて接続テストをしたので、その手順について述べる。実行環境は、PowerMacintosh7600/132、Mac OS J1-8.1、NI-488.2である。
NI社はこれからもMac用の計測ボード(GPIB,AD/DAなど)を販売・サポートしていくということなので、これからMacを使って計測を始める人はNI社に問い合わせること。
USAのNI本社から、最新版のNI-488.2とpdfファイルのマニュアルをダウンロードできる。購入すればもちろんドライバもマニュアルも付属している。NI-488.2 Installerを実行すると、NI-488.2フォルダができて、この中にテストプログラムやC言語用のインターフェースが入っている。システムフォルダの中の機能拡張フォルダには、NI-488 INITとNI-DMA/DSPがインストールされる(ここが自動で入ったか手動でコピーしたか忘れた)。この2つがドライバである。
ドライバのインストール後、ボードが正常に動いているかどうか、ちゃんと接続されているかどうかなどを付属のツールを使って確認する。方法はマニュアルに書いてあるので、まずこれをやる必要がある。
C言語とのインターフェースルーチンは、68KMac用のはNI-488.2フォルダの中のCLIフォルダの中のMacGPIB68k(CodeWarrior).libであり、CodeWarriorのプロジェクトファイルにサンプルプログラムとこのライブラリを追加してコンパイル&リンクすれば測定プログラムを作ることができる。PPCMac用は共有ライブラリとして提供されており、機能拡張フォルダの中のMacGPIB.shlbをプロジェクトファイルに加えてコンパイル&リンクすることになる。MacGPIB.shlbは機能拡張フォルダに置いてもよいし、自分のアプリケーションと同じフォルダに置いても動作する。最初、これを理解していなくて技術サポートに電話して手をわずらわせてしまった。
NI-488.2の場合は、IgorProとのインターフェースを行うXOPが最初からIgorProに含まれているので、わざわざ開発する必要はない(GW Instrumentsのときは無かったから自作した)。
ファイルへのパスは、Igor Pro Folder:More Extensions:Data Acquisition:NIGPIBである。これのエイリアスを作って、Igor Pro Folder:Igor Extensionsに入れてIgorProを起動すると、NIのボードと通信するコマンドが使えるようになる。あとは、個々の計測器のマニュアルを見て命令を調べ、NIGPIBのマニュアルの通りにプロシージャを書いて実行するだけである。
NI社は、LabViewという計測ソフトウェアを販売しており、RADツールのような操作で計測プログラムを作ることができる。グラフィカルに計測の機能を矢印で結んでいくだけでプログラムが作れるようである。計測器を多量に抱えているような会社のサポート部門では、頻繁に処理を変えることになった場合に迅速に対応できるので、LabViewを利用するとよい。大学の研究室でも、academic discountで最近は安く入手できるようなので、利用を検討してもよいと思う。
計測後の解析が複雑な場合は、IgorProの出番となるだろう。直接waveにデータを取り込んで、あとはIgorProの強力な解析機能を使って好きなようにデータを料理できる。また、IgorProのレイアウトは直接印刷可能な品質なので、そのまま投稿論文の図を作ったりすることもできて便利である。IgorProのプロシージャはプログラムの初心者でも習得が容易である。
NIGPIBを使って、実際に計測器とデータのやりとりをしている例を以下に示す。TDR測定用のHP社のデジタイジングオシロ5412*T用のものである。ドライバ側のデリミタの設定はCR+LFにしている。オシロのGPIBアドレスは6である。ドライバ側はGPIBボードを1つだけ入れて使うという環境にあわせて設定している。
doReadHP()は、オシロのメモリ1のデータのプリアンブル(縦横の軸のスケールやデータ点数やデータの積算回数など)を文字列に読み込むというものである。doReadHP2()は、HP社の定義したデータのヘッダを解析して、データがどれだけのサイズか求めた後測定データを読み込んで、続いて対応するプリアンブルを読み込むものである。StrToNWave(w, s)とNWaveToStr(w)は、文字列とwave(数値)の間の変換をする関数である。
#pragma rtGlobals=1 // Use modern global access method.
// HP oscilloscope address is 6
// get preamble and memory 1
Macro doReadHP()
Make/O/N=4096/W data
Make/B/U/O buf
Variable DABend = 0x02 // Means assert EOI with last output byte.
Variable STOPend = 0x100 // Means stop receiving when EOI is asserted.
String preamble
Variable/G gBoardAddress = 0, gDeviceAddress = 6
Variable/G gBoardUnitDescriptor=0, gDeviceUnitDescriptor=6
// Find the unit descriptors.
NI488 ibfind "gpib0", gBoardUnitDescriptor
NI488 ibfind "dev1", gDeviceUnitDescriptor
// Set active board and device for high-level GPIB operations.
GPIB board gBoardUnitDescriptor // Board to use for GPIB InterfaceClear command.
GPIB device gDeviceUnitDescriptor // Device to use for GPIBXXX operations.
GPIB KillIO
GPIB InterfaceClear
GPIBWrite/F=":SYSTEM:HEADER OFF;:EOI ON\r\n"
GPIBWrite/F=":WAVEFORM:SOURCE WMEMORY1;FORMAT WORD\r\n"
GPIBWrite/F=":WAVEFORM:PREAMBLE?\r\n"
GPIBRead /T="\r\n"/N=128/, preamble
NI488 ibonl 0,0
End
Macro doReadHP2()
Make/W/O/N=4096 data // signed word
Make/B/U/O/n=128 buf // unsigned byte
Variable DABend = 0x02 // Means assert EOI with last output byte.
Variable STOPend = 0x100 // Means stop receiving when EOI is asserted.
String/G preamble
Variable len, l_size, blocksize,points
NI488 SendIFC 0
NI488 DevClear 0, 6
buf = 0
len = StrToNWave(buf, ":SYSTEM:HEADER OFF;:EOI ON")
NI488 Send 0, 6, buf, len, DABend
buf=0
len = StrToNWave(buf, ":WAVEFORM:SOURCE WMEMORY1;FORMAT WORD")
NI488 Send 0, 6, buf, len, DABend
buf=0
len = StrToNWave(buf, ":WAVEFORM:PREAMBLE?")
NI488 Send 0, 6, buf, len, DABend
buf=0
NI488 Receive 0, 6, buf, 128, STOPend
preamble = NWaveToStr(buf)
buf=0
len = StrToNWave(buf, ":WAVEFORM:DATA?")
NI488 Send 0, 6, buf, len, DABend
buf=0
NI488 Receive 0, 6, buf, 1, STOPend // skip '#'
buf=0
NI488 Receive 0, 6, buf, 1, STOPend // read blocksize region
l_size = str2num(NWaveToStr(buf))
buf=0
NI488 Receive 0, 6, buf, l_size, STOPend // read blocksize
blocksize = str2num(NWaveToStr(buf))
points = blocksize/2 // Word is 2 byte.
if(points > numpnts(data)) // check the size of data area
Redimension/N=points data
endif
data=0
NI488 Receive 0, 6, data, blocksize, STOPend // read blocksize
// close
NI488 ibonl 0,0
End
Function StrToNWave(w, s)
Wave w
String s
Variable len=strlen(s), n=numpnts(w),i
if(s > w)
printf "wave is too short\r"
return -1
endif
i=0
do
w[i] = char2num(s[i])
i = i + 1
while(i < len)
return i
End
Function/S NWaveToStr(w)
Wave w
Variable n=numpnts(w),i
String str=""
i=0
do
if(w[i] == 0)
break
endif
str[i]=num2char(w[i])
i = i + 1
while(i < n)
return str
End
この例ではwaveにデータを読み込むだけだが、IgorProの機能を使って、データを表示しながら計測するプログラムを作ることもできる。IgorProについてくるexampleを見て、それぞれの環境にあったプログラムを作っていただきたい。