Linux でお手ごろ価格な USB 接続の温湿度計を使う
USBRH
実験ノートを取るときに温度や湿度を書きましょうという建前があっても、結構サボっている人は多いのではないでしょうか。実験している場所のすぐ横に温湿度計のない場合が多いから。しかし温度によってエレキの応答が変わったりする場合には、ちゃんと室温を記録しておきたいですよね。
実験を一昼夜連続して行う場合には、人間が目で温湿度を読み取るなんてことは出来ません。定期的に PC に測定してもらいたいですが、温湿度計ごときに何万円も払いたくないし、あまり筐体のでかいのが来ても取り回しに苦労します。そこで見つけたのが、Strawberry Linux の USBRH という温湿度計。ハンダ付けを自分でやるキットが 3,980 円、ハンダ付け済みのものが 4,980 円、ハンダ付け済みで専用の筐体に入っているものが 6,240 円と、自分の科研費で気軽に買える値段。今回、筐体に入っているものを買いました。
▲ 大きさはリンゴより少し大きいくらい。基盤中央の PIC で、基盤先端に取り付けてある Sensirion の SHT11 という温湿度計チップを制御しています。
乗っかっている SHT11 は非常に取扱いが簡単で、ちょっと PIC をかじったことのある人であれば、このキットを買わないでも同等品を作れると思います。
Linux で使う
販売元では Windows 用の driver しか公開していないため、Linux で USBRH を使うには有志の方が作成されたソフトを使う必要があります。以下、作業記録。
1. 環境
- Scientific Linux 5.5 (64 bit)
- Kernel 2.6.18-194.17.1.el5
- Snow Leopard + VMware Fusion 3 上で guest OS として実行
2. Kernel Module を使う
kimata さんが作成された USBRH driver for Linux を使うことで、
$ cat /proc/usbrh/0/status t:21.30 h:70.92
なんてやるだけで、簡単に温湿度を読み出すことができます。
2.1 Kernel Module の Build
$ wget http://green-rabbit.sakura.ne.jp/usbrh/dist/usbrh-0.0.8.tgz $ tar zxvf usbrh-0.0.8.tgz $ cd usbrh-0.0.8 $ make $ sudo make install
この作業で、以下の 2 つの file が install されるはずです。
/etc/udev/rules.d/10-usbrh.rules /lib/modules/2.6.18-194.17.1.el5/extra/usbrh.ko
$ sudo /sbin/modprobe /lib/modules/2.6.18-194.17.1.el5/extra/usbrh.ko
とした後、/sys/bus/usb/drivers/usbrh が作成されることを確認します*1。
2.2 /etc/udev/rules.d/ の設定
Gentoo Linux では、2.1 の設定だけで使えるようになるそうですが、Red Hat clone である Scientific Linux や CentOS ではすぐに使用できません。先ほど install した usbrh ではなく、usbhid が先に USBRH を掴んでしまうからです。そこらへんの議論と解決方法は id:dayflower さんが詳しく解説されています。
/etc/udev/rules.d/10-usbrh.rules の中身を次のように書き換えます。
# USBRH by Strawberry Linux ACTION=="add", BUS=="usb", SYSFS{idVendor}=="1774", SYSFS{idProduct}=="1001", PROGRAM="usbrh.sh '%b:1.0'"
id:dayflower さんの環境では PROGRAM の代わりに RUN となっていたのですが、自分のとこでは動かなかったので、PROGRAM に書き換えて解決しました。man udev しても、いまいち RUN と PROGRAM の差が分かりませんでした。
また、ここで呼び出している usbrh.sh を、次の中身で /lib/udev/usbrh.sh として保存しておきます。当然、実行権限は付けておいて下さい。
#!/bin/sh DRIVER_PATH=/sys/bus/usb/drivers /sbin/modprobe -v -s usbrh echo -n "$1" > $DRIVER_PATH/hiddev/unbind 2>/dev/null echo -n "$1" > $DRIVER_PATH/usbhid/unbind 2>/dev/null echo -n "$1" > $DRIVER_PATH/usbrh/bind 2>/dev/null exit 0
ここまで、ほとんど id:dayflower のパクリです。
2.3 実際に使う
それでは、USBRH を接続します。自分とこでは VMware 上で使っているので、USB が VMware 上に現れるようにする必要があります。USB を接続した後、dmesg で次のように出ていれば OK のはず。
usb 2-1: new full speed USB device using uhci_hcd and address 35 usb 2-1: configuration #1 chosen from 1 choice hiddev96: USB HID v1.00 Device [Strawberry Linux Co.,Ltd. Hygrometer/Thermometer] on usb-0000:02:00.0-1 /home/oxon/sw/usbrh-0.0.8/src/usbrh.c: USBRH device now attached to /dev/usbrh0
後は、次のようにして温湿度を読み出せれば完了です。root 権限は必要ありません。
$ cat /proc/usbrh/0/status
2.4 Error への対処
ここまで、本当はうまく行くはずだったのですが、手元の環境では
$ cat /proc/usbrh/0/status Failed to get temperature/humierature
という error が頻繁に出ました。どうやら USB の通信に時間がかかりすぎ、timeout する場合があるようです。そこで、作者の kimata さんにお伺いしたところ、src/usbrh.c の 152 行目で 1000 msec の wait を 5000 msec に長くするという方法で解決しました。2000 msec では失敗するときがあり、また 5000 msec でも稀に失敗するときがあるのですが、この遅延の原因はよく分かりません。
失敗する場合は、src/usbrh.c を書き換えて、再度 usbrh を読み込ませます。
$ sudo /sbin/rmmod usbrh $ make $ sudo cp src/usbrh.ko /lib/modules/2.6.18-194.17.1.el5/extra/usbrh.ko $ sudo /sbin/modprobe usbrh
3. 単独の Command を使う
id:Briareos さんが作成された command で、こちらも簡単に
$ sudo ./usbrh 21.53 56.09
とすれば、温湿度を読み取れます。
3.1 Command の Build
まずは、普通に tar.gz を展開します。
$ wget http://www.dd.iij4u.or.jp/~briareos/soft/usbrh-0.05.tar.gz $ tar zxvf usbrh-0.05.tar.gz $ cd usbrh-0.05
作者さんの blog のコメントによると、一部環境で error が出るようなので、
usbrh_main.c の 232 から 236 行目を次のように書き換えます。
if((rc = usb_set_configuration(dh, dev->config->bConfigurationValue))<0){ if( rc = usb_detach_kernel_driver_np(dh, dev->config->interface->altsetting->bInterfaceNumber)<0 ){ puts("usb_set_configuration error"); usb_close(dh); exit(3); } }
で、make して実行すれば動作します。
$ make $ sudo ./usbrh 24.01 33.55
3.2 Error
ただし、自分の環境では 2 回に 1 回、必ず読み取り値が不正でした。
$ sudo ./usbrh -v -d usb_set_debug: Setting debugging level to 5 (on) USBRH is found USB error: could not set config 1: Device or resource busy usb_control_msg OK:send bytes:[7] 00 00 00 00 00 00 00 usb_bulk_read error convert to integer(temperature):[00 00] -> [0000] convert to integer(humidity):[00 00] -> [0000] Temperature: -40.00 C Humidity: -4.25 %
usbrh_main.c の中で 5000 msec の timeout を設定してあるのですが、これを 20000 msec などに変更しても timeout してしまい、配列 buff の値が初期値のままになるからです。これは原因が不明です。
4. 試しに測定してみる
TestEquity 1000 Series の恒温槽を使って、較正してみました。と言っても、恒温槽側の温度計の精度は不明です。
15.0 ℃、17.5 ℃、20.0 ℃、22.5 ℃、25.0 ℃に恒温槽を設定したときの、USBRH で測定した温度の変化のグラフです。測定値自体は安定しているので、offset を考慮すれば、問題なく使えます。また、±5 ℃であれば、実用上は十分に線形です。
*1:usbrh.ko を絶対 path でしないと、初回は modprobe が usbrh.ko を見つけてくれませんでした。再起動後は、modprobe usbrh とするだけで動作しました。再起動せずに検索させる方法は知りません。