TDRのデータをMac OS Xで取り込む方法
譲り受けたちょっと古いTDRの装置(HP54120B(オシロ本体),HP51421T(サンプリングヘッド))を動かすのに、用意されたGPIBインターフェースが、NI社のGPIB-USBやそれ以降の製品だと、Mac OS 9用のドライバが存在しない。このため、現状ではclassic環境でしか動作しないTDRppcで直接データを持ってくることができない。
幸いにして、Igor Proを使うと、OS XからでもNI社のドライバを叩くことができる。
TDRppcは、プログラムとしては後発なので、この分野の「老舗」の東海大学の研究室で使われているデータファイルフォーマットにも対応している。Igor Proで、装置からデータを読み込んで、東海大フォーマットで保存すれば、classic環境でTDRppcを動かし、フーリエ変換して誘電スペクトルを計算することができる。
誘電スペクトルを得た後は、モデルを仮定してフィッティングし、緩和時間を出すといったことが必要になるので、どっちみちIgor Proが大変役立つ状況になる。それならば、計測をIgor Proでやってしまうという解決策も有りだろう。
まあ、TDRppcのCarbon対応をとっととやる、というのが一番正しい解なのだが、なかなか……(汗)。時間稼ぎも必要なので、とりあえず、スクリプトを公開しておく。
装置依存の部分(データ点が500など)を決め打ちで書いてるけれど、若干の変更で、もっと新しい機種でも動作はするはず。HP(現アジレントテクノロジー)は、新しい計測器でも、古い計測器のコマンドが通るように設計してくれているようだ。
#pragma rtGlobals=1 // Use modern global access method. // 東海大学と同じデーターフォーマットで測定結果のファイルを書き出す。 // NI社のGPIBインターフェース利用。 // Mac OS Xで動かす場合は、Igor Pro Folder/Igor Extensionsの中に、Igor Pro Folder/More Extensions/Data Acquisition/NIGPIB2_OSX.xop // をコピーした後、Igorを一旦終了し、再度走らせる。 // Preambleを入れたwaveの内容 // pre[0] format // pre[1] type // pre[2] points データ点(横軸)の数 // pre[3] count 積算回数 // pre[4] xincrement 時間軸の間隔 // pre[5] xorigin // pre[6] xreference // pre[7] yincrement 電圧軸のスケールファクター。ASCII等で読み出した値にこれをかけると電圧の値になる // pre[8] yorigin // pre[9] yreference // pre[10] yrange // インターフェース回りの初期化と、グローバル変数として持ち回る変数の宣言および初期化 Macro InitializeInterface() Variable/G BoadAddr = 0 // パソコン側のGPIBインターフェースのアドレス。通常0とか1とか Variable/G TDRAddr = 7 // 計測器のGPIBインターフェースのアドレス Variable/G DVTDR // 計測器の識別子 String/G cmdstr //コマンドラインで実行する文字列を作る String/G resultstr // 結果を一時的に格納する Variable/G len // 文字列の長さなどの格納用 // Preamble格納用 _sとあるのは標準試料、_xとあるのは未知試料、_dcとあるのはDC補正用試料にそれぞれ対応。 Make/O/N=11 preamble_s Make/O/N=11 preamble_x Make/O/N=11 preamble_dc //Memory1-3を読み出した内容を格納する文字列 String/G s_sample String/G s_dc String/G s_standard //保存前にwaveで受ける // 東海大のフォーマットは歴史的理由で1つの時間領域データが1024点のデータからなる。 // 54120Bを使った場合に有効なデータは、最初の500点のみである。 Make/O/N=1024 w_sample Make/O/N=1024 w_dc Make/O/N=1024 w_standard // インターフェースクリア等 sprintf cmdstr, "NI4882 ibdev={%d,%d,0,13,1,0}", BoadAddr, TDRAddr Execute cmdstr DVTDR = V_flag // 以後はこの数で計測器を特定する。 // ifc sprintf cmdstr, "NI4882 ibclr={DVTDR}" Execute cmdstr End // DC成分が無い場合の測定。 // Memory1に標準試料、Memory2に未知試料のデータをいれておくこと。 // 保存の時にできるファイルは1つ。 Macro Standard_Sample() sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":SYSTEM:HEADER OFF;:EOI ON¥", 26}" Execute cmdstr // memory 1の読み出し sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:SOURCE WMEMORY1;FORMAT ASCII¥", 38}" Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:PREAMBLE?¥", 19}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 256}" Execute cmdstr resultstr = S_Value // Preambleの文字列を得る sprintf cmdstr, "preamble_s = {%s}", resultstr Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:DATA?¥", 15}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 3200}" // 数字5桁にカンマなので1つの数字につき6文字、500点あるので3000で足りるが、多めに読んでみる。 Execute cmdstr s_standard = S_value // 標準試料の測定結果。カンマで区切った整数値。 ReadDataToWave(s_standard, w_standard) w_standard[500,1023] = w_standard[499] // 穴埋め // memory 2の読み出し sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:SOURCE WMEMORY2;FORMAT ASCII¥", 38}" Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:PREAMBLE?¥", 19}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 256}" Execute cmdstr resultstr = S_Value // Preambleの文字列を得る sprintf cmdstr, "preamble_x = {%s}", resultstr Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:DATA?¥", 15}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 3200}" // 数字5桁にカンマなので1つの数字につき6文字、500点あるので3000で足りるが、多めに読んでみる。 Execute cmdstr s_sample = S_value // 未知試料の測定結果。カンマで区切った整数値。 ReadDataToWave(s_sample, w_sample) w_sample[500,1023] = w_sample[499] // 穴埋め // 東海大互換フォーマットでの書き出し // time interval(改行) // スタンダードの電圧軸スケールファクター(改行) // 未知試料の電圧軸スケールファクター(改行) // 1行に8個スペース区切りで、合計1024個(128行)のスタンダードのデータ // 1行に8個スペース区切りで、合計1024個(128行)の未知試料のデータ Variable FileRefNum Variable i Close/A Open/C="????"/T="TEXT" FileRefNum fprintf FileRefNum, "%e¥r¥n", preamble_s[4] fprintf FileRefNum, "%e¥r¥n", preamble_s[7] fprintf FileRefNum, "%e¥r¥n", preamble_x[7] // 標準試料の書き出し i = 0 do fprintf FileRefNum, " %e ", w_standard[i] i += 1 if (mod(i, 8) == 0) fprintf FileRefNum, "¥r¥n" endif while(i < 1024) // 未知試料の書き出し i = 0 do fprintf FileRefNum, " %e ", w_sample[i] i += 1 if (mod(i, 8) == 0) fprintf FileRefNum, "¥r¥n" endif while(i < 1024) Close FileRefNum End // DC成分が有る場合の測定。 // Memory1に標準試料、Memory2にDC補正用試料、Memory3に未知試料のデータをいれておくこと。 // 保存の時にできるファイルは3つ。 Macro Standard_DC_Sample() sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":SYSTEM:HEADER OFF;:EOI ON¥", 26}" Execute cmdstr // memory 1の読み出し sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:SOURCE WMEMORY1;FORMAT ASCII¥", 38}" Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:PREAMBLE?¥", 19}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 256}" Execute cmdstr resultstr = S_Value // Preambleの文字列を得る sprintf cmdstr, "preamble_s = {%s}", resultstr Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:DATA?¥", 15}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 3200}" // 数字5桁にカンマなので1つの数字につき6文字、500点あるので3000で足りるが、多めに読んでみる。 Execute cmdstr s_standard = S_value // 標準試料の測定結果。カンマで区切った整数値。 ReadDataToWave(s_standard, w_standard) w_standard[500,1023] = w_standard[499] // 穴埋め // memory 2の読み出し sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:SOURCE WMEMORY2;FORMAT ASCII¥", 38}" Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:PREAMBLE?¥", 19}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 256}" Execute cmdstr resultstr = S_Value // Preambleの文字列を得る sprintf cmdstr, "preamble_dc = {%s}", resultstr Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:DATA?¥", 15}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 3200}" // 数字5桁にカンマなので1つの数字につき6文字、500点あるので3000で足りるが、多めに読んでみる。 Execute cmdstr s_dc = S_value // 未知試料の測定結果。カンマで区切った整数値。 ReadDataToWave(s_dc, w_dc) w_dc[500,1023] = w_dc[499] // 穴埋め // memory 3の読み出し sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:SOURCE WMEMORY3;FORMAT ASCII¥", 38}" Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:PREAMBLE?¥", 19}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 256}" Execute cmdstr resultstr = S_Value // Preambleの文字列を得る sprintf cmdstr, "preamble_x = {%s}", resultstr Execute cmdstr sprintf cmdstr, "NI4882 ibwrt={DVTDR, ¥":WAVEFORM:DATA?¥", 15}" Execute cmdstr sprintf cmdstr, "NI4882 ibrd={DVTDR, 3200}" // 数字5桁にカンマなので1つの数字につき6文字、500点あるので3000で足りるが、多めに読んでみる。 Execute cmdstr s_sample = S_value // 未知試料の測定結果。カンマで区切った整数値。 ReadDataToWave(s_sample, w_sample) w_sample[500,1023] = w_sample[499] // 穴埋め // 東海大互換フォーマットでの書き出し // time interval(改行) // スタンダードの電圧軸スケールファクター(改行) // 未知試料の電圧軸スケールファクター(改行) // 1行に8個スペース区切りで、合計1024個(128行)のスタンダードのデータ // 1行に8個スペース区切りで、合計1024個(128行)の未知試料のデータ Variable FileRefNum Variable i Close/A // DCなし標準と、DC有り標準の書き出し Open/C="????"/T="TEXT"/M="DCなし標準とDC補正データの保存" FileRefNum fprintf FileRefNum, "%e¥r¥n", preamble_s[4] fprintf FileRefNum, "%e¥r¥n", preamble_s[7] fprintf FileRefNum, "%e¥r¥n", preamble_dc[7] // DCなし標準試料の書き出し i = 0 do fprintf FileRefNum, " %e ", w_standard[i] i += 1 if (mod(i, 8) == 0) fprintf FileRefNum, "¥r¥n" endif while(i < 1024) // DCあり標準試料の書き出し i = 0 do fprintf FileRefNum, " %e ", w_dc[i] i += 1 if (mod(i, 8) == 0) fprintf FileRefNum, "¥r¥n" endif while(i < 1024) Close FileRefNum // DCあり標準試料と、未知試料の書き出し Close/A Open/C="????"/T="TEXT"/M="DC補正データと未知試料の保存" FileRefNum fprintf FileRefNum, "%e¥r¥n", preamble_dc[4] fprintf FileRefNum, "%e¥r¥n", preamble_dc[7] fprintf FileRefNum, "%e¥r¥n", preamble_x[7] // DCあり標準試料の書き出し i = 0 do fprintf FileRefNum, " %e ", w_dc[i] i += 1 if (mod(i, 8) == 0) fprintf FileRefNum, "¥r¥n" endif while(i < 1024) // 未知試料の書き出し i = 0 do fprintf FileRefNum, " %e ", w_sample[i] i += 1 if (mod(i, 8) == 0) fprintf FileRefNum, "¥r¥n" endif while(i < 1024) Close FileRefNum End // 読み出したデータ(カンマ区切り文字列)を、waveに入れる // dstr:文字列 // dwave:読み込み先のwave Function ReadDataToWave(dstr, dwave) String dstr WAVE dwave variable ss, es, i, len, dpos, n_dwave len = strlen(dstr) n_dwave = numpnts(dwave) i = 0 ss=0 do dpos = strsearch(dstr,",",ss) if(dpos == -1) // last dwave[i] = str2num(dstr[es, len-1]) i = i+1 break; endif es = dpos dwave[i] = str2num(dstr[ss, es-1]) ss = es+1 es = es + 1 i = i + 1 while (i < n_dwave) return i End