Posted at

ESP8266を使って温度センサ情報をIFTTTに投げる

More than 1 year has passed since last update.


やったこと

Boschの温度・気圧・湿度センサ(BME280)をWifiボードESP8266に接続。

IFTTTと連携してデータをスプレッドシートに格納


はじめに

 近年、IoTという言葉で表されるように、センサ機器をインターネットに接続することで、センサ情報を手軽に、リアルタイムに、集約的に扱うことが可能になってきました。

 ホビーユースでこのブームに火をつけた要因の一つはなんといってもESP8266だと思います。それ以前だと、センサ情報を処理してインターネットに接続することを考えると、ArduinoとWifiボードを用いるか、もしくはラズパイを用いることを考えました。どちらも数千円のコストがかかります。

 ESP8266ならば、数百円、評価用ボードを用いても2000円くらいで済んでしまいます。

 最近では後継機種であるESP32も出てきており、こちらはWiFiに加えてBluetoothも扱えるようですが、ESP8266もまだまだ現役ですし、先行機種であるがゆえに情報の蓄積も多いと思います。

 今回は記事としては目新しさはないですが、ESP8266と温度(+湿度+圧力)センサであるBME280を接続し、WiFiアクセスによりIFTTTに情報を投げてみます。

ソースコードはgithubに公開しています。


設定


ESP8266

Arduino用の開発環境を用います。

また、センサ情報は5分に一回IFTTT側に送ればいいと考えから、deepsleepモードを使っています。

deepsleepに関する記事はこちらが参考になりました。

ESP8266の真骨頂Deep-Sleepモードの使い方

IFTTTサーバへの接続状態を判断するために4番ピンにLEDを接続し、接続試行中にLEDが点滅するようにしています。


BME280

BME280は通信にSPIとI2Cが使えますが、今回はI2Cを選択します。

I2Cアドレスを0x76として使うために、BME280のSDO端子をグラウンドに落としておきます。

コードは基本的に、スイッチサイエンスさんが公開しているBME280用のサンプルコード をベースに、ESP8266の機能や、IFTTTへの接続部分を追加していきます。


ESP8266とBME280の接続

留意点、ピン配置としては


  • Wire.begin関数で12,13番ピンを指定


    • ESP8266の12番ピンをBME280のSDI番に接続

    • ESP8266の13番ピンをBME280のSCKに接続



ESP8266によるI2Cの使い方は

macsbug - ESP8266 と I2C

BME280のI2C接続での使い方は

AmbientでIoTをはじめよう


WiFiの設定


  • SSID

  • パスワード
    を把握


IFTTTの設定


  • event名

  • WebHookアプリのsecret keyを設定

IFTTT側の設定は特に書かないので各自やりたいことをやってください。設定方法は例えば

ESP8266とBME280とIFTTTでIoTボタンをつくった

に詳しく書かれています。同じような事をしていらっしゃるかたが既にいました。


コードの解説


Wifi, IFTTTの設定

#include <ESP8266WiFi.h>

#include <Wire.h>

char* ssid = "put your SSID";
const char* password = "put your password"

const char* host = "maker.ifttt.com";
const char* event = "put your event";
const char* secretkey = "put your secretkey";

最初の2行はSSID名、パスワードを指定します。下の3行はIFTTT側の設定。通知したいイベント名を設定します。また、Webhooksを用いるので、 webhookのsecretkeyを入手しておき、指定しておきます。

secretkeyの確認に関してはこちらなどが参考になると思います。eventはIFTTT側の設定と同じにしておきます。

ちなみにこのコードではポート80を使ってhttp通信をおこなっています。つまり、パスワードが平文で流れるので、セキュリティ的に非常によろしくないです。ゲスト用のアクセスポイントを使うなどしてください。(それでもwebhook側のsecret keyはわかってしまいますが)。https通信については確認中です。(180711)


データの取得とIFTTTへのデータ転送


void loop()
{
double temp_act = 0.0, press_act = 0.0, hum_act = 0.0;
signed long int temp_cal;
unsigned long int press_cal, hum_cal;

readData();

temp_cal = calibration_T(temp_raw);
press_cal = calibration_P(pres_raw);
hum_cal = calibration_H(hum_raw);
temp_act = (double)temp_cal / 100.0;
press_act = (double)press_cal / 100.0;
hum_act = (double)hum_cal / 1024.0;
Serial.print("TEMP : ");
Serial.print(temp_act);
Serial.print(" DegC PRESS : ");
Serial.print(press_act);
Serial.print(" hPa HUM : ");
Serial.print(hum_act);
Serial.println(" %");

Serial.print("connecting to ");
Serial.println(host);

// Use WiFiClient class to create TCP connections
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}

// We now create a URI for the request
String url = "/trigger/";
url += event;
url += "/with/key/";
url += secretkey;
url += "?value1=";
url += String(temp_act);
url += "&value2=";
url += String(press_act);
url += "&value3=";
url += String(hum_act);

Serial.print("Requesting URL: ");
Serial.println(url);

// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");

// Read all the lines of the reply from server and print them to Serial
while (client.available()) {
String line = client.readStringUntil('\r');
Serial.print(line);
}
}

readData関数でI2C通信を用いてBME280から温度、圧力、湿度データを取得します。

取得したデータはグローバル変数であるtemp_raw, pres_raw, hum_rawに格納され、

さらにcalibration_X (X=T, P, H)関数とスケール変換により実際の値に変換されます。

その後、WiFiClientクラスのインスタンス変数clientを作成し、host変数を用いてIFTTTに接続します。

先ほどの測定値を文字列に変換し、event, secretkeyと連結することでリクエストのためのURIを作成します。

最後にclientインスタンスのprintメソッドでサーバーにGETリクエストを送信します。

さらにサーバーからの返信があればシリアルコンソールに表示します。


Deep sleepモード

 Serial.println("Deep sleep start!");

ESP.deepSleep(300 * 1000 * 1000, WAKE_RF_DEFAULT);
delay(1000);

loop関数の最後に上記のように記述してESP8266をディープスリープさせます。時間の単位はマイクロ秒なので、ここでは止めたい時間である300秒を1,000,000倍しています。

WAKE_RF_DEFAULTと最後のdelay関数に関しては

ESP8266の真骨頂Deep-Sleepモードの使い方

を参考にしてみてください。

deepSleepモードに入ったあとは、設定時間後にもう一度プログラムが再起動されます。起動から接続、データ送信完了まで大体数秒でしょうか。ですので、10秒とか20秒間隔でデータを送信したい場合はdeepsleepモードは有効ではありません。(もっともそんな使い方する人はいないと思いますが。。)


最後に

簡単にですが、ESP8266を用いてIFTTTにセンサ情報を投げる方法を解説しました。

私の使い方としてはwebhookを受け取った後にgoogle spreadsheetに書き込んでいます。

実はこのあとが本当にやりたいことで、google homeと連携して「今の温度は?」と聞いたら答えてくれるようにできたらと思っています。また進展しましたら記事にしたいと思います。