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

 前回作成したloop()の処理は、1秒ごとに温度を測定しLCDに表示する内容でした。1秒ごとの計時を、delay(1000)で行っています。そのため、delay(1000)関数を実行中、クライアントからのアクセスがあっても対応できない状態になっています。

1秒間に1回行う処理の記述

 これを改善するには、millis()関数で経過時間を調べ1000で除算し1秒経過したことを確認し(millis() / 1000)に1回の処理を行います。具体的なコーディングは次のように行います。

① 整数bpより(millis() / 1000)が大きくなるまで繰り返し待ちます。大きくなったらbpに(millis() / 1000)をセットし次に進みます。

if (bp < (millis() / 1000)) {
    bp = millis() / 1000;
}

② bpと(millis() / 1000))が等しいとき、(millis() / 1000)に1回の処理を行うタイミングとなります。この条件の確認したとき、最初にbpカウントアップするので、①の条件を満たすのは(millis() / 1000)経過後となります。

if (bp == (millis() / 1000)) {
    bp = bp + 1;
  ここに(millis() / 1000)に1回の処理を記述する

ページが見つからない場合の処理

 AdvencedWebServerのサンプル・プログラムには、ページが見つからなかった場合の応答の処置が用意されています。

  handleNotFound()関数

 この関数の中で、ページが見つからない場合の表示画面について記述します。また、このサンプル・プログラムには、アクセスしたページのアドレス、クライアントとサーバとの間のデータのやり取りの方法がGETかPOSTの表示で、受け渡しデータの名前と値が表示されるようになっています。ページが見つからない場合の警告ならページのアドレスは必須ではありませんが、あると原因を確認するのに便利です。その他のデータはなくてもかまいません。
 しかし、クライアントからサーバとの間のデータの受け渡しは、サーバに送ってもらうデータを知らせるなどで必要となるので、サンプル・プログラムで動作の確認を行います。GET、POSTによるデータの受け渡し方法を、確認します。
 処理の手順は次のようになります。

①ページが見つからない場合起動する関数handleNotFound()を用意します。ページが見つからないことを示すメッセージを文字列として作成します。この関数で表示文字列messageをブラウザに表示するserver.send(404, "text/plain", message);命令を実行して、この関数を終えます。

②setup()関数の中でページが見つからなかった場合に、先ほど作成したhandleNotFound ()を起動する関数をセットし起動するようにserver.onNotFound(handleNotFound);の命令を実行します。

ページが見つからない場合の関数handleNotFound()

(server.method() == HTTP_GET) ? "GET" : "POST"は(server.method() == HTTP_GET)の結果が等しいときはGETが選択され、等しくないときはPOSTが選択されます。
void handleNotFound(){ // 文字列のオブジェクトmessageに表示内容をセットする
String message = "File Not Found\n\n"; // \nは改行を示す\n\nは2行の改行を示す
message += "URI: "; // ページのアドレスを表示するための見出し
message += server.uri(); // ブラウザから送られたページのアドレスを取り出す
message += "\nMethod: "; // メソッドを表示するための
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: "; // GET、またはPOSTのパラメータの数の見出し
message += server.args(); // GETまたはPOSTのパラメータの数が得られる
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) { // パラメータの数for分で繰り返し名前と
message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; // 値を文字列に追加
}
server.send(404, "text/plain", message); // メッセージを送信
}

テスト結果

 IPアドレスは正しいのですが/klm/のページは設定していません。しかし、GETでパラメータの設定?マーク以下で次のように行っています。

  http://192.168.1.66/klm/?name1=val1&name2=val2&name3=val3

 実行結果は、次に示すようになりました。File Not Foundでページが見つからなかった場合のメッセージが表示されています。メソッドはGET、パラメータの名前と値は、設定値と同じものが表示されています。

 今までの修正結果をまとめると次のようになります。

#include <Wire.h>
#include <i2clcd.h>
#include <WiFi.h>
#include <WebServer.h>
const char ssid[] = "Buff******C6E";
const char password[] = "************";

WebServer server(80);

IPAddress ipadr;
int n = 0;
int bp = 0;
unsigned char tmp2_adr = 0x48;
i2clcd qlcd(0x3E, 3, 0x20); // 具体的な処理を行うためのオブジェクトを作る

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;
}

void handleRoot() { // ブラウザからアクセスに応答する関数
char temp[400];
int sec = millis() / 1000;
int min = sec / 60;
int hr = min / 60;
float tvalue = get_tmp102(tmp2_adr);
snprintf(temp, 400,
"<html>\
<head>\
<meta http-equiv='refresh' content='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: %2d:%2d:%2d</p>\
<p>Temperature: %8.2f</p>\
</body>\
</html>",
hr, min % 60, sec % 60,
tvalue
);
server.send(200, "text/html", temp);
}

void handleNotFound(){ // 文字列のオブジェクトmessageに 表示内容をセットする
String message = "File Not Found\n\n"; // \nは改行を示す\n\nは2行の改行を示す
message += "URI: "; // ページのアドレスを表示するための見出し
message += server.uri(); // ブラウザから送られたページのアドレスを取り出す
message += "\nMethod: "; // メソッドを表示するための
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += "\nArguments: "; // GET、またはPOSTのパラメータの数の見出し
message += server.args(); // GETまたはPOSTのパラメータの数が得られる
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) { // パラメータの数for分で繰り返し名前と
message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; // 値を文字列に追加
}
server.send(404, "text/plain", message); // メッセージを送信
}

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);
qlcd.lcdcu_set(0, 1); // LCDモジュールにIPアドレスをここで表示する
qlcd.i2cprint(String(ipadr[0]) + "." + String(ipadr[1]) + ".");
qlcd.i2cprint(String(ipadr[2]) + "." + String(ipadr[3]));
server.on("/", handleRoot); // ルート・フォルダ・アクセス時handleRoot関数を実行
server.onNotFound(handleNotFound); // ページがないときの応答設定
server.begin(); // サーバを開始
Serial.println("HTTP server started");
}

void loop(void) {
server.handleClient();
if (bp < (millis() / 1000)) {
bp = millis() / 1000;
}
if (bp == (millis() / 1000)) {
bp = bp + 1;
qlcd.lcdcu_set(0, 0); // LCDモジュールのカーソルを先頭に
n = n + 1;
qlcd.i2cprint(String(n)); // カウンタの値をLCDへ表示
qlcd.i2cprint(":");
qlcd.i2cprint("temp2="); // 見出しをLCDへ表示
qlcd.i2cprint(String(get_tmp102(tmp2_adr))); // 測定温度を表示
}
}

 このプログラムの実行結果を次に示します。

 今まで確認したWebServerを利用するための準備は、次のようになります。

① 該当するページがアクセスされたときに、ブラウザに表示するデータを用意し表示する関数を準備する。

② アクセスされたアドレスに対応して起動する関数の関係を設定する。
    server.on("/", handleRoot);

③ サーバを起動する。
    server.begin();

④ loop()関数の中でクライアントの処理を行う関数を起動する。
    server.handleClient();

 次回からは、このシリーズで確認したWebサーバを利用して、ボタンによるON/OFF制御、ON/OFFの状態の確認などを新しいシリーズで行う予定です。

(2019/4/9 V1.0)

<神崎康宏>

前へ

はじめてのModbus (2) Lチカ

次へ

はじめてのModbus (3) 温湿度