ESP32入門 通信機能が標準搭載されたマイコン・ボード (9) 測定した温度をWebに表示①

 前回までで、Wi-Fi経由のネットワークへの接続が行えました。今回は、PCからアクセスされたときにESP32が測定した温度データを表示し、その表示を定期的に更新することを考えます。基本的な枠組みは、サンプル・プログラムのAdvencedWebServerに基づいています。

WebServerライブラリを利用する

 PCのWebブラウザからIPアドレスで問い合わせがあった場合、ESP32は問い合わせ元のPCのブラウザに応答メッセージ表示データを送信します。
 表示データは、サーバからの経過時間と測定した温度です。この表示は、PCのブラウザからの問い合わせがなくても定期的に更新されるようにします。そのために、PCのブラウザの表示は定期的に最新の測定結果で更新されることになります。

ブラウザに表示する画面の作成(handleRoot()関数)

 Webサーバからの応答として表示される画面は、handleRoot()関数の中でHTMLの画面の表示データを用意します。

  snprintf(temp,400,“HTMLによる表示のためのデータ”)

で、文字列配列tempにブラウザの画面表示のHTML文書をセットします。tempに文字列として定義したクライアントへの表示画面データは、

  server.send(200, "text/html", temp);

で、クライアントのブラウザに送られ表示されます。初期化処理を行うsetup()関数内の、

  server.on("/", handleRoot);

命令で、クライアントからの問い合わせ時にhandleRoot()関数を実行するように設定します。メインの処理となるloop()関数内で、

  server.handleClient();

によりクライアントからのアクセスの処理を行います。

ヘッダ・フィルの読み込み

 今回新しくWebServerライブラリを追加するので、WebServer.hのインクルードを追加します。その他は、前回のヘッダ・ファイルの読み込みと同じです。

#include <Wire.h>
#include <i2clcd.h>
#include <WiFi.h>
#include <WebServer.h>

Wi-FiのSSID、パスワードの設定

 SSIDとパスワードを文字列で定義します。ともにダミーを設定しているので、実際のWi-Fiの環境に合わせて設定してください。

const char ssid[] = "Buffalo-G-2C6E";
const char password[] = "hxxxx3kvvvv3d";

オブジェクトの生成

 前回は、I2C経由でLCDに書き込むライブラリから、実際にデータの処理を行うオブジェクトglcdを生成しました。今回はこれに追加してWebサーバの処理を行うインスタンスをserverの名前で作成します。()内は使用するポート番号を設定します。80は、HTTP通信で使われる最も一般的なポートです。

i2clcd qlcd(0x3E, 3, 0x20); // 具体的な処理を行うためのオブジェクトを作る
WebServer server(80);

変数、定数の設定

IPAddress ipadr;
int n = 0;
unsigned char tmp2_adr = 0x48; // 温度センサのスレーブ・アドレス

温度センサから温度を読み取る関数

 I2Cのデバイスとの通信を行うためのライブラリがWireライブラリです。このライブラリを利用して、温度センサからの気温データを読み取って結果を戻り値としている関数です。
 温度センサTMP102のI2Cのスレーブ・アドレスを引数としてこの関数を呼び出すと、実数型の戻り値が測定結果として得られます。

float get_tmp102(unsigned char tmp0_adr) { // 温度センサを読み取る関数
Wire.requestFrom(tmp0_adr, 2);
while (Wire.available() < 2) {
}
int tmpin = Wire.read() * 16;
tmpin = tmpin + (Wire.read() >> 4);
return 0.0625 * tmpin;
}

クライアントから問い合わせがあったとき起動される関数

 HTML文で、クライアントに表示するデータを文字列にセットして、クライアントに書き出します。最初にmillis()関数で経過時間をチェックし、変数sec、min、hrにセットします。併せて、get_tmp102(tmp2_adr)で気温の測定を行い、実数変数tvalueにセットします。

