せらぴんブログ

サークル「せらぴん」のうのはな透です。やっぱり眼鏡っ娘が好き!!

rubyでシリアル通信するとき、ケーブルが抜けるとどうなるか?

Bye Bye Mooreに倣って技術系の記事をたくさんつけてミントス

ここ最近、Arduinoとサーバを、RasPiを中継機として繋げる作業をしています。
Arduino.Ethernet? 知らんなぁ

RasPi(の上で動くruby製ソフト)とArduinoはUSBケーブルを介してシリアル通信でやりとりしてるんですが、
「このUSBケーブルが抜けちゃうことがあるから、
挿し直した時に復旧できるようにして!
と要望があって調査しました。

結論としては、(私の調べた範囲では)無理っぽいです。

ケーブルが抜けるとどうなるか?

RasPiからはserialport(下記記事参照)で通信しているんですが、
Serialport#writeするときに例外が発生します。

橋本商会 » Rubyでシリアルポートを使う(最新版)

Serialport#readするときは例外は発生しません。原因は不明。

ケーブルを挿し直すとどうなるか?

一旦抜けたUSBケーブルをRasPiにケーブルを挿し直すと、
バイスファイル名が変更されます。

シリアル通信する際はソフトを起動するときは、「このシリアルポートは/dev/ttyACM0ですよー」という風に
バイスファイル名を指定することにより、どのシリアルポートを利用するか指定できます。
WindowsでいうCOMポート番号みたいなもんです)

これが変更されるということは、
もとあったコネクションは存在しないデバイスファイル名を参照することになるので、正常に動作しなくなるわけです。

バイスファイル名を固定すればいいのでは?

ではArduinoごとに固有のデバイスファイル名を設定して利用すればいいのでは?
RasPi(というかLinux)では、USBデバイスに固有のデバイスファイル名を設定することができます。詳細は下記記事参照。

d.hatena.ne.jp

これを設定した上で動作試験してみましたが、結果としてはwrite時の例外が解消されることはありませんでした。

コネクションを再構築すればいいのでは?

これは試してないので断言はできませんが、
コネクションを再構築してもうまく行かないんじゃないかなぁ、と。

というのも、OS上でもシリアル通信が受信できているかは確認できるんですが*1
ソフト起動中にUSBケーブルを抜いてから挿し直した場合、
OS上で確認してもシリアル通信が受信できていない状態なのです。

じゃあ結局どうすればいいの?

RasPiを一旦再起動してからソフトを立ち上げる。
原始的ですが、現段階ではこれが一番早いです。

*1:$ cat /dev/ttyACM0