我が家の洗面所で暖房ボイラーの消費電力と温度・湿度を計っているRaspberry Pi。そこで使用している温度センサをより高精度なものへ交換しました。
今で使っていたDHT11だと3.3V時の精度が低く、出力も1度刻みなのでM2Xでグラフを見てもガクガクしていて今一つだったのです。
DHT11からAM2320へ
そのDHT11を製造しているAosong(Guangzhou) Electronics Co.,Ltd.の最新?温湿度センサがAM2320。DHT11の上位製品であるDHT22にi2c通信モードを足した製品のようで、温度測定範囲は-40℃から80℃とマイナスにも対応、0.1℃刻みで誤差±0.3℃と高性能。
足の間隔が2.54mmピッチのAM2320と1.27mmピッチのAM2321があり、後者を買って「あーっ」っとなってる人が結構多そうな印象。ユニバーサル基盤などで作業しやすいのはAM2320です。
通信はDHT11と同じようにタイムチャートに合わせてデータを取得する1-wireモードもありますが、せっかくなので今回は楽そうで事例も多いi2cを使う事に。データシートはメーカーではなくていつもの秋月電子のページにあります。
その秋月は送料が高かったので、スイッチサイエンスの通販 – Yahoo!ショッピングにて580円+送料全国一律164円で購入。
CからRubyへ
結線やサンプルプログラムなどまるっとRaspberry PIで温度湿度センサーをRubyで動かす – Qiitaを参考にさせていただきました。結線は線が1本増えたのでGPIOから引き直し。Vcc5V、GNDのほかAM2320の2pin(SDA)をピンヘッダの4pinへ、4pin(SCL)を6pinへ。
面倒なので以下rootにて作業しています。i2c-toolsを入れてユーザー作成。piは最初からあるので何か言われる想定。
# apt-get install i2c-tools # adduser pi i2c
modulesに2行追加します。
# vi /etc/modules i2c-bcm2708 i2c-dev
モジュールのブラックリストファイル(/etc/modprobe.d/raspi-blacklist.conf)から除外しますが自分はすっからかんでした。もし
blacklist i2c-bcm2708
が入っていれば#でコメントアウトします。ここまできたらリブート。
期待しながらi2cdetectを実行してみます。
# i2cdetect 1 Error: Could not open file `/dev/i2c-1' or `/dev/i2c/1': No such file or directory # i2cdetect 0 Error: Could not open file `/dev/i2c-0' or `/dev/i2c/0': No such file or directory
うーん。モジュールはロードされてるのに/devが無いっぽい。i2c-toolsを入れなおしてもダメ(今思えばMAKEDEVをaboteしたとかなんとか)。ググったりしているうちにこの記事に出会って思いました。
あれ、コメントアウトもなにも結局i2c自体が有効になってないって事じゃね?
という事で
#raspi-config -> 9 Advanced Options -> A7 I2C
で全部Yes押して有効にすれば
# i2cdetect 1 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-1. I will probe address range 0x03-0x77. Continue? [Y/n] 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- # i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- 5c -- -- -- 60: -- -- -- -- -- -- -- -- -- -
ちゃんと動きました。今元記事見たら
Raspbianの標準ではi2cが有効になっていないので有効にします。
書いてあるし(ノ∀`)
無事にセンサと窓口が開いた所で、Rubyのプログラムにとりかかります。
Gemでi2cのライブラリをインストール。
gem install i2c
ソースもとりあえずまるごとお借りして実行。
# ruby am2321.rb nil nil nil [42.8, 26.1] nil nil nil nil nil nil nil nil nil
うーん。このnilの山はいったい。一部温度は取れているようなのだけど・・・
結局データシートや色々な所を調べてみると、ほとんど
s = @device.read(@address, 8, “\x03\x00\x04”)
の結果うまく値が入らずnilを返している模様。最初は通信上のエラーでCRCチェックに漏れているのかと思ったんですが、i2c通信自体となると自分のスキルでは打てる手はなし。
とりあえず目的優先という事でプログラムのループ部分を
- 値が取れるまでループ
- 取るのに何回かかったかを別ファイルに書き出し
するように変更しました。
sensor = AM2321.new('/dev/i2c-1') 100.times do p sensor.read sleep(0.5) end
から
res = nil rcount = 0 sensor = AM2321.new('/dev/i2c-1') while res == nil do res = sensor.read rcount += 1 sleep(1) end print(res[0], ",", res[1], "\n") File.open("/dev/shm/am2320retry-counts.txt","a") do |file| file.puts "#{Time.now.strftime("%H:%M:%S")},#{rcount}" end
[湿度,温度]
の形で入ってくるのでDHT11の時と同じく、”,”でcutしてm2xに投げるシェルを変更してcrontabも入れ替えて完了。cronで動かない・・・と思ったら作った.rbのパーミッションが755になってませんでした。
これで我が家の温度グラフがより詳細に!!
最後に取得失敗回数をカウントしたテキストを載せておきます。10分に一回実行し、失敗した場合は内部で1秒ごとにリトライ。結果9割は1回ないし2回で取得ができていますが、時折59回や中には99回もかかったなんてのもあってどうしたらいいのやら。
# tail -f /dev/shm/am2320retry-counts.txt 14:10:04,1 14:20:04,1 14:30:05,1 14:40:05,1 14:51:02,59 15:00:05,2 15:10:05,2 15:20:06,2 15:30:05,1 15:40:04,1 15:50:04,1 16:00:04,1 16:10:05,1 16:20:05,2 16:30:06,2 16:40:04,1 16:50:05,2 17:00:05,2 17:10:05,2 17:20:06,2 17:30:05,2 17:41:43,99 17:50:05,2 18:00:25,21 18:10:06,2 18:20:05,2 18:30:06,2 18:40:05,2 18:50:05,2 19:00:05,2 19:10:05,2 19:20:14,10 19:30:05,2 19:40:05,2 19:50:05,2 20:00:05,2 20:10:06,2 20:20:05,2 20:30:46,43 20:40:05,2 20:50:05,2 21:00:06,2 21:11:02,58 21:20:04,1 21:30:06,2 21:40:05,2 21:50:05,2 22:00:05,2
とりあえず、こんな形でうまく動き始めてくれました。
説明怪しいけどAM2320は一応Amazonでも売ってます。
最近AM2320を買って、ラズパイ3B + Win10 IoT Core で接続してみました。
このセンサーは自動的に省電力モードに入るらしく、一度ダミーのコマンドを送信した後、世紀のコマンドを投げることでデータを取得できます。
また、コマンドを投げた後、15ms待たないとデータの読み取りに失敗するそうです。
pythonはほとんど触ったことが無いので的外れかもしれませんが、コマンドの送信と受信を1命令で行うのではなく、送信後にウエイトを入れてから受信してみてはどうでしょう。
▽VELMY
ようこそいらっしゃいました。
スリープモードは認識があっても15msは盲点でした。
2回で取れる時もあれば未だに何十回もnilが続く事もあるので、
read前に15ms入れてみようと思います。
ありがとうございました。