void handleRoot() {
char temp[400];  // 
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;
float tvalue = get_tmp102(tmp2_adr);

 次のsnprintf()関数で最大400文字までの文字列として、表示データを文字列にセットします。
 経過時間、気温の表示書式は、文字列の中のUptime:、Temperature:に続く変換指定子%2d、%2d、%2d、%8.2fで行っています。変換指定子は%で始まります。%に続く次の数字は、数値の表示桁数です。次のdは10進数表示を示します。fは実数表示で少数の右側の2は小数点以下の表示桁数を示します。カラー・コードは、RGBの強さをそれぞれ2桁の16進表示で、3色合計を6桁の16進数で表しています。文字の色は3色0のブラックを指定しています。
 背景は#40e0d0と各色をブレンドして、明るい青緑色に設定しました。>¥の¥は次の行への継続を示しtempの文字列にセットされるときは¥と次の改行コードは無視されます。

    snprintf(temp, 400,
"<html>\ // ブラウザで表示するためのHTML文書の開始を示す
<head>\ // 次のhttp-equiv='refresh'で自動更新が指定されている
<meta http-equiv='refresh' content='3'/>\ // 間隔は3秒に設定されている
<title>Denshi Club ESP32 test</title>\ // 文書のタイトルで画面には表示されない
<style>\ // バックグラウンドのカラー・コード、フォント、文字の色を指定
body{background-color:#40e0d0;font-family:Arial,Helvetica,Sans-Serif;Color:#000000;}\
</style>\
</head>\
<body>\
<h1>Temperature from ESP32</h1>\
<p>Uptime: %02d:%02d:%02d</p>\
<p>Temperature: %8.2f</p>\
</body>\
</html>",
hr, min % 60, sec % 60,
tvalue
);

 書式で示した順番に時、分、秒、気温に対応して並べます。分と秒表示時に再計算しています。

    server.send(200, "text/html", temp); //ここでクライアントに送信している
}

最初に1回だけ実施する処理がまとめられた関数

 今回Webサーバの処理のために追加された命令は、最後の3行だけです。それ以外はLCDモジュールの初期化処理と開始を示すstartの表示、シリアル通信の初期化、Wi-Fiの設定・接続・IPアドレス確認の表示です。

void setup(void) {
qlcd.init_lcd(); // LCDモジュールの初期化処理
qlcd.i2cprint("start:");
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
ipadr = WiFi.localIP();
Serial.println(ipadr); // ここまででWi-Fiに接続し、IPアドレスが判明している
server.on("/", handleRoot); // クライアントからのアクセスで起動する関数を指定
server.begin(); // サーバを開始
Serial.println("HTTP server started");
}

繰り返し終わりなく処理される関数

 Webサーバの追加で加わった命令は server.handleClient()のみで、この関数がクライアントからのアクセスに対応します。その他は、1秒ごとに気温を測定し表示しています。

void loop(void) {
server.handleClient(); // この処理でクライアントからのアクセスに対応
qlcd.lcdclear(); // LCDモジュールのクリア
n = n + 1;
qlcd.i2cprint(String(n)); // カウンタの値をLCDへ表示
qlcd.i2cprint(":");
qlcd.i2cprint("temp2="); // 見出しをLCDへ表示
qlcd.i2cprint(String(get_tmp102(tmp2_adr))); // 測定温度を表示
qlcd.lcdcu_set(0, 1);
qlcd.i2cprint(String(ipadr[0]) + "." + String(ipadr[1]) + ".");
qlcd.i2cprint(String(ipadr[2]) + "." + String(ipadr[3]));
delay(1000);
}

 プログラムを、次のようにArduino IDEで作成しボードに書き込みます。

 スケッチが動き始めて、LCDモジュールに表示されたIPアドレスを、PCのWebブラウザのURLにセットしてアクセスすると、次に示すように、経過時間と気温が表示されます。後は何もしなくても設定された3秒ごとに更新されます。

 スマートホンでも、Google Chromeで確認したIPアドレスをセットすると次のような結果を得ました。


 LEDモジュールへの表示は前回までのプログラムと同じで、delay(1000)でほとんどの時間を待ち処理に費やしています。その期間外部から対応できないので改善の余地があります。また、エラーの処理などの追加の必要があります。次回検討します。

(2019/3/25 V1.0)

<神崎康宏>

前へ

はじめてのMKR ZERO (5) RTC

次へ

はじめてのMKR ZERO (6) 距離センサVL53L1X