jippiniusの自然科学研究

ジッピニウスの自然科学や技術関連についての備忘録です。

USB接続の測定器制御を目指す:(8) シリアル通信のプログラミング、そしてついに完成!

シリアル通信でDoseRAE2とLinuxがデータ交換していることが前回までに判明した。いよいよ、自分自身でこのデータを処理するプログラムを書く段階となった。しかし、libusbではシリアルポートを操作する関数はなく、新たに別の手法を探らねばならない。そこで、検索を重ねると、DoseRAE2の操作プログラミングを扱った例のネット記事を参考にして、シリアルポートを利用するプログラムを公開している記事を発見した。

この記事ではperlを用いたプログロミングを採用していた。実は我輩はperlもよく知らないのである。そこで、perlの基本から調べることになった。

perlスクリプト言語で、非常に直感的なプログラミングが可能であることから、人気が高く、特にnetworkのCGIなどでよく利用されている。台湾の唐鳳(Audrey Tang)氏は若い頃perlにはまってIT業界に入ったという話を聞いたこともある。彼女は現在もPerlの開発者グループの中心メンバーでもあるらしい。また文の表現は、C言語によく似ていてそれも人気の理由らしい。

perlのみならず、このプログラムはFreeBSDUnixに対して書かれていて、インターフェースの部分が若干Linuxと異なっている点も注意である。ただ、ここまでの調査で、Ubuntuではシリアルポートが/dev/ttyUSBxxと表現されることを知っているので、対応する部分を書き換えるだけでいいはずだ。

さて、プログラムの初めに

use Device::SerialPort;

という一文が出てきた。これはperlの特徴である拡張クラス(package module)を引用するという意味らしい。調べると、SerialPort.pmというpmが出てきて、これをインストールする必要があるらしい。

Device::SerialPortの使い方は、「非常に」簡単なものがこちらにある(これを読み解くの一苦労だが、最後の方にexampleがあるので、これを読んである程度理解することが可能)。

導入の仕方はこちらを参考にした。どうも、perl自身はCで書かれているらしく、cpanから対応するソースコードをダウンドロードしたものをmakeでコンパイルし、make installでインストールするようだ。(ソースファイルをみると、termios.hが利用されていて、これが最終的な問題解決の鍵となることが後でわかった。) また、SerialPortの例題もたくさんソースコードと一緒に提供されていて、真剣にperlを勉強するときは、このプログラムを読めば良いこともわかった。こうして、SerialPort.pmクラスの導入は無事に終わった。(関連するページを見ていると、このmoduleはもともとはモデムを操作するためのものであることがわかった。)

root権限に気をつけつつ、プログラムを書き、実行する。エラーは出ないが、通信待ち状態が続き、5秒間隔でデータが表示されない....おそらく、まだUbuntuに対応できていない部分があるのであろう。まあ、しかし、エラーが出ないだけでもマシである。そもそもperlで書かれているので、詳細を短時間で解析するのは我輩には難しいのは端からわかっていたことだ。

perlでできることであれば、C言語でもできるはずだ(そもそもperlC言語で書かれているプログラムだから)。そこで、DoseRAE2に対する直接的なプログラミングの解説を探さなくても、シリアルポートを使う機器に対するCのプログラミング例は巷に溢れているはずだから、それを検索してしまおう、という発想に転換するすることにした。

そうして見つけたのが、こちらのホームページである。予想通り、C言語に付帯するtermios.hで規定された関数を使ってアクセスするようである。このページではUbuntu系列のLInuxを対象としているようで、シリアルポートの名前が同じ(/dev/ttyUSB0)であった。しかも、対象とする測定機器(センサーによって温度や振動を測定し、その結果を無線で受信し、最後はシリアル通信でPCに送信するという機械, 残念ながら現在製造中止)は、DoseRAE2と同じ「CP2101」を利用しているらしいから、なおのこと親和性が高い。

必要な部分を切り取り、プログラムを書いてみた。コンパイルし、実行!するとついに、DoseRAE2からのデータを捉えることに成功したのである。

生のデータでは、gtktermとまったく同じである。全部でデータ長(ストリーム長)は35バイトで、始まりは7B, 終わりは7Dである。放射線の強さのデータ部分は28バイト目から31バイト目までの4桁を利用していて、単位は0.01μSv/hであるから、\(16^4\times 0.01=655.36\text{μSv/h}=0.65536\text{ mSv/h}\)まで測ることができる。空間線量を測定するなら、まあ十分なレンジである(そんな場面に行き会いたくないが.....)。したがって、μSv/hに変換するには\[\text{線量($\mu$ Sv/h)}=\left(\text{data}[27]*16^3+\text{data}[28]*16^2+\text{data}[29]*16+\text{data}[30]\right)*10^{-2}\]とすればよい。ただしdata[0]から始まり、data[34]で終わるとする。

測定データは5秒おきに送られてくるので、そのデータをその都度端末に表示し、1分毎に平均値を計算して、それを記録する。測定時間をあらかじめ、2時間とか3時間とか決めておき、その時間が経過すると、ためておいた平均値を1分単位でグラフに描き出す、という具合にプログラムを設計した。その結果が下の図である。

f:id:jippinius:20210302170945p:plain

5秒ごとに送信されるデータをリアルタイムで端末に表示する。最初の数字が8分目の測定に入っていることを意味し、2つ目の数字が最初の5秒、2回目の5秒という具合にデータを受け取った回数を表す。この数字が12になると、つまり60秒経つと平均値を計算する。

f:id:jippinius:20210302171030p:plain

1分ごとの平均値をグラフにまとめたもの(3時間の連続測定)

今回は3時間の連続測定を行ってみたが、無事に終了した。平均値のデータは(shellスクリプトを利用して日付を名前に付して)ディスクに書き出している。

これで、長年の夢がひとつ叶ったことになる。非常に長い道のりだった....こうやって、積年の問題がひとつひとつ解決できるのも、実は新型コロナウイルスの「おかげ」である。やはり、科学者には暇を与えよ、である。

実は次なる野望があるのである。次は、このプログラムとDoseRAE2を使って、実際に環境モニタリング装置をつくることを考えたいと思う。最近は、Raspberry PIやら、USBメモリだけで起動するスモールボックスPCなど様々な軽量システムが売っているから、それを利用して測定装置の開発に進みたいと思っているのだ。これは案外早く実現しそうである。