ただコマンドラインで順繰りにプログラムを動かすのでは21世紀っぽくないなぁ,と思い,思い切ってGUIで操作できるようにすることにしました.
そこで,練習のためにGtkをつかって,(でもmain関数がバカでかい)接続したデバイスのIDをGPIB経由でとってきて,画面上に表示させるプログラムをちょちょいと書いてみました.
(Gtkでは全然21世紀っぽくもないのですが...)
(Gtkでは全然21世紀っぽくもないのですが...)
つないであるデバイスは今のところ三つなのでボタン三つ.
構成は,メニューバー,ラベル1,三つボタンの入ったhbox,ラベル2をvboxに入れて,ボタンをクリックすると各装置に"*idn?"をなげ,帰ってきたテキストをラベル2に"g_signal_connect_swapped"をつかって反映させる,というだけのものです.
ボタンのソースコードは,
button1 = gtk_button_new_with_label ("TR6861");
gtk_widget_set_size_request (button1, BTN_WIDTH, BTN_HEIGHT);
gtk_container_add (GTK_CONTAINER (hbox), button1);
gtk_signal_connect (GTK_OBJECT (button1), "clicked", G_CALLBACK (TR6861read), NULL);
g_signal_connect_swapped (GTK_OBJECT (button1), "clicked", G_CALLBACK (cb_label), (gpointer) label2);
gtk_container_set_border_width (GTK_CONTAINER (button1), 5);
button1をクリックしたときに,gtk_signal_connectで一つ目のコールバック関数を呼び出し,この関数の中で測定器からIDNをとってきてBufferに入れ,その次の行でg_signal_connect_swappedでlabel2の内容をBufferで書き換えるコールバック関数を呼び出しています.
ここで問題は,一つ目のGPIB通信に時間がかかってしまった場合,すぐに下の行のg_signal_connect_swappedでラベルを書き換えるコールバック関数が呼ばれてしまうと,Bufferに測定器からの読み取り値が代入される前に古いBufferの値でlabel2を書き換えてしまうのではないかという心配です.
そこで,わざとgtk_signal_connect で呼び出しているコールバック関数の中にsleep行を入れてみて,どんなに待っても逐次的に処理されるかを試したところ,しっかり待ってからg_signal_connect_swappedのコールバック関数を実行していたので,問題はありませんでした.
GPIBで測定するところは,
static void Agilent34420Aread (){
PrimaryAddress = 22;
Device = ibdev(
BoadIndex,
PrimaryAddress,
SecondaryAddress,
T10s,
1,
0
);
ibwrt (Device, "*IDN?\n", 5);
ibrd (Device, Buffer, 100);
Buffer[ibcntl] = '\0';
ibloc(Device);
// sleep(1);
}
こんな感じでエラー処理とか細かいことは一切していないのですが,本番はきちんとエラーが出たときに処理して標準出力にいろいろ吐くようにします.
ここで問題は,一つ目のGPIB通信に時間がかかってしまった場合,すぐに下の行のg_signal_connect_swappedでラベルを書き換えるコールバック関数が呼ばれてしまうと,Bufferに測定器からの読み取り値が代入される前に古いBufferの値でlabel2を書き換えてしまうのではないかという心配です.
そこで,わざとgtk_signal_connect で呼び出しているコールバック関数の中にsleep行を入れてみて,どんなに待っても逐次的に処理されるかを試したところ,しっかり待ってからg_signal_connect_swappedのコールバック関数を実行していたので,問題はありませんでした.
GPIBで測定するところは,
static void Agilent34420Aread (){
PrimaryAddress = 22;
Device = ibdev(
BoadIndex,
PrimaryAddress,
SecondaryAddress,
T10s,
1,
0
);
ibwrt (Device, "*IDN?\n", 5);
ibrd (Device, Buffer, 100);
Buffer[ibcntl] = '\0';
ibloc(Device);
// sleep(1);
}
こんな感じでエラー処理とか細かいことは一切していないのですが,本番はきちんとエラーが出たときに処理して標準出力にいろいろ吐くようにします.
メニューバーにはFile > Quitのシンプルなメニューしかありません.
ちなみに,プログラムはウインドウのクローズボックスをクリックしても,メニューで終了を選んでもどちらでも終了できるようにしてあります.
この程度に半日近くかかってしまった.
作業はすべて,自室のMacからssh -Xで実験室につないで行っているので,画像でもmacっぽく見えていますが,実際はLinux上で動いています.
0 件のコメント:
コメントを投稿