ESP32でWEBサーバーをホストする方法(1)

マイコン/Arduino

ESP32はWiFi機能を備えた高性能マイコンで、WEBサーバー(HTMLサーバー)をホストすることが可能です。今回は最も簡単な方法(例)をいくつか紹介します。

前提

ESP32を既存の無線LANに接続し、WEBサーバーをホストする方法を紹介します。ESP32をアクセスポイントにしてサーバーをホストする方法ではありません。

なお、今回のArduinoスケッチは全てESP32-C3での動作確認を行っています。また、開発環境はArduinoIDE 1.18.16です。

テキストデータを返すサーバー

まずはもっとも簡単な例からです。

#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>

const char *ssid = "******"; // WifiのSSID
const char *pass = "******"; // Wifiのパスワード
WebServer Server(80); // ポート番号(HTTP)

void SendMessageRoot() {
 String message = "This Page is hosted by ESP32";
 Server.send(200, "text/plain", message);
}
void SendMessageHoge() {
 String message = "hogehoge";
 Server.send(200, "text/plain", message);
}
void Send404() {
 Server.send(404, "text/plain", "404 not found");
}

void setup() {
 //WiFi接続
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, pass);

 while (WiFi.status() != WL_CONNECTED) {
  if (WiFi.status() == WL_CONNECT_FAILED) {
  delay(10);
  }
 }
 MDNS.begin("webserver_ESP32");

 Server.on("/", SendMessageRoot); //ホストのルートにアクセスした場合
 Server.on("/hoge",SendMessageHoge);// /hogeにアクセスした場合
 Server.onNotFound(Send404);//見つからなかった場合
 Server.begin();
}

void loop() {
 Server.handleClient();
}

動作

以下スケッチを書き込み後、WEBブラウザからhttp://webserver_ESP32.localにアクセスすると

This Page is hosted by ESP32

と表示されるはずです。

解説

以下の部分でそのページにアクセスしたときの挙動を決定しています。

Server.send(200, "text/plain", message);

ここでは単純なテキストを返すため”text/plain”としています。

また、接続先はIPアドレスで指定してもOKですがESP32に割り当てられたIPアドレスを知る方法は面倒(外部ディスプレイに表示する、シリアルで返す…など)です。そこで今回はMDNSを用いてホスト名を設定しています。自宅内での使用であれば好きな名前を設定すればOKです。

MDNS.begin("webserver_ESP32");

HTMLを返すサーバー

次にHTMLを返す例です。基本的には先の例とほぼ同じですがHTMLタグが必要になる分だけ少々面倒です。

#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>

const char *ssid = "******"; // WifiのSSID
const char *pass = "******"; // Wifiのパスワード
WebServer Server(80); // ポート番号(HTTP)

void SendMessageRoot() {
 String htmlHeader = "<!DOCTYPE html><html lang=\"ja\"><head><meta charset=\"utf - 8\"><title>ESP32 WEB SERVER</title></head><body>";
 String htmlBody = "This WEB PAGE IS HOSTED BY ESP32-C3";
 String htmlFooter = "</body></html>";
 String message = htmlHeader + htmlBody + htmlFooter;
 Server.send(200, "text/html", message);
}

void setup() {
 //WiFi接続
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, pass);

 while (WiFi.status() != WL_CONNECTED) {
  if (WiFi.status() == WL_CONNECT_FAILED) {
  delay(10);
  }
 }
 MDNS.begin("webserver_ESP32");

 Server.on("/", SendMessageRoot); //ホストのルートにアクセスした場合
 Server.begin();
}
void loop() {
 Server.handleClient();
}

動作

以下スケッチを書き込み後、WEBブラウザからhttp://webserver_ESP32.localにアクセスすると

THIS WEB PAGE IS HOSTED BY ESP32-C3

と表示されるはずです。

解説

まず、htmlを返すことを明示するために以下の部分を変更します。

Server.send(200, "text/html", message);

また、htmlの内容は以下の3つの変数に分けて書いています。(もちろん最初からひとまとめにしても問題ないです)

String htmlHeader
String htmlBody
String htmlFooter

少し読み書きしにくいですが、通常のHTMLをこの中に仕込んでおけばよいです。1点注意したいのはダブルクオーテーション(“)です。htmlタグの中では”を使用することが多いですが、Stringの都合上バックスラッシュ(\)でエスケープする必要があります。

 String htmlHeader = "<!DOCTYPE html><html lang=\"ja\"><head><meta charset=\"utf - 8\"><title>ESP32 WEB SERVER</title></head><body>";
環境によってバックスラッシュが円マークになる場合があります。これは古代の取り決めによって生じた、日本語環境特有の文字化けです。

WEBページからGPIOを制御する

WEB上でGPIOのON/OFFを使えるようにします。これができないとマイコンの意味がありませんね。

特定のページが叩かれるとLEDがON/OFFするようにします。回路図等は書きませんが、GPIO20にLED(と抵抗)が接続されているとします。

#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>

#define LED_PIN 20

const char *ssid = "******"; // WifiのSSID
const char *pass = "******"; // Wifiのパスワード
WebServer Server(80); // ポート番号(HTTP)

void SendMessageRoot() {
 String htmlHeader = "<!DOCTYPE html><html lang=\"ja\"><head><meta charset=\"utf - 8\"><title>ESP32 WEB SERVER</title></head><body>";
 String htmlBody = "THIS WEB PAGE IS HOSTED BY ESP32-C3";
 String htmlFooter = "</body></html>";
 String message = htmlHeader + htmlBody + htmlFooter;
 Server.send(200, "text/html", message);
}
void SendMessageLedON(){
 String message = "LED ON!";
 Server.send(200, "text/plain", message);
 digitalWrite(LED_PIN, HIGH);
}
void SendMessageLedOFF(){
 String message = "LED OFF!";
 Server.send(200, "text/plain", message);
 digitalWrite(LED_PIN, LOW);
}

void setup() {
 //LEDピンの出力設定
 pinMode(LED_PIN, OUTPUT);
 digitalWrite(LED_PIN, LOW);

 //WiFi接続
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, pass);

 while (WiFi.status() != WL_CONNECTED) {
 if (WiFi.status() == WL_CONNECT_FAILED) {
  delay(10);
 }
}
MDNS.begin("webserver_ESP32");

Server.on("/", SendMessageRoot); //ホストのルートにアクセスした場合
Server.on("/ledon", SendMessageLedON); //LEDをONにする
Server.on("/ledoff", SendMessageLedOFF); //LEDをOFFにする
Server.begin();
}
void loop() {
 Server.handleClient();
}

動作確認

http://webserver_ESP32.local/ledon にアクセスするとLEDが点灯し

http://webserver_ESP32.local/ledoff にアクセスするとLEDが消灯するはずです。

解説

特定のページが叩かれたときに特定の関数を呼び出すという構造になっていますので、その呼び出された関数の中でGPIOの制御を行えばOKです。基本的なArduinoの使い方と同じです。

Lチカであれば、setup()関数内で出力ピンの設定&呼び出された関数の中でdigitalWrite()すればOKです。

ちなみに、呼び出された関数内でGPIOの操作のみを行い、メッセージを返さなくても良いですがブラウザからは”動作していないページ”と見えてしまいます。(GPIOの操作自体は正常に行われる)

まとめ

いかがだったでしょうか。今回はESP32で簡単にWEBサーバーを作ってGPIOの操作などを行う方法を紹介しました。

ESP32で取得したデータを表示したり、WEBページ上のボタンを操作してGPIOの制御を行えればより便利&楽しそうですよね。そのあたりはまた別に解説します。

コメント