2個のBME280で気象データを取得する
みなさん、こんにちは。
前回の記事では1個のBME280で気象データを取得したのですが、気温のブレが大きかったので基板から
ただ、基板につけたBME280のはんだを外すのが大変なので、別のBME280を外付けすることにしました。
当初、ESP8266の別のIO端子と接続することを考えていたのですが、Wire.hが複数のバスに対応していない
ため、以下の配線図のようにカスケード接続することにしました。
カスケード接続するということは、外付けのBME280でI2Cのアドレスを変えないといけません。幸いBME280は0x76と0x77の切り替えができるようです。
こちらの資料を見ると、基板上に3つの端子があり、左2つがつながると0x76,右2つがつながると0x77になるそうで、左2つの端子はつながっているので、ナイフで切断しなさいとなっていました。
で今回購入したセンサーを見ると、端子はあるけど左2つの端子の間はつながっていません。よく見るとセンサーの左下の端子の左側がつながっており、これで左2つの端子がショートしていることになります。
なので、センサーの左下端子の左側をカッターで切断しました。ルーペが無かったので、カミさんのスマホスタンドを借りて、スマホのカメラで拡大しながら、慎重に切断、テスターで抵抗値を確認... 50歳を過ぎたオッサンの作業としては非常に辛いものとなりました(笑)。
切断が確認されると今度は右2つの端子をはんだでつなぎました。加工後が以下の写真です。
プログラムは以下の通りです。前回のものから外付けBME280のインスタンスbme2を作成し、初期値としてbme2settingsを作成、I2Cのアドレスとして0x77を代入しています。
初期化はインスタンスbmeと同じでbme2.begin()で初期化を行い、bme2.read()で気象データを読み込み、編集に代入しています。
外付けBME280のデータは元々のbme280で使用しているトピック名の後ろに-2を取り付けて、別途MQTTブローカーにpublishしています。
また、電池が2日弱しかもたず省電力設定をする必要があったのですが、プログラムの作り直しは面倒でしたので、とりあえずsetup()の最初の方で
wifi_set_sleep_type(LIGHT_SLEEP_T)
を実行し、Light sleepモードにしています。この1行で3日弱持つようになったので、およそ1日分長くなりました。
#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::Settings bme2settings(
BME280::OSR_X1,
BME280::OSR_X1,
BME280::OSR_X1,
BME280::Mode_Forced,
BME280::StandbyTime_1000ms,
BME280::Filter_16,
BME280::SpiEnable_False,
0x77
);
// BME280オブジェクト
BME280I2C bme, bme2(bme2settings);
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.println("センサー(ボード)");
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());
// 外付けセンサーのトピック名
topic=String("point/")+String(clientID)+String("-2");
// 外付けセンサーからの読み込み
bme2.read(pres, temp, hum, tempUnit, presUnit);
Serial.println("センサー(外付け)");
Serial.print("気温:");
Serial.print(temp);
Serial.println(" ℃");
Serial.print("湿度:");
Serial.print(hum);
Serial.println(" %");
Serial.print("気圧:");
Serial.print(pres);
Serial.println(" hPa");
// データ
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);
}
while (!bme2.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);
}
}
}
これで測定した同じ日のデータを見比べてみると、左の外付けセンサーの方が温度が安定していることがわかりました。
外付けセンサー | 基板設置センサー |
---|---|