タイムアウト処理
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
てな感じで良いのかも。