ESP-WROOM-02とBME280で床下環境を計測する

自宅の床下部分が収納庫として成立するのかを確かめるべく、温度・湿度・気圧の環境状況を長期にわたって計測してみようと思います。床下というのはいわゆる床下収納庫ではなく、その外側にあり家外の外気とつながっている本当の床下で、家の基礎などが丸見えになっている領域です。家の外につながっているので外気に連動して温度や湿度が変動するような気もするし、床の下なのである程度安定した状況になるような気もする。ということで、実際に確かめてみることにします。

測定回路

床下は電源が取れないので、電池で長期間動作させられそうなものとして、ESP-WROOM-02を選択。Raspberry Piだとちょっと電池の持ち的に厳しそうなので。

回路は東京お気楽カメラさんの記事を参考にさせていただきました。

  • ESP-WROOM-02
    スイッチサイエンスのピッチ変換済みモジュール(フル版)を使用。Arduinoとしてスケッチを書き込んで使います。
  • 温度・湿度・気圧センサー BME280
    BME280を使っているモジュールは各社から販売されていますが、今回は調べた限り一番安かった秋月電子のモジュールキットを購入。このモジュールをI2Cで接続して使います。モジュール基板には3か所のハンダジャンパーがあり、今回は3つともショートさせます。

    • J3: I2Cで使う場合は必ずショートさせる。
    • J1, J2: 信号線をプルアップさせる場合にショートさせる。今回は他のI2Cデバイスとバスを共用していないので、BME280でショートさせることとします。
  • レギュレーター
    低損失・低消費電力のNJU7223を使用。電圧降下を避けるため出力側に470μFの電解コンデンサを入れました。
  • USB-シリアル変換
    ArduinoのスケッチをPCからUSBで書き込むためにUSB-シリアル変換器を使います。私はスイッチサイエンスのUSBシリアル変換アダプタを使っています。
  • 電源
    eneloopを4本使います。

そして回路図はこうなりました。スケッチ書き込み時はIO0のスイッチをWRITE側にしてリセットスイッチを押してPCからデータを送信し、終わったらIO0のスイッチをEXEC側にして再度リセットスイッチを押します。常時Highか常時LowにするIOピンやENピンにはプルアップ抵抗/プルダウン抵抗はいらないはずなのでVccまたはGNDに直結しています。これでいいはずですが……。

回路図

これをブレッドボードを使って組み上げます。

スイッチサイエンスのESP-WROOM-02モジュールはちょうどブレッドボードの幅になっているので、基板裏側をうまく活用して配線する必要があります。またブレッドボードの大きさ的にスイッチを実装する場所が無くなってしまったので、ジャンパーコネクタでEXECとWRITEを切り替え、ジャンパーワイヤー直結でリセットをかけるようにしています。

これをダイソーで買ったプラスチックケースに収めます。ブレッドボード実装部品からの発熱の影響を避けるため、センサーはケースの外側に露出させることとしました。虫やらなんやらの生き物が近づかなければいいのですが……。

ソフトウェア

ソフトは@yukitterさんの記事を参考に、deep sleepモードへの移行用のコードを追加しています。データはAmbientに送信し可視化することにします。さらに少しでも消費電力を抑えるため、運用上は不要なシリアル通信部分をコメントアウトできるようにしています。

#include <Wire.h>
#include <ESP8266WiFi.h>

#include "BME280_MOD-1022.h"
#include "Ambient.h"

extern "C" {
#include "user_interface.h"
}

// 計測する間隔(秒)
#define PERIOD 500

// シリアル出力をしない場合はコメントアウトする
// #define SERIAL_OUT

//----------------------------------------------

const char* ssid = "接続するwi-fiのSSID";
const char* password = "接続するwi-fiのパスワード";

unsigned int channelId = AmbientのチャネルID;
const char* writeKey = "Ambientのライトキー";

WiFiClient client;
Ambient ambient;

//----------------------------------------------

float temperature = 0.0;
float humidity    = 0.0;
float pressure    = 0.0;

void printFormattedFloat(float val) {
  char buffer[10];

  dtostrf(val, 4, 2, buffer);
  Serial.print(buffer);
}

void setup() {
  wifi_set_sleep_type(LIGHT_SLEEP_T);

  // I2Cの通信を開始
  // SDA: GPIO4
  // SCL: GPIO5
  Wire.begin(4, 5);
#ifdef SERIAL_OUT
  Serial.println("I2C start.");
#endif

  // シリアル通信を開始
#ifdef SERIAL_OUT
  Serial.begin(115200);
  Serial.println("Serial start.");
#endif

  // BME280を初期化
  BME280.readCompensationParams();

  // オーバーサンプリングの回数を設定
  BME280.writeOversamplingTemperature(os1x);
  BME280.writeOversamplingHumidity(os1x);
  BME280.writeOversamplingPressure(os1x);
#ifdef SERIAL_OUT
  Serial.println("BME280 start.");
#endif

  // wifi初期化
  WiFi.begin(ssid, password);
#ifdef SERIAL_OUT
  Serial.println("WiFi start.");
#endif

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
#ifdef SERIAL_OUT
    Serial.print(".");
#endif
  }
#ifdef SERIAL_OUT
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
#endif

  // チャネルIDとライトキーを指定してAmbientの初期化
  ambient.begin(channelId, writeKey, &client);
#ifdef SERIAL_OUT
  Serial.println("Ambient start.");
#endif

}

void loop() {
  // BME280を1度だけ測定を行うモードに設定し計測が終わるまで待機
  BME280.writeMode(smForced);
  while (BME280.isMeasuring()) {
    delay(1);
  }

  // BME280から測定値を読み取る
  BME280.readMeasurements();
  temperature = BME280.getTemperature();
  humidity = BME280.getHumidity();
  pressure = BME280.getPressure();

  // 読み取った値をシリアルにプリント
#ifdef SERIAL_OUT
  Serial.print("Temperature: ");
  printFormattedFloat(temperature);
  Serial.println("");

  Serial.print("Humidity: ");
  printFormattedFloat(humidity);
  Serial.println("");

  Serial.print("Pressure: ");
  printFormattedFloat(pressure);
  Serial.println("");
  Serial.println("");
#endif

  // Ambientに連携
  ambient.set(1, temperature);
  ambient.set(2, humidity);
  ambient.set(3, pressure);
  ambient.send();

  ESP.deepSleep(PERIOD * 1000 * 1000, WAKE_RF_DEFAULT);
  delay(1000);
}

実行結果

いまのところ順調にデータが送信されているようです。22:00より前はテスト用に家の中をうろうろしているときのデータなので変動が大きいです。また22時くらいに床下に設置したのですが、この直後くらいに湿度が急上昇しました。これはいきなり寒い場所に置いたための結露が発生したものと思います。

今後はデータを採取する場所を増やして、床下の状況と比較できるようにしたいと思います。

投稿者: けむしろう

プログラミング、サーバ構築、電子工作、旅行が好きです。

コメントを残す

メールアドレスが公開されることはありません。