タイムアウト処理
RS232Cのエラー
この間、装置が暴走してしまった。その原因はまだはっきりしないが、一番状況を説明できるのが、RS232Cの読み取りで止まってしまったという可能性だ。GPIBなどでは、長い間読み取りできないと、タイムアウトエラーになるので、そのエラートラップをかけておけばよいが、RS232Cにはデフォルトではタイムアウトがない。また、パリティーぐらいしかチェックしていないので、通信ミスでうまく命令が伝わらなくても、それに気づかないで、読み取ろうとしていつまでもデータが戻ってこない。そうなると、その部分でずっとプログラムが止まってしまう。
それを防止するために、RS232Cでもtime outができるように、読み込みのmethodをこんなふうにしてみた。
def read() @rs.write(sprintf("L\x0d\x0a")) t=Thread::start{@v=@rs.gets("\x0d\x0a").to_f} t0=Time::now while Time::now < t0+1 return @v unless t.alive? sleep 0.01 end t.kill print "rs232c timeout!\n" @v=-1.0 return @v end
もっとシンプルに書ける気がするが、読み取りはスレッドにまかせて、それが終了していたらその値を返して、それがいつまでも終わらなかったら、スレッドを殺すという感じである。 これで、RS232Cのエラーは無くなるはずだが、これが本当の原因なのかはまだはっきりしないので、他の部分も調べないと。
2008/11/30追記 timeoutのライブラリもあるようで、
require 'timeout' def read() @rs.write(sprintf("L\x0d\x0a")) timeout(1){ return @rs.gets("\x0d\x0a").to_f } rescue TimeoutError return -1.0 end end
てな感じで良いのかも。