LoginSignup
7
7

ESP32でNetatmo Weather Stationもどきを作る

Last updated at Posted at 2021-12-19

はじめに

Netatmo ウェザーステーション という製品がございまして、室内と室外の温度湿度を測ることができます。
が、この製品は長らく使っていると壊れます。
私が買ったNetatmoも最近クラウドにレポートを送るのが途切れ途切れになってきました。
周囲でも「壊れた」という声はきくのですが、そうやって買い直させてクラウド維持費を稼ぐビジネスモデルなのかもしれません(そんな馬鹿な!)。

というわけで自分で似たようなものを作りました。

室内モジュール

室内.jpg

室外モジュール

室外.jpg

目標

以下を計測しWiFi経由でMQTTにてスマートホーム制御プロセスに報告します。

  • 室内
    • 温度
    • 湿度
    • 大気圧
    • ガス
    • 二酸化炭素濃度
    • 騒音
    • 臭い
  • 室外
    • 温度
    • 湿度
    • 大気圧
    • ガス
    • 植木鉢の水分

Netatmoとは異なる要求としては以下を設定しました。

  • 家庭内LANで完結させ、外部にデータを出さない
  • Netatmoの最小計測間隔は5分だが、より高頻度に計測し、「二酸化炭素濃度が高くなったら換気扇を回す」が料理をはじめたらすぐに発生することを目指す
  • タバコの煙・臭いを検出し、室外がタバコ臭い時は換気扇を動作させないようにする (たまに近所でタバコを吐く人がいるため。吸ってもいいが吐くな!)
  • RGB LEDで状態が常にみえるようにする

レシピ

以下に記載していない配線材料、抵抗、コンデンサ、ケース類を含めて全部で1万円くらいです。
もちろん秋月で買わなければならない義理はございませんので、amazonやaliexpressで安く仕上げましょう。

室内・室外共通部品 (各1台、合計2組)

製品名 秋月売り場 お値段(約)
ESP32 ESP32-DevKitC-32E ESP32-WROOM-32E開発ボード 4MB: 無線、高周波関連商品 秋月電子通商-電子部品・ネット通販 1200円
5V ACアダプタ 超小型スイッチングACアダプター5V1A AD-D50P100: 電源一般 秋月電子通商-電子部品・ネット通販 600円
AM2320 温湿度センサ モジュール AM2320: センサ一般 秋月電子通商-電子部品・ネット通販 600円
BME680 BME680使用 温湿度・気圧・ガスセンサモジュールキット: 組立キット(モジュール) 秋月電子通商-電子部品・ネット通販 1300円

室内

製品名 秋月売り場 お値段(約)
MH-Z19C CO2センサーモジュール MH-Z19C: センサ一般 秋月電子通商-電子部品・ネット通販 2500円
コンデンサマイク エレクトレットコンデンサーマイクロホン(ECM) WM-61A相当品 リードピン付: パーツ一般 秋月電子通商-電子部品・ネット通販 50円
LM386 オーディオアンプIC NJM386BD: 半導体(モジュール) 秋月電子通商-電子部品・ネット通販 50円
TGS2450 においセンサ TGS2450: センサ一般 秋月電子通商-電子部品・ネット通販 300円
TTA008B トランジスタ TTA008B 80V2A: 半導体(モジュール) 秋月電子通商-電子部品・ネット通販 25円
RGB LED RGBフルカラーLED 5mm OSTA5131A カソードコモン (10個入): LED(発光ダイオード) 秋月電子通商-電子部品・ネット通販 500円(10個)
LED拡散∩ LED光拡散キャップ(5mm) 白 (50個入): LED(発光ダイオード) 秋月電子通商-電子部品・ネット通販 200円(50個)

室外

製品名 秋月売り場 お値段(約)
MQ-2 ガスセンサー(煙センサー) MQ-2: センサ一般 秋月電子通商-電子部品・ネット通販 300円
MQピッチ変換 MQガスセンサ用ピッチ変換キット: センサ一般 秋月電子通商-電子部品・ネット通販 60円
SEN0193 静電容量式土壌水分センサー: センサ一般 秋月電子通商-電子部品・ネット通販 1000円

ハードウェア

室内・室外共通

ESP32

買ってきて技適マークがあれば手続きなしでWiFiを出せます。

AM2320, BME680 (温度、湿度、大気圧、ガス)

ともにi2cなので適当にプルアップしてi2cに繋げばOK.
秋月のBME680モジュールはジャンパ設定でプルアップしてくれます。

BME680があればAM2320は不要といえば不要ですが、今回は本体からすこし離して本体の発熱の影響をうけない計測も試してみるために追加しました。
内外ともにBME680にする必要もないといえばそうなのですが、比較をするには同じものが2つあったほうが正確ですね(部品の個体差はあるでしょうが)。

