夏休み自由研究ブログ連載の8本目です。
はじめに
こんにちは。TIG/DXユニットの宮永です。
昨今の観葉植物ブームに便乗して先日ドラセナ・コンパクタという熱帯アフリカ原産の植物を購入しました。茎の縞模様とパイナップルを彷彿させるような葉っぱがとても可愛らしい植物です。ふとしたときに眺めるととても癒やされます。
観葉植物を購入してから気づいたのですが、水やりというのは結構大変です。植物を置いている場所の室温、日当たり、湿度などから適切な水分量を見極めるのが素人の私には難しいと感じています。
また、生来がズボラな性格をしているため、水をやるのを忘れてしまったりなども今後考えられます。
枯れてしまってから泣きをみることがないように、今回は土壌水分計とRaspberryPi、ADコンバータを使用して観葉植物の水分量を監視するSlackBotを作成します。
また、本記事のサンプルコードはorangekame3/mcp3002にて公開していますので、参考にしてください。
システム構成
構成はシンプルです。
RaspberryPiにこちらの土壌水分計を取り付け、ADコンバータMCP3002で読み出しを行います。読み出した電圧値に応じてSlackBot経由で通知を行います。
Pythonで同様のことを行っている記事はたくさんありますが、Go言語での実装例は殆どなかったのでその点で参考になれば幸いです。
使用機器
- RaspberryPi 3
- 土壌水分計
- ADコンバータ(MCP3002)
- ジャンパーワイヤ(適量)
- ブレッドボード
配線
余談ですが、RaspberryPiにはpinout
というコマンドが標準で備わっています。配線するときに便利ですのでおすすめです。
せっかくですので、pinout
で出力されたピン番号に沿って今回の配線を説明します。
J8: |
ADコンバータは秋月商店で購入しました。
商品詳細ページにデータシートがあったため、こちらを使用して配線の説明をします。
MCP3002には前後があります。写真にあるように前方には半円のマークがついています。
下図のように半円の印がついたものを上向きにした場合、左上から1,2,3…と番号が振られます。
以下、MCP3002とRaspberryPiそして土壌水分計との接続関係です。
今回はMCP3002のCH0のみ使用したため、CH1にはなにも接続していません。
▼配線一覧
MCP3002ピン番号 | RaspberryPiピン番号 | 土壌水分計 |
---|---|---|
1(CS/SHDN) | 24(GPIO8) | Vcc |
2(CH0) | - | Aout |
3(CH1) | - | - |
4(Vss) | 6(GND) | GND |
5(Din) | 19(GPIO10) | - |
6(Dout) | 21(GPIO9) | - |
7(CLK) | 23(GPIO11) | - |
8(Vdd/Vref) | 1(3V3) | - |
実装
今回実装するにあたってこちらのgolang.org/x/exp/io/spi
パッケージを使用しました。
また、MCP3002からの読み出しの実装についてはこちらのリポジトリでMCP3004、MCP3008、MCP3204、MCP3208の実装がされていたため、MCP3002のデータシートと比較しながら実装の参考とさせていただきました。
デバイスの読み込み
まずはgolang.org/x/exp/io/spi
を使用して、デバイスを読み込みます。
dev, err := spi.Open(&spi.Devfs{ |
MCP3002のドライバ作成
デバイスを読み込んだらMCP3002の仕様に合わせてドライバを作成します。
package mcp3002 |
上記の実装で初見でよくわからんと思うポイントにナンバリングしました。順に説明します。
(1)MCP3002のチャネル数
(1)の実装はMCP3002のチャネル数に対するバインディングです。冒頭で説明したとおり、MCP3002はチャネルが2つあります。使用するチャネルによってMCP3002に渡すバイナリも変わるため、ここのハンドリングは大事です。
(2)MCP3002に渡すバイナリ
MCP3002のデータシートを参照すると以下のようなシーケンス図が記載されています。DinがRaspberryPi→MCP3002にわたすバイナリ、DoutがMCP3002→Raspberryで受け取るバイナリです。
データシートにはMCP3002に送るべきバイナリと読みとるべきバイナリについて記載がありました。
このデータシートによれば、MCP3002に向けて2バイト渡せば良いことがわかります。そのうち、1バイト目には条件に沿ったバイナリを渡してあげる必要があります。
StartBitの次に記載されているSGL/DIFF、ODD/SIGN、について0/1のどちらを渡すかは使用するチャネルによります。
以下の図に従えばCH0を使用する場合は10を渡せば良いことがわかります。MSBFについてですが、Figure5-1に従う読み出しを行う場合は1にします。よってRaspberryPi→MCP3002にむけて送信するべきバイナリは
01101000 00000000
であることがわかります。これは16進数表記で0x68
です。同様にして使用しているチャネルが1である場合SGL/DIFF、ODD/SIGNが11となるためRaspberryPi→MCP3002にむけて送信するべきバイナリは
01111000 00000000
となります。これは16進数表記で0x78
です。これで(2)の謎の16進数の役割がおわかりいただけたかと思います。
(3)10ビット読みだし
データシートのFIGURE6-1に記載の通り、末尾10ビットに読み出すべき情報が含まれています。RaspberryPi→MCP3002で2バイト渡したように、MCP3002→RaspberryPiでも2バイト受け取ります。
1バイト目と3で論理積を取ることで1バイト目の下方2ビットの値を特定できます。
例)
10110101と00000011(3)の論理積 は00000001です。
上記で算出したバイナリを8ビット左シフトし後方1バイトと論理和を取ることで、読み出すべき10ビットを取得できます。
例)
00000001を8ビット左シフトすると00000001 00000000になります。
MCP3002→RaspberryPiで受け取った2バイト目のバイナリが01011010
だとすると、上記00000001 00000000
と01011010
の論理和は
00000001 01011010
であることがわかります。これで(3)の謎の演算がわかったかと思います。
あとはこの読み出した値に対して閾値を設定してやれば、観葉植物監視botの要件を達成できます。
呼び出し元の実装
1つのADコンバータに2つのチャネルがついているので監視する観葉植物も2つ登録できます。
Plant構造体を作成してADコンバータを登録するようにします。
閾値0.4を境にbotが通知する状態を変えます。
package main |
上記実装にSlack通知機能を実装します。cronで定期的に土壌水分を監視してPlant.StatusがThirstyである場合はSlackで通知するようにします。Slack通知にはslack-goをcronにはrobfig/cronを使用しました。
package main |
それでは最後に上記ジョブを実行してみます。
ドラセナが喉の乾きを訴えかけてきました…
さいごに
今回は土壌水分計とADコンバータを用いて観葉植物監視botを作成しました。
実はgolang.org/x/exp/io/spi
パッケージはすでにメンテがされていないようで、https://github.com/periphの利用が現在は推奨されているようです。
記事をほぼ書き終えてから気づいたので少し反省です。今後GoでRaspberryPi周りを触る際はhttps://github.com/periphを利用してみようとおもいます。Gobotもこちらをベースに実装を行っているようです。
最後まで読んでいただきありがとうございました。