WebページからESP32のGPIO出力を切り替える【ESP32, ESPAsyncWebServer】

はじめに

以前、ESP32でWebサーバーを立てる方法をご紹介しました。

今回はこれを応用し、WebページからESP32のGPIO出力を切り替えるプログラムを作成します。

構成イメージ

以前と同じようにESP32のWi-Fi設定をsoftAPモードに設定し、Webサーバーを動かします。
また、ESP32のGPIOにLEDを接続します。今回は例としてGPIO25に接続します。

ESP32 Web LED image

ライブラリの準備

Arduino IDEに、必要なライブラリをインストールしていきます。

「ESPAsyncWebServer」、「AsyncTCP」、「Sketch data upload」に加えて、
Webページとのデータのやりとりで使用するJSONを扱えるライブラリの「ArduinoJSON」をインストールします。

Arduino IDEの「ツール」→「ライブラリを管理…」でライブラリマネージャーを開き、「ArduinoJSON」で検索してインストールします。

プログラム

Arduino IDEで以下のようなプログラムを作成・保存して、ESP32に書き込みます。

#include <WiFi.h>
#include "ESPAsyncWebServer.h"
#include "SPIFFS.h"
#include <ArduinoJson.h>

const char ssid[] = "ESP32AP-TEST";
const char pass[] = "12345678";       // パスワードは8文字以上
const IPAddress ip(192,168,123,45);
const IPAddress subnet(255,255,255,0);
AsyncWebServer server(80);            // ポート設定

// Jsonオブジェクトの初期化
StaticJsonDocument<512> doc;

#define LED_PIN 25

uint8_t led_status;  //LEDの状態制御用変数

void setup()
{
  Serial.begin(115200);

  pinMode(LED_PIN, OUTPUT); // GPIO25を出力設定に

  // SPIFFSのセットアップ
  if(!SPIFFS.begin(true)){
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  
  WiFi.softAP(ssid, pass);           // SSIDとパスの設定
  delay(100);                        // このdelayを入れないと失敗する場合がある
  WiFi.softAPConfig(ip, ip, subnet); // IPアドレス、ゲートウェイ、サブネットマスクの設定
  
  IPAddress myIP = WiFi.softAPIP();  // WiFi.softAPIP()でWiFi起動

  // 各種情報を表示
  Serial.print("SSID: ");
  Serial.println(ssid);
  Serial.print("AP IP address: ");
  Serial.println(myIP);

  // GETリクエストに対するハンドラーを登録
  // rootにアクセスされた時のレスポンス
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html");
  });
  // style.cssにアクセスされた時のレスポンス
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/style.css", "text/css");
  });

  // LED の制御変数の変更リクエスト
  server.on(
    "/post_test",
    HTTP_POST,
    [](AsyncWebServerRequest * request){},
    NULL,
    [](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
      String resjson = "";
 
      for (size_t i = 0; i < len; i++) {
        //Serial.write(data[i]);
        resjson.concat(char(data[i]));
      }
 
      Serial.println(resjson);
      DeserializationError error = deserializeJson(doc, resjson);

      if(error){
        Serial.println("deserializeJson() faild");
        request->send(400);
      }
      else{
        led_status = doc["LED_STATUS"];       //zz Tilt Motor Default SPEED
        request->send(200);
      }
  });

  led_status = 0;

  // サーバースタート
  server.begin();

  Serial.println("Server start!");
}

void loop() {
  // LED状態変更
  if(led_status == 0){
    digitalWrite(LED_PIN, LOW);
  }
  else{
    digitalWrite(LED_PIN, HIGH);
  }
  delay(100);
}

 

「data」フォルダの中に「index.html」と「style.css」を以下の内容で作成・保存して、「ESP32 Sketch Data Upload」を実行して書き込みます。