BME680のガスセンサーは、IAQという空気質の指標の計算ができます。
が、計算式が記載されているdatasheetには誤記らしきものがたくさんあり、公式のライブラリはクローズソースになっています。
以下のソースが参考になります。

G6EJD/BME680-Example: Using the BME680 to measure temperature, pressure, humdity and air quality
thstielow/raspi-bme680-iaq: Basic IAQ calculator for the Bosch bme680 sensor, compensating the humidity dependency and long-term drifts. Outputs a gas quality score on a range of 0-100%.

室内

MH-Z19C (二酸化炭素濃度)

幅がユニバーサル基盤と微妙にずれていましたがソケットをつけたら無事つきました。
発熱しますので近くに温度湿度センサーをつけてはいけません。

PWMとシリアル接続で二酸化炭素濃度が読めます。
オートキャリブレーション機能を設定するにはシリアル接続が必須です。
他方、シリアル接続のみではマニュアルキャリブレーションができません。
従って、

  • シリアル接続
  • マニュアルキャリブレーション

の双方(信号線としては3本)をESP32と接続します。

コンデンサマイク、LM386 (騒音)

以下と同じです。

Arduino Sound Level Meter - Measure Sound/Noise Level in dB with Microphone and Arduino

TGS2450 (臭い)

秋月の販売ページの接続例をそのまま実装すればできます。
センサーのピン番号に注意。

RGB LED (表示用)

Netatmoは上部タッチセンサーを押すと二酸化炭素濃度に応じて光ります。
平常レベルだと緑、ちょっと高くなると黄色、濃くなると赤になります。

今回は押さなくても常に連続的に光るようにしました。
ついでにキャンドル風にゆらゆら光らせました。

RGBそれぞれに220Ωを繋げてPWMで光らせます。
RGB LEDは拡散キャップをつけないと色が混ざらないのでつけておきます。

室外

電池稼働は諦めて電源を窓の隙間から通します。
そして雨のかからなそうなところに本体を設置し、そこから信号線を伸ばして簡易百葉箱的な覆いの下にAM2320を設置しました。

室外機にのみつくセンサーは以下です。

MQ-2 (煙)

秋月でピッチ変換ソケットを売っていますのでそれを使います。
負荷抵抗は10kにしました。

SEN0193 (土壌水分)

近くに小さな植木鉢が置いてあるため、その土壌水分を検出して水切れを教えてもらいます。

ソフトウェア

今回はArduino IDEから書き込んでいます。
Arduino IDEの設定は以下の通りですね。

ESP32を買ってしまった - Qiita

5秒ごとに計測し1σ以上の変化があるか1分経過するごとにmqttで報告させています。

Arduino IDEは.inoという拡張子ですがその中身はc++です。
内外で共通のクラスを作って継承して共通化しています。
STLが使えるのでリングバッファで時系列情報を蓄積して平均や分散をとったりログを貯めるといったことも簡単にできます。

センサーがエラーを出している時に内蔵LEDを点滅させるようなコードをいれておくと、設置したあとソケットの緩み等による動作不良にすぐに気づくので便利です。

使用ライブラリ

以下のライブラリを使用させていただきました。 感謝です。

ポイント

ESP32

使ってみて気づいた注意点は...

  • WiFi使用時はADC1のみ使用可能 (ADC2は使えない)
  • アナログ、デジタルともに入力は3.3Vまで
  • デジタル出力も3.3V。5Vの半分は超えるので出すだけなら大体動きます(規格が3.0Vではなく3.3Vになっているのはそのためです)
  • アナログで計測する電圧の範囲は可変で設定可能(後述)
  • i2cを含めてプルアップは自分でいれたほうが安定する
  • gpio12を使うとフラッシュがうまく書けないことがある
  • 書き込めない時は...___...___の時にボタン(下記1つめの記事参照)を長めに押す
  • OS起動時のシリアルは74880bps
  • OTAは便利

Arduino IDEでESP32/ESP8266を使う時のメモ - Qiita
ESP32-WROOM-32

mqtt, json

接続がきれたら再接続するコードや、長時間loop()が止まる時はmqtt.loop()を自分で呼ぶといったおまじないが必要です。

callback関数の中でpublish()すると引数が破壊されます。
ちゃんとコピーしておくか、callbackの中でpublish()はしないでどこか別の場所に積んでおいて外のloopで処理します。

今回はmqttではjsonを飛ばしていますが、PCで使うような立派なjsonクラスとは違いメッセージサイズに気を付ける必要があります。

debugのon/offや設置したあとに調整する必要がある値(センサーの閾値、サーボの回転角度など)はmqttで可変にしておくと、ちょっとした調整で焼き直す必要がなくて楽です。

MH-Z19C

こちらに記載がある通りなのですが、

ESP32(M5Stack)で作る、安価なCO2モニタ【秋月でCO2センサ取扱開始 記念】 - Qiita

ESP32はUARTを複数持っていて、それぞれのピンを自由に設定できます。
0番を使うと開発時コンソール出力ができなくなってしまうので別のものを使います。

