「アレクサ、部屋の温度を教えて」を実現のための第4歩になります。Blynkを導入した目的はESP8266/32で測定した温度データをAlexaへ送るためですが、Blynkアプリを使ってデータの可視化と妥当性の確認をしておきます。
一例として、天井裏の温度を測定しています。夏の暑いときに、いったい天井裏では何度まで上がっているのだろうと気になったのが、天井裏に温度センサをつけるきっかけでした。
これは2年ほど前に作ったものです。今は新しい白地のBlynkアプリに変わっています。ここで書いている従来のBlynkはLegacy Blynkと呼ばれサポート対象外のようです。さらに、local server やBluetoothがなくなっています。
構成
スケッチ
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <BME280_MOD-1022.h>
#include <Wire.h>
#include "Ambient.h"
const char* ssid = "***your ssid***";
const char* password = "***your password***";
char server[] = "192.168.*.**"; // IP for your Local Server
int port = 8080;
//for Blynk
BlynkTimer timer;// Create a Timer object called "timer"
//for Ambient
//#define PERIOD 600 //(sec)Ambientへのデータ送信間隔 ex 600(sec)=10分
int PERIOD = 600 ; //(sec)Ambientへのデータ送信間隔 初期値 ex 600(sec)=10分
unsigned long prev = 0 ; // 前回実行時刻を初期化
unsigned int channelId = ****;//channelId for Ambient
const char* writeKey = "***your writeKey***";//writeKey for Ambient
WiFiClient client;
Ambient ambient;
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "***your token from Blynk***";
unsigned long lastCheck = 0;
double tempMostAccurate, humidityMostAccurate, pressureMostAccurate, WBGT;
char buff[50];
//変数xを小数点以下precision桁の文字列に変換する
void printFormattedFloat(float x, uint8_t precision) {
char buffer[10];
dtostrf(x, 7, precision, buffer);//変数xを7文字の文字列に変換して,bufferに格納。precisionは小数点以下の桁数
Serial.print(buffer);
}
void setup()
{
Serial.begin(115200);
//You can also specify server:
//Blynk.begin(auth, ssid, pass, "blynk-cloud.com", 80);
//Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);
Blynk.begin(auth, ssid, password, server, port); // Blocking until server connected, Blynk local Server
Wire.begin();
// need to read the NVM compensation parameters
BME280.readCompensationParams();
BME280.writeStandbyTime(tsb_0p5ms); // tsb = 0.5ms
BME280.writeFilterCoefficient(fc_16); // IIR Filter coefficient 16
BME280.writeOversamplingPressure(os16x); // pressure x16
BME280.writeOversamplingTemperature(os2x); // temperature x2
BME280.writeOversamplingHumidity(os1x); // humidity x1
BME280.writeMode(smNormal);
ambient.begin(channelId, writeKey, &client); // チャネルIDとライトキーを指定してAmbientの初期化
// Setup a function to be called every 60 seconds
// サーバーへのデータの送信(書き出し)間隔をミリ秒で指定
timer.setInterval(60*1000L, myTimerEvent);
}
void myTimerEvent()//for Blynk
{
tempMostAccurate = BME280.getTemperatureMostAccurate();
humidityMostAccurate = BME280.getHumidityMostAccurate();
pressureMostAccurate = BME280.getPressureMostAccurate();
//今回、作成した暑さ指数近似式:(屋内用)
WBGT = 0.725*tempMostAccurate + 0.0368*humidityMostAccurate + 0.00364*tempMostAccurate*humidityMostAccurate - 3.246;
Blynk.virtualWrite(V0, tempMostAccurate);
Blynk.virtualWrite(V1, humidityMostAccurate);
Blynk.virtualWrite(V2, pressureMostAccurate);
Blynk.virtualWrite(V4, WBGT);
}
BLYNK_WRITE(V3){
//スマホ側 Blynk アプリで設定したスライダー値の受信
int PERIOD_level = param.asInt();
if ( PERIOD_level < 256 ) {PERIOD = 60 ;} //1分周期
else if ( PERIOD_level >= 256 && PERIOD_level < 512 ) {PERIOD = 600 ;} //10分周期
else if ( PERIOD_level >= 512 && PERIOD_level < 768 ) {PERIOD = 3600 ;} //1Hr周期
else if ( PERIOD_level >= 768 && PERIOD_level < 1024) {PERIOD = 10800 ;} //3Hr分周期
Serial.printf("PERIOD_level = %d\r\n", PERIOD_level );
Serial.println((String)"PERIOD = "+ PERIOD + " sec" );
}
void loop()
{
int diff = millis() - lastCheck;
if (diff > 1000) { //1000msごとに
while (BME280.isMeasuring()) {// BME280の計測が終わるまで待機
}
// read out the data - must do this before calling the getxxxxx routines
// getxxxxxルーチンの呼び出し前に、データの読み込みを行う
BME280.readMeasurements(); //1000msごとに、BME280の計測を行う
lastCheck = millis();
} else if (diff < 0) {
lastCheck = 0;
}
Blynk.run();
timer.run(); // Initiates BlynkTimer
unsigned long curr = millis();
if ((curr-prev) >= PERIOD * 1000 ) { //PERIOD secごとに以下の処理を実行
Serial.print((String)"milleis/1000: "+millis()/1000 +" sec, ");
// 読み取った値をシリアルにプリント
Serial.print("Temperature: ");
printFormattedFloat(tempMostAccurate, 1);
//Serial.println("");
Serial.print(" ℃, Humidity: ");
printFormattedFloat(humidityMostAccurate, 1);
//Serial.println("");
Serial.print(" %, Pressure: ");
printFormattedFloat(pressureMostAccurate, 1);
Serial.println(" hpa");
//Serial.println("");
Serial.print(", WBGT: ");
printFormattedFloat(WBGT, 1);
Serial.println(" ℃");
//Serial.println("");
ambient.set(1, tempMostAccurate); // 温度をデータ1にセット
ambient.set(2, humidityMostAccurate); // 湿度をデータ2にセット
ambient.set(3, pressureMostAccurate); // 気圧をデータ3にセット
ambient.send(); // データをAmbientに送信
prev += PERIOD * 1000; // 前回実行時刻に実行周期を加算
}
else if ((curr-prev) < PERIOD * 1000 ) {;}
}
Blynkの設定
iphone側
アプリ初期設定
- 新しいプロジェクトを作成します。(ハードウェアモデルesp8266を使用)
- AUTHTOKENを生成します。
- Eメールトークンを送信します。(ESP8266スケッチでトークンを使います)
アプリ表示設定
上に挙げたスケッチでは、4個のVirtual pin(たぶん、ESP8266のデジタル出力とアナログ出力を区別なく使えるのでVirtual pinという名前にしているのだと思う)を設定しています。これらのデータをアプリに取り込んで表示させます。
アプリではValue Display widget やGauge widgetを使用します。新しいProjectでwidget配置画面(方眼紙のような画面)をタッチすると現れるWidget Box(左下図)から所望のwidgetを選びます。各々のwidgetの設定を行い、右下図のようになりました。
メータ表示がGauge widget、数値表示が3個ともLabeled Valueです。グラフ表示がSuperChartになります。(Blynk local serverを作ったので、widgetが無料で自由に使えます。)
ESP8266側 スケッチ
Blynkの接続設定
SuperChartの設定
"SuperChart"は、ライブデータと履歴データを可視化するために使用されます。センサーデータ、バイナリイベントロギングなどに使用できます。"gauge widget"などでは"Fresh Interval"で更新間隔を指定しています。この更新データを"SuperChart"でも利用しているのですが、次に示すデータをプッシュする設定を行わないと正常なグラフ表示ができません。
Blynk.ccのドキュメントにsuperchartに関して次のように書いてあります。この設定を行います。
To use SuperChart widget you would need to push the data from the hardware with the desired interval by using timers.SuperChartウィジェットを使用するには、タイマーを使用して、ハードウェアから必要な間隔でデータをプッシュする必要があります。
私の自己解釈で補足すると、Blynkにはpull型とpush型があって、アプリを開いてデータを見たりボタンを押して動かすのがpull型です。一方、push型はアプリを開かなくても定期的にセンサを読んだりできます。"SuperChart"はpush型なのでスケッチはpull型と違う書き方をしなければなりません。
14行目:"timer"という名前のBlynkTimer Objectを設定します。delay を使ってプログラムを長い間停止する場合には、Blynk サーバと接続が切れてしまう場合があります。それに比べ、BlynkTimerはBlynkライブラリルーチンに干渉しない正確な一定の間隔で定期的にデータを送信できます。(注記)Blynk.virtualWriteに関しては1秒に10個より多くの値は送らないでくださいとBlynk.ccのドキュメントに書かれています。
Ambientの設定
Ambientではマイコンからデーターを送ってグラフ化まで非常に簡単にできます。 最低限必要なのはAmbientサイトで「チャネル」を作ることと、 マイコン側のプログラムでチャネルIDとライトキーを指定してデーターを送ることだけです。
チャンネル生成
上記の引用元で書いてあるとおりにチャンネルを作ります。
ESP8266側 スケッチ
可視化データ
Blynk
SuperChartの単位横軸を3days(左下図)と1month(右下図)で表示してみました。3月初めのデータです。最高温度は20度を超えています。最低温度は半月くらい前で5度でした。