皆さん、こんにちは。
寒い日が続きますね。
前々回の記事でDHT11とBMP180を使って作成したのですが、実際に外に置いて計測してみると、氷点下の場合、12~13℃となってしまい、正しく計測できませんでした。(先にデータシートを確認しておけばよかったのですが、DHT11、BMP180共に0℃以上になっていました...)そこで代わりのセンサーが無いか探していたところ、BME280というセンサーが見つかりました。-40℃から85℃まで測れ、BMP180と同じBosch製で値段も数百円。
センサーモジュールはBMP280と共用の基板で、どちらなのか印がなく、湿度が測れるのかどうかちょっと心配していましたが、注文通りBME280だったらしく、湿度も測れました。
配線図は以下のようになります。BMP180と同様にI2Cで接続しています。また、今回は別のESP8266とユニバーサル基板を使って配線をやり直すついでに電源をUSB給電から3Vの電池にしています。
前回のようにリード線でセンサーとマイコンを離すのが扱いづらかったので、センサーモジュールをユニバーサル基板上にはんだ付けしました。その上でセンサーが保存容器の外に出るようにケースに切り込みを入れてみました。
プログラムは以下の通りです。I2C通信に必要な<Wire.h>、BME280のI2C通信に必要な<BME280I2C.h>をインクルードしており、Wire.begin(5,4)にてSDA,SCLの端子をGPIO5,GPIO4にアサインしています。
bme.begin()でBME280の初期化をおこない、bme.read(pres,temp,hum)で気圧、温度、湿度を計測し、変数に代入しています。
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <BME280I2C.h>
// 接続情報
const char *ssid = "********";
const char *password = "********";
const char *mqtt_server = "********";
const int mqtt_port = 8883;
const char *mqtt_user = "mqttclient";
const char *mqtt_pass = "********";
// 計測間隔 (60秒)
unsigned short interval = 60;
// クライアントID
char clientID[10];
// WiFiオブジェクト
WiFiClientSecure wifiClient;
// MQTTクライアントオブジェクト
PubSubClient mqttClient(wifiClient);
// BME280オブジェクト
BME280I2C bme;
void init_wifi();
void init_mqtt();
// センサーからの情報を集める
void collectSensors() {
float temp(NAN), hum(NAN), pres(NAN);
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
// トピック名
String topic=String("point/")+String(clientID);
// センサーからの読み込み
bme.read(pres, temp, hum, tempUnit, presUnit);
Serial.print("気温:");
Serial.print(temp);
Serial.println(" ℃");
Serial.print("湿度:");
Serial.print(hum);
Serial.println(" %");
Serial.print("気圧:");
Serial.print(pres);
Serial.println(" hPa");
// データ
String str=String(temp,2);
str += String(",");
str += String(hum,3);
str += String(",");
str += String(pres,5);
// MQTTでサーバに送信
mqttClient.publish((char *)topic.c_str(),(char *)str.c_str());
}
// 初期化処理
void setup() {
Serial.begin(115200);
Serial.println("起動");
// 省電力モード(Light sleepモード)
wifi_set_sleep_type(LIGHT_SLEEP_T);
// I2Cインターフェースの初期化.
Wire.begin(5,4); // Define(SDA, SCL)
init_wifi();
init_mqtt();
Serial.println("bmpの初期化(GPIO5[SDA],GPIO4[SCL]");
while (!bme.begin())
{
Serial.println("ボード上のBME280センサーが見つかりません");
delay(1000);
}
}
// WiFiの初期化
void init_wifi() {
Serial.println("WiFiインターフェースを初期化します");
WiFi.mode(WIFI_STA);
connect_wifi();
}
void connect_wifi(){
WiFi.begin(ssid,password);
while( WiFi.status() != WL_CONNECTED ) {
delay(500);
Serial.print(".");
}
wifiClient.setInsecure();
Serial.println("");
Serial.println("WiFiネットワークに接続しました");
}
// MQTTの初期化
void init_mqtt() {
// ClientIDの生成
for (int i = 0; i < 8; i++) {
clientID[i] = random(26)+65;
}
clientID[8]=0;
mqttClient.setServer(mqtt_server, mqtt_port);
}
// メインループ
void loop() {
// 計測開始時刻を取得
unsigned long st = millis();
if (!mqttClient.connected()) {
reconnect();
}
collectSensors();
// 計測終了時刻を取得
unsigned long ed = millis();
// 計測間隔から計測や転送に要した時間を差し引いた分Waitする
delay(interval * 1000 - ( ed - st ));
}
void reconnect()
{
// Loop until we're reconnected
while (!mqttClient.connected())
{
Serial.print("Attempting MQTT connection...");
// Connect to the MQTT broker
if (mqttClient.connect(clientID,mqtt_user,mqtt_pass))
{
Serial.println("connected");
} else
{
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
実際に実行してみると以下のグラフのように氷点下のデータも取得できたのですが、温度の上下が激しくマイコンの影響を受けているのかもしれません...
また、電池も2日弱で切れてしまいました...