照度計を追加する
の続き?
amazonのセールで Echo Dot と SwitchBotハブミニ を買いましたが、スマートホームに対応した家電は全然持っていません。
ので、とりあえず SitchBot に赤外線リモコンで操作できる照明とエアコンを登録してみました。
が、シーリングライトが古いせいか、赤外線受光部の感度が悪く、結構操作に失敗します。
そこで、確実に照明がoffできたか確認するために、照度計をつけたら良いのでは、と考えて調べてみました。
まず目につくのは、フォトダイオードやフォトトランジスタと呼ばれるパーツです。これらは、光が当たると抵抗が変化する半導体で、抵抗と組み合わせてRaspberryPiのGPIOと接続すれば一応on/offが取れそうです。
しかし、それだと閾値を自分で変えるのは難しそうなので、一般的にはADコンバータを挟むようです。ADコンバータはI₂CやSPIでRaspberryPiと繋ぐようです。
既にI₂Cは温度センサやOLEDディスプレイで使っているので、アドレスが重複しなければI₂Cの方が使い勝手が良さそうです。
なんてことを考えていたら、こんな部品を見つけました。
これを使えば、何も考えずに照度を取れそうです。パーツが500円、送料500円で合わせて1,000円でした。
ピンヘッダを自分ではんだ付けする必要があります。
結線
Pi | TSL25721 |
---|---|
1(3.3v) | 1(VIN),3(3V3) |
3(SDA.1) | 6(SDA) |
5(SCL.1) | 7(SCL) |
6(0v) | 2(GND) |
全て他のパーツのためにブレッドボードとPi間は結線済みなので、ボード内のジャンパワイヤのみです。
だんだんスパゲッティになってきました。
前回との違いは、OLEDを付けるためのプッシュスイッチを、人感センサに変更しています。
人感センサのパーツと配線については、OLEDにセンサ情報を表示するの記事に書いてあります。
センサが5Vの電源を必要とするため、MH-Z19に入れていたPiの4番ピンの5Vをブレッドボードの電源ラインに入れています。
図では書き切れていませんが、MH-Z19の下で5Vの電源をMH-Z19のVinに接続しています。
例によって図とは使っているジャンパワイヤの色が違いますが、実際にはこんな感じになりました。
実装
基本的には秋月さんの商品ページにリンクがあるサンプルソースを参考にすれば良いのですが、例によってpython2.7用なので、微妙に変えています。
後、ソースでは使われていないですが、TSL2572_WEN と言う定数が 0x80 になっていますが、データシートを見ると 0x08 が正しそうです。
I₂Cは、OLED が board.I2C
経由で、BME280 は smbus.SMBus
経由でアクセスしていますが、今回の TSL2572 も smbus.SMBus
を使うことにしました。
smbus.SMBus
のインスタンスを複数作っても良いのかわかりませんが、今回のプログラムはシングルスレッドで逐次アクセスしかしないので、たぶん問題ないと思います。
ソースは、https://github.com/false-git/power-consumption の 9a45ec... のあたり。TSL2572のコードは tsl2572.py です。
データシートを読むと、閾値を指定して割込みをかける機能とか、Idleに落として消費電力節約とかありそうですが、いまいち使い方がわからなかったのでサンプルそのままの使い方をしています。
測定値
部屋の照明をつけていると80〜90の間くらい、消していると昼間で10〜20くらいの値になるようです。夜はまだ来ていないのでわかりません。
実際にルクスとしてどのくらい正確なのかはわかりません。とりあえず、明るさに応じて変化はするので、照明が点いているかどうかの判断には使えそうです。
追記: Status Register
起動後の初回の測定値が0になったりして、ちょっと怪しい挙動があったのですが、データシートを良く読むと Status Register と言うのがあることに気づきました。
ここに AINT と AVALID と言うフラグがあり、AVALID が 1 になっていないと ADC の値を読み出してはいけないのです。
なんでこれに気づいたかと言うと、以下のページを発見したからでした。
ここでは、cgsensorと言うモジュールを公開していて、今回の TSL2572 だけでなく BME280 の制御もできるようです。
ソースも https://github.com/IndoorCorgi/cgsensor/blob/master/cgsensor/tsl2572.py で公開されているので、中身を読んでみました。
すると、gain/cycle を決め打ちではなく最初に短い時間で試してみて、読めた値によって適切な値に決め直すようになっています。
また、測定のたびに Enable Register で PON/AEN して、Status Register で AINT/AVALID が立つのを待ってから ADC の値を読み出すようになっています。
いやもうとても良くできているので、自前で組むよりはこれを使った方が全然良さそうだと言うことに気づいてしまったのですが、せっかく書いてしまったのと、smbusではなくsmbus2を使っているので、一応自前のコードを修正することにしました。
gain/cycleについては、暗いときの制度はそれほどいらないので決め打ちのままとし、計測のたびに AEN と PON を立てるところを真似しました。さらに、SAI(Sleep after interrupt)も立てることで、計測時以外はSleep状態にするようにしてみました。
なんとなく動いているように見えるのですが、本当にSAIがうまく行っているのか良くわかりません。
あと、暗い状態から照明を付けると、1分毎に照度が 0 → 50 → 80 のように徐々に上がります。これは、今回の SAI を入れる前の常に PON を立てていたときと同じ挙動なので、そう言うものなのかも知れませんが、ちょっと気持ち悪い。
暗くなるときはすぐに反映されます。
変更後のソースは a881eb... のあたり。
Discussion