部屋のセンサーはDHT11からDHT12にアップグレードしていましたが、ベランダのセンサーはDHT11のままでした。
このところ急に寒くなって、気温が零度を下回ることもありえる状況になってきましたが、DHT11では零度以下は計測できないんです。
部屋と同じDHT12では芸がないなぁと思って新しいセンサーを物色していたら、気圧も計れる凄いやつを見つけました。
BME280はボッシュ社のセンサーで、温度・湿度・気圧が計れてI2Cに対応しています。センサー自体は非常に小さいので秋月電子では基板に半田付けしたキットとして販売されていました。
仕様は以下のようになっていて、これなら真冬の旭川でも余裕な感じです。
- 温度:-40 ~ 85℃ 精度±1℃
- 湿度:0 ~ 100% 精度±3%
- 気圧:300 ~ 1100hPa 精度±1hPa
センサーを替えるついでに、バッテリーもモバイルバッテリーに替えることにしました。実際に取り付けたモバイルバッテリーは秋葉原で600円くらいで購入したものですが、ダイソーで300円で買えるものと大きさ電池容量的に大差のないものです。
モバイルバッテリーが横長で今まで使っていたおかず容器に入らなくなったので、おかず容器も横長の300mlタイプのものに替えました。底に9つの空気穴を開けています。
ベランダに吊るされるWiFi温湿度・気圧計入りおかず容器
BME280のArduinoライブラリの多くには温度・湿度・気圧の他にもう一つ「標高」を取得できる機能があります。しかし、これは海面の気圧を基準とした換算値を単純に返すだけのためまったく役にたちません。ちょっと天気がいい(気圧が高い)と地下にもぐっている地底人扱いされてしまいます。
※2017/12/30更新
標高は本当に意味がないので外して、代わりに動作モードと前回計測時刻を表示するように改良しました。
温湿度・気圧計のBlynk画面
AE-BME280の接続方法
秋月電子の温湿度・気圧センサモジュールキット(AE-BME280)にはJ1~J3の半田ジャンパがあります。
ジャンパ設定(半田ジャンパ)
- J1:I2C設定時のSDA用プルアップ抵抗の選択
- J2:I2C設定時のSCL用プルアップ抵抗の選択
- J3:I2C設定時には半田でジャンパします
写真のように、ぼくは全て半田ジャンパしています。
また、I2Cのアドレスは5番ピン(SDO)をVDDに接続すると0x77になるとマニュアルに書かれてあったので、基板上で接続しています。
I2Cのアドレスを0x77にするのは、使用するAdafruitのライブラリが0x77を使用するようになっていたからです。
使用しているESP8266ボード(Wio Node)とは次のように接続しています。
- 1番ピン(VDD) <ー> 赤(3.3V)
- 2番ピン(GND) <ー> 黒(GND)
- 4番ピン(SDI, SDA) <ー> 白(GPIO4)
- 6番ピン(SCK, SCL) <ー> 黄色(GPIO5)
センサーモジュールのアップ
8ピンのピンソケットを使っているのは、単に6ピンのものを持っていなくて手持ちの部品で作ったからで、深い理由は全くありません …。
BlynkのWidget設定 ※2017/12/30更新
温度・湿度・気圧・標高用にGauge Widgetを4つ3つ使っています。
LABELの「.」は小数点のことで、表示したい桁数分「#」を書きます。「#」が一つもないと小数点以下は表示されません。
プログラムでDeep Sleepをオンオフできるようにしたので、その制御用のボタンを配置しています。Deep Sleepの間隔はSliderで指定します。
動作モードと前回計測時刻の表示はLCD Widgetを使いました。
スケッチ
画面のボタンでDeep Sleepを制御できるようにしたため、少しごちゃごちゃしてしまいました。
スケッチ中のBLYNK_CONNECTED()
で、クラウドサーバー接続時にクラウドに送られていたボタンのオンオフ情報と間隔を取得しています。そのため、画面のボタンでDeep Sleepをオフにしても次にDeep Sleepから目覚めるまでは反映されません。
BME280で使用するI2CのピンはWire.begin(I2C_SDA, I2C_SCL)
で自由に指定することができます。
※2017/12/30更新
/*
* BME280Blynk
* December 30, 2017
* By Hiroyuki ITO
* http://intellectualcuriosity.hatenablog.com/
* MIT Licensed.
*/
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
// Set Blynk Auth Token and WiFi credentials.
const char *auth = "YourAuthToken";
const char *ssid = "YourNetworkName";
const char *pass = "YourPassword";
// Select I2C sensor pin and BME280
#define I2C_SCL 5 // WeMos D1 mini D1 or Wio Node Right Yellow
#define I2C_SDA 4 // WeMos D1 mini D2 or Wio Node Right White
Adafruit_BME280 bme; // I2C Address 0x77
// Set NTP
const char *NTP_SERVER = "ntp.nict.jp"; // National Institute of Information and Communications Technology
const int TIME_OFFSET = 9 * 60 * 60; // UTC+9h (JST)
// Deep Sleep
#define TEXT_DS "Deep Sleep mode"
#define TEXT_RT "Real Time mode "
int ds_switch = 0; // 0:Off 1:On
int ds_interval = 60; // minutes
BlynkTimer timer;
WidgetLCD lcd(V7);
/*
* Get Time as String
*/
void getDateTime(char *dateTime) {
sprintf(dateTime, "%04d/%02d/%02d %02d:%02d", year(), month(), day(), hour(), minute());
}
/*
* Send Sensor Data to Blynk
*/
void sendSensor() {
char dateTime[17];
getDateTime(dateTime);
if (ds_switch == 1) {
lcd.print(0, 0, TEXT_DS);
} else {
lcd.print(0, 0, TEXT_RT);
}
lcd.print(0, 1, dateTime);
// Get data from BME280 sensor
float t = bme.readTemperature(); // C
float h = bme.readHumidity(); // %
float p = bme.readPressure() / 100.0F; // hPa
Blynk.virtualWrite(V1, t);
Blynk.virtualWrite(V2, h);
Blynk.virtualWrite(V3, p);
BLYNK_LOG2("Time:", dateTime);
BLYNK_LOG2("Temperature:", t);
BLYNK_LOG2("Humidity:", h);
BLYNK_LOG2("Pressure:", p);
}
/*
* Receive Data from Blynk at connected
*/
BLYNK_CONNECTED() {
Blynk.syncVirtual(V5);
Blynk.syncVirtual(V6);
}
/*
* Receive Data from Blynk
* Deep Sleep Switch
*/
BLYNK_WRITE(V5) {
ds_switch = param.asInt();
BLYNK_LOG2("ds_switch:", ds_switch);
}
/*
* Receive Data from Blynk
* Deep Sleep interval time
*/
BLYNK_WRITE(V6) {
ds_interval = param.asInt();
BLYNK_LOG2("ds_interval:", ds_interval);
}
/*
* Main Setup
*/
void setup() {
delay(10);
Serial.begin(74880);
BLYNK_LOG2("Reset Reason: ", ESP.getResetReason());
// Uncomment 2 lines if you use Wio Node
//pinMode(15, OUTPUT);
//digitalWrite(15,HIGH);
Blynk.begin(auth, ssid, pass);
timer.setInterval(2000L, sendSensor); // 2 seconds
// setup BME280
Wire.begin(I2C_SDA, I2C_SCL);
if (!bme.begin()) {
BLYNK_LOG("Could not find a valid BME280 sensor, check wiring!");
while (1); // Hung up!
}
delay(100); // let sensor boot up
// Setup NTP
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_SERVER, TIME_OFFSET);
timeClient.begin();
while (!timeClient.update()) {
delay(500);
}
setTime(timeClient.getEpochTime());
}
/*
* Main Loop
*/
void loop() {
if (ds_switch == 1) {
Blynk.run(); // Get V5 data
Blynk.run(); // Get V6 data
// Confirm the time to wake up
int min = ds_interval - minute() % ds_interval;
if (min != ds_interval) {
BLYNK_LOG("Go to sleep for %d minutes.", min);
ESP.deepSleep((min * 60 - second() + 10) * 1000 * 1000, WAKE_RF_DEFAULT);
}
sendSensor();
// Deep Sleep
min = ds_interval - minute() % ds_interval;
BLYNK_LOG("Go to sleep for %d minutes.", min);
ESP.deepSleep((min * 60 - second() + 10) * 1000 * 1000, WAKE_RF_DEFAULT);
} else {
Blynk.run();
timer.run();
}
}
おしまい