ブートしたら手動キャリブレーションのピンをHIGHにしてUARTを初期化したのち、オートキャリブレーションを無効化するコマンドを出します。
オートキャリブレーションが有効だと過去24時間の間での最低値を400ppmとして設定してしまうため、室内に設置しているときは誤動作の原因となります。

手動キャリブレーションのためのピンも接続しておき、mqttでリクエストを受け取ったら手動キャリブレーション操作(7秒以上LOWを出力)をするようにします。
風通しの良い室外に30分程度放置してから遠隔でリクエストを飛ばします。
スイッチをつけて人間が近くで押してもいいのですが呼気の影響がでるかもしれません。
というか寒いor暑い季節に外まで押しにいくのは単純に面倒ですね。

オートキャリブレーション無効化コマンドを起動時にだしているのに、なぜか数日後にオートキャリブレーションが走ってしまうことがありました。
数時間ごとにオートキャリブレーション無効化コマンドを発行することで安定してオートキャリブレーションしなくなりました。
コマンド転送を失敗している訳でもなさそうなのですが...

ライブラリのwriteCommnad()の冒頭に

  while(hserial->available()){
    hserial->read();
  }

を追加しておくと、受信バッファにゴミがあった時でも正しく動くようになります。

騒音

適当にanalogRead()してもなんとなくな数値がとれますが、ちゃんとやるにはFFTして定常ノイズを潰してからA特性で比較したほうがよさそうです。

ガス・臭い・水分

ちゃんと校正して計算式を立てればいいのですが、リファレンスとなる機材がないのでanalogRead()した値でなんとなく(ひどい)。
しばらく使っていると、「だいたいこの値が閾値かな」というのがわかります。

analogRead()について詳細は以下が参考になります。dbの設定が味噌。

ESP32のADCについて - Qiita

RGB LED キャンドル風演出

RGB LEDは青以外のレベルを半分にします。

ESP32 RTOSのマルチスレッド機能を使いLEDをゆらゆら揺らすスレッドを作ります。
測定中でもゆらゆらします。

loop()とは別スレッドですのでdelay(1000)とかしてもそのスレッドだけがsleepしてくれます。

FreeRTOSでマルチタスク (on ESP32) - Qiita
[M5Stack] マルチスレッドで並列処理を行う - Qiita

夜中にゆらゆら光っても困るので、mqttから遠隔でnightmodeに設定すると消えるようにしました。

今回はRGBでGPIOを3本消費していますが、ピンの節約とデジタル化のためにマイコン付きのLEDにする方法もあります。
明日の天気を予知してくれる魔法のランタンをつくる - Qiita

完成!

あとは適当にグラフを書かせたり、観測値に基づいてエアコンを制御したりすれば完成。

謝辞

製品やライブラリの作者の皆様、参考にしたサイトの筆者の皆様、ありがとうございました。

過去記事紹介と次回予告

過去にQiitaでネタにしたオモチャたち。
実は自宅にあるものは投稿当時から更新しているのですが、そのうち気が向いたらupdate記事を書くかも...

こちらにある壁から吊っているセンサーもESP32にしてE-INKで状態表示をするようにしました。
基本はMQTTですが、赤外線の信号とE-INK (ePaper)に表示する内容はhttpでPOSTしています。

こちらもESP32にするとともに、歪み計で加湿器全体の重さを計って水の量を推測するようにしました。

こちらもOLEDが焼けてきたのでE-INKに変更してESP32にしました。
いろいろ付けたらピンの数がギリギリでした。

トンガ火山噴火の気圧変化が計測できましたよ (追記 2022/01/16)

このBME680でも天変地異が起きたことを検出できました。

bme680.png

他の皆さんの観測結果

センサー地獄! (追記: 2022秋)

その後、調子に乗って多数のセンサーを載せ、「ぼくのかんがえたさいきょうのセンサー用基底クラス」を継承してシングルトンにするようにし、観測値もinfluxdb/victoria metricsにesp32から直接書き込むようにしました。

  • 紫外線

日傘をもってお出かけ。

Qwiic - VEML6075搭載 UV光センサモジュール — スイッチサイエンス

  • 土壌水分検出と自動水やり

植木鉢に自動で水やりをします。

Unit Watering(水分測定センサー付き給水ポンプユニット) M5STACK-U101 M5Stack製|電子部品・半導体通販のマルツ

  • 雨の検出

単に濡れたら電気が通るだけです。

  • 風速計

風車が回転するとロータリエンコーダからパルスが出ます。

ESP32 パルスカウンタの使い方 - Qiita

Amazon.co.jp: Nitrip 風向センサー 風速計 風力計 風量計 カップ式 風速風量湿度測定用 気象観測システム 風速風速計 風速送信機 信号風センサー 風力事業などに : 産業・研究開発用品
(aliexpressでもっと安く買えます)

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7