From: Makoto Tagusari Date: 2000-02-24T00:06:16+09:00 Subject: [ruby-list:20992] GPIB driver その後 ----Next_Part(Thu_Feb_24_00:06:03_2000_518)-- Content-Type: Text/Plain; charset=iso-2022-jp Content-Transfer-Encoding: 7bit 皆さん今晩は、田鎖です。 以前、GPIB モジュールの件で相談させていただきましたが、結局うまい解決法 は見つからず、やばそうなところを GC.disable と GC.enable で囲むことであ る程度解決いたしました。非常に効率の悪い方法ですが、動かないよりましです。 これで安定したかと思えば、例えば # GPIB デバイス にはオシロスコープがつながっています dev = Gpib.new("dev1") cnt = 1 loop do print cnt," " # "curve?" という命令は画面の波形データを転送します。約 5 KByte dev.write("curve?") # とりあえず取り込んだデータはすべて捨てます dev.read cnt += 1 end と言うコマンドを実行すると数十回のループ後セグメンテーションフォルトで落 ちてしまいます。 しかし、機器の動作検証用に irb から呼び出してちょこちょこと書く分には非 常に便利で重宝しています。 Gpib 用のコンソール(?) には、NI のボードの場合 標準で ibic というプログ ラムが付いてくるのですが、これが非常に使いにくいのです。コマンドの編集は できないし、変数が使えないので結果は常にファイルにセーブしなければならな いし。だからといってちょこっとしたプログラムを書くのに LabVIEW みたいな 物は大げさすぎるし。 GUI については、Ruby/Gtk に期待しております。快適な環境を手に入れること ができました。皆さんありがとうございます。 最後に変更したソースをつけておきますので、NI の GPIB ボードを持ってる方 がいらっしゃいましたら、使ってみてください。(NI の GPIB ボードは高いから なかなか使っている人がいないんだよね。) '00.2.23 tag ----Next_Part(Thu_Feb_24_00:06:03_2000_518)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: gpib.rb Content-Disposition: attachment; filename=gpib.rb # NI Gpib library wrapper # require "Win32API" def Gpib(name = "") dev = Gpib.new dev.open(name) if name != "" dev end class Gpib class Error < StandardError end def initialize @devname = "" @dev = -1 @pad = -1 @sad = -1 @tmo = -1 end attr("pad",true) attr("sad",true) attr("tmp",true) def open(devname) @devname = devname r = ibfind(@devname) raise Gpib::Error, error_to_str(thrediberr) if r < 0 r end def write(str) GC.disable ibfind(@devname) ibpad(@pad) if @pad != -1 ibsad(@sad) if @sad != -1 ibtmp(@tmo) if @tmo != -1 stat,cnt = ibwrt(str) if (stat & 0b1000000000000000) > 0 raise Gpib::Error, error_to_str(stat) end GC.enable cnt end def read(cnt=1024) GC.disable ibfind(@devname) ibpad(@pad) if @pad != -1 ibsad(@sad) if @sad != -1 ibtmp(@tmo) if @tmo != -1 buf = "" loop do stat,b = ibrd(cnt) if (stat & 0b1000000000000000) > 0 raise Gpib::Error, error_to_str(stat) end buf << b if (stat & 0b0010000000000000) > 0 # END bit break end end GC.enable buf end def rsp GC.disable ibfind(@devname) ibpad(@pad) if @pad != -1 ibsad(@sad) if @sad != -1 ibtmp(@tmo) if @tmo != -1 stat, rsp = ibrsp if (stat & 0b1000000000000000) > 0 raise Gpib::Error, error_to_str(stat) end GC.enable rsp end # # # def error_to_str(stat) r = [] err_stat = (format "%016b",stat).split(//) err_str = ["ERR","TMO","END","RQS","SRQI",nil,nil,"CMPL","LOK","REN","CIC","ATN","TACS","LACS","DTAS","DCAS"] while err_stat != [] if err_stat.shift == "1" r << err_str.shift else err_str.shift end end "<" + r.join(",") + ">" end def ibfind(name = "dev1") func = Win32API.new("gpib-32","ibfind",["P"],"L") @dev = func.call(name) end def ibwrt(str) func = Win32API.new("gpib-32","ibwrt",["L","P","L"],"L") stat = func.call(@dev,str,str.size) cnt = thredibcntl [stat,cnt] end def ibrd(size = 1024) buf = "\000" * size func = Win32API.new("gpib-32","ibrd",["L","P","L"],"L") stat = func.call(@dev,buf,size) cnt = thredibcntl [stat,buf[0,cnt]] end def thredibcntl func = Win32API.new("gpib-32","ThreadIbcntl",[],"L") func.call end def thrediberr func = Win32API.new("gpib-32","ThreadIberr",[],"L") func.call end def ibrsp rsp = "\0" func = Win32API.new("gpib-32","ibrsp",["L","P"],"L") stat = func.call(@dev,rsp) [stat, rsp.unpack("c")[0]] end def ibpad(pad) func = Win32API.new("gpib-32","ibpad",["L","L"],"L") func.call(@dev,pad) end def ibsad(sad) func = Win32API.new("gpib-32","ibsad",["L","L"],"L") func.call(@dev,sad) end def ibtmo(tmo) func = Win32API.new("gpib-32","ibtmo",["L","L"],"L") func.call(@dev,tmo) end end if __FILE__ == $0 dev = Gpib("dev1") dev.write("*idn?") print dev.read STDOUT.flush cnt = 1 loop do print cnt," " STDOUT.flush dev.write("curve?") dev.read 3000 cnt += 1 sleep (2) end end ----Next_Part(Thu_Feb_24_00:06:03_2000_518)----