記事
Toshihiko Minamoto · 2020年12月30日 5m read

ESP8266で取得した気象データをMQTTブローカーに送信する

皆さん、こんにちは

前回のつづきとしてESP8266からMQTTブローカーに接続し、データを送信する部分の内容ついて説明したいと思います。

今回は温度湿度センサーのDHT11と気圧センサーのBME180を使って気温、湿度、気圧を計測し、1分に1回、MQTTブローカーに送信しています。

ハードウェア

回路図は以下のようにDHT11のDATAピンはGPIO、BMP180のSDA,SCLピンはそれぞれGPIO2,GPIO5に接続しました。
電源は紆余曲折の末、単純にmicro USBから供給し、NodeMCUのボードから出力されている3.3Vをそれぞれのセンサーで使用しています。

    

今回は外気温を測りたかったので、ケースに入れた方が良いと思いましたが、ブレッドボードだと見合った箱がありませんでした。
そこで、手元にあったユニバーサル基板にESP8266をはんだ付けし、100均で購入した食品保存用の箱に入れてみました。

     

箱からUSB電源の接続やセンサーとリード線を出す必要がありますので、ニッパで適当に欠きとっています。
センサーは各ピンとリード線をはんだ付けし、熱収縮チューブで覆っています。BMP180の表面はそのままですが...

        

ソフトウェア

ESP8266のプログラムはArduino IDEを利用し、以下のプログラムを書きこんでいます。

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <DHTesp.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);

// 温度湿度計オブジェクト
DHTesp dht;
// 気圧計オブジェクト
Adafruit_BMP085 bmp;

void init_wifi();
void init_mqtt();

// センサーからの情報を集める
void collectSensors() {
  float humidity = dht.getHumidity();
  float temperature = dht.getTemperature();
  float pressure = bmp.readPressure();
  pressure /= 100;
  
  Serial.print("気温:");
  Serial.print(temperature);
  Serial.println(" ℃");
  Serial.print("湿度:");
  Serial.print(humidity);
  Serial.println(" %");
  Serial.print("気圧:");
  Serial.print(pressure);
  Serial.println(" hPa");

  // トピック名
  String topic=String("point/")+String(clientID);

  // データ
  String str=String(temperature,2);
  str += String(",");
  str += String(humidity,3);
  str += String(",");
  str += String(pressure,5);
  
  // MQTTでサーバに送信
  mqttClient.publish((char *)topic.c_str(),(char *)str.c_str());
}

 // 初期化処理
void setup() {
  Serial.begin(115200);
  // I2Cプロトコルの初期化
  Wire.begin(2,5);    // Define(SDA, SCL)
  init_wifi();
  init_mqtt();

  // 温度湿度センサー(DHT11)の初期化(GPIO 13に接続)
  dht.setup(13, DHTesp::DHT11);

  Serial.println("bmpの初期化(GPIO2[SDA],GPIO5[SCL]");
  if (!bmp.begin()) 
  {
    Serial.println("Could not find BMP180 sensor at 0x77");
  }  
}
// WiFiの初期化
void init_wifi() {
    Serial.println("init wiri interface");
    WiFi.mode(WIFI_STA);
    
    WiFi.begin(ssid,password);
    while( WiFi.status() != WL_CONNECTED ) {
      delay(500);
      Serial.print(".");
    }
    Serial.println("");
    Serial.println("WiFi connected");
}

// MQTTの初期化
void init_mqtt() {
  // ClientIDの生成
  for (int i = 0; i < 8; i++) {
    clientID[i] = random(26)+65;
  }
  clientID[8]=0;

  wifiClient.setInsecure();
  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);
    }
  }
}

7行目からの接続情報にある各定数の値については以下の通りです。

  • ssid ... WiFiに接続する際に使用するSSID
  • password ... WiFiに接続する際のパスワード
  • mqtt_server ... 前回設定したmosquittoがインストールされているサーバのIPアドレス
  • mqtt_port ... mosquittoがListenしているポート番号
  • mqtt_user ... mosquittoにアクセスするためのユーザ名
  • mqtt_pass ... mosquittoにアクセスするユーザのパスワード

ざっくりとした処理の内容としましては

ESP8266をブートしますと、setup()関数が実行されます。その中でinit_wifi()、init_mqtt()が実行され、WiFiの初期化、MQTTの初期化を行います。
その後、DHT11ならびにBMP180の初期化も行います。BMP180はI2Cプロトコルを使用してESP8266と通信を行いますので、I2Cプロトコルも初期化します。
I2Cプロトコルは2本のピン(SDA,SCL)で通信をおこないますが、今回、

Wire.begin(2,5);

と記載することで、SDAはGPIO2、SCLはGPIO5のピンを指定しています。

初期化が終了しますと、メインループ(loop()関数)が実行されます。
loop()関数ではMQTTの接続状況をチェックし、接続されていなければreconnect()メソッドを実行し再接続を行います。
接続できればcollectSensors()メソッドを実行し、DHT11センサーの温度、湿度とBMP180センサーの気圧を取得、<気温>,<湿度>,<気圧> のフォーマットでメッセージを作成、mqttClient.publish()メソッドでmosquittoにメッセージを送信しています。

次回はIRISでのMQTTメッセージ取得方法について説明します。

00
1 0 0 96
Log in or sign up to continue