・ index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" charset="UTF-8">
    <title>ESP32 Web Server</title>
    <link rel="icon" href="data:,">
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <h1>ESP32 Web Server</h1>
    <br>
    <div id="btn_msg" style="visibility:hidden;">送信OK</div>
    <br>
    <button type="button" onclick="btn_do_on()" id="btn_led_on">ON</button>
    <br>
    <button type="button" onclick="btn_do_off()" id="btn_led_off">OFF</button>
  </body>
  <script>
    // json返り値のテンプレート
    var json_temp = {
      LED_STATUS: 0
    }

    // 送信ステータス表示
    function btn_msg_display(msg_txt, txt_color){
      var id_btn_msg = document.getElementById("btn_msg")
      id_btn_msg.style.color = txt_color;
      id_btn_msg.textContent = msg_txt;
      id_btn_msg.style.visibility ="visible";
    }

    // タイムスタンプ文字列の作成
    function get_time_stamp() {
      var now_time = new Date();
      var now_date = ('000' + now_time.getFullYear()).slice(-4) + '-' + ('0' + (now_time.getMonth() + 1)).slice(-2) + '-' + ('0' + now_time.getDate()).slice(-2);
      var now_time_val = ('0' + now_time.getHours()).slice(-2) + ':' + ('0' + now_time.getMinutes()).slice(-2) + ':' + ('0' + now_time.getSeconds()).slice(-2);
      var time_stamp = now_date + " " + now_time_val + " ";
      return time_stamp;
    }

    // LEDの状態変更リクエストの送信
    function send_status(send_status){
      var str_status = "";
      if(send_status == 0){
        str_status = "LED_OFF";
      }
      else{
        str_status = "LED_ON";
      }

      // JSONデータの作成
      var send_json = json_temp;
      send_json.LED_STATUS = send_status;
      send_json = JSON.stringify(send_json);

      // リクエストを送信
      var xhr = new XMLHttpRequest()
      xhr.open("POST", "/post_test", true)
      xhr.setRequestHeader("Content-Type", "application/json")
      xhr.timeout = 5000; // タイムアウト設定(ms)
      xhr.onload = () => {
        btn_msg_display(get_time_stamp() + str_status + " 送信 OK", "#00aa00");
      };
      xhr.onerror = () => {
        btn_msg_display(get_time_stamp() + str_status + " 送信 NG", "#ff0000");
      };
      xhr.ontimeout = () => {
        btn_msg_display(get_time_stamp() + str_status + " 送信 タイムアウト", "#ff0000");
      };
      xhr.send(send_json)
    }

    // ONボタン動作
    function btn_do_on(){
      send_status(1);
    }

    // OFFボタン動作
    function btn_do_off(){
      send_status(0);
    }
  </script>
</html>

・ style.css

html {
  font-family: Helvetica;
  display: inline-block;
  margin: 0px auto;
  text-align: center;
}
h1{
  color: #0F3376;
  padding: 30px;
  font-size: 1.5rem;
}
button{
  font-size: 2.0rem;
  width: 180px;
  height: 75px;
  margin: 10px;
  border-radius: 3px;
}
#btn_led_on{
  color: #cc0000;
  border: solid 2px #cc0000;
  background-color: #ffcccc;
}
#btn_led_off{
  color: #00cccc;
  border: solid 2px #00cccc;
  background-color: 7acccc;
}

動作

PCやスマホ等をESP32のアクセスポイントに接続し、Webブラウザから設定したIPアドレス(例: 192.168.123.45)にアクセスします。

画面上の「ON」ボタンを押すとLEDが点灯します。

ESP32 Web DISP ON
ESP32 Web LED ON

 

「OFF」ボタンを押すとLEDが消灯します。

ESP32 Web DISP OFF
ESP32 Web LED OFF

おわりに

WebページからESP32のGPIO出力を切り替えるプログラムをご紹介しました。
このプロラグムを利用すれば、プログラムの設定値をスマホ等のWebブラウザから手軽に変更できるようになります。
様々な応用ができそうなので、今後のものづくりに生かしていきたいと思います。

よかったらシェアしてね!