お得なAmazonタイムセールはこちら

【ESP32】Wi-Fiからシリアル通信・エスケープシーケンスも・RS-232C・UART・ハードウェア学習

プログラミング
質問する人
質問する人

Wi-Fi経由でESP32を制御して、シリアル通信(RS-232C)を行いたいな。ついでにエスケープシーケンスの送り方も知りたい。

こんな質問にお答えします。

◆この記事の内容
・Wi-Fi経由でシリアル通信(UART)のコマンドを送る方法が分かります
・エスケープシーケンスの送り方が分かります
うまし
うまし

ハードウェアエンジニア歴15年のうましが解説します。

スポンサーリンク

Wi-Fi経由でシリアル通信

今回はESP32を使用してWi-Fi経由でシリアル通信(UART)を行い、コマンドを送ります。海外のこちらの記事を参考にさせて頂いた前回のスケッチをベースに変更を行います。

【変更前】
GPIOの制御を行うたびに出力されるコマンドが多すぎます。緑の部分だけを取り出したいと思っています。

【変更後】
必要な部分だけを取り出します。

ESP32_Wi-Fi経由でシリアル通信2

開発環境

・OS : Windows10 64bit
・Arduino IDE1.8.13

使用した機材

Arduino IDEのスケッチ

前回のスケッチから以下をコメントアウト(もしくは削除)します。

//これらはお好みで残す/コメントアウトするか調整してください
Serial.println("New Client.");

Serial.write(c);

Serial.println("Client disconnected.");
Serial.println("");

こちらが修正後のソースコードです。

//コメントは原文を訳させて頂きました
/*********
シリアルをシンプルにする
reference
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/

//WiFi.hをインクルード
#include <WiFi.h>

//Wi-Fiのssidとpasswordに置き換えてください
const char* ssid     = "********";
const char* password = "******";

//ポート80にセット
WiFiServer server(80);

// HTTPリクエスト
String header;

//制御するピンの状態
String output26State = "off";
String output27State = "off";

//数値だけだと分かりづらいのでoutputxxと表記
const int output26 = 26;
const int output27 = 27;

//現在の時間
unsigned long currentTime = millis();
//以前の時間
unsigned long previousTime = 0; 
//タイムアウト時間
const long timeoutTime = 2000;

void setup() {
    Serial.begin(115200);     //シリアル通信のボーレート設定
    //GPIOピンの初期設定
    pinMode(output26, OUTPUT);
    pinMode(output27, OUTPUT);
    //LOWに設定
    digitalWrite(output26, LOW);
    digitalWrite(output27, LOW);

    //Wi-Fiに接続
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    //IPアドレスをシリアル通信で出力してWebサーバーとしてスタート
    Serial.println("");
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();
}

void loop(){
    WiFiClient client = server.available();   //クライアント(スマホなど)の接続を確認

    if (client) {                             //もし新しいクライアントが接続されていたら
        currentTime = millis();
        previousTime = currentTime;
//        Serial.println("New Client.");          //New Client.をシリアル通信出力する
        String currentLine = "";                //clientから入力されるデータの保持用の変数
        while (client.connected() && currentTime - previousTime <= timeoutTime) {  //クライアントが接続されている間のwhileループ
            currentTime = millis();
            if (client.available()) {             //もしクライアントからコマンドが来ている時
                char c = client.read();             //コマンドを読み込む
//                Serial.write(c);                    //シリアルモニターに表示
                header += c;
                if (c == '\n') {                    //改行コード(エスケープシーケンス¥n)ならば
                // もし現在の行が空白ならば、この改行コードのみ受け取る
                // つまりHTTPリクエストの終わりなので、レスポンスを返す 
                    if (currentLine.length() == 0) {
                    //HTTPヘッダーはHTTP/1.1 200 OKのようなコードで始まることが多い
                    //コンテントタイプなどの送信
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-type:text/html");
                    client.println("Connection: close");
                    client.println();
            
                    //GPIOのON/OFF制御
                    if (header.indexOf("GET /26/on") >= 0) {
                        Serial.println("GPIO 26 on");   
                        output26State = "on";
                        digitalWrite(output26, HIGH);
                    } else if (header.indexOf("GET /26/off") >= 0) {
                        Serial.println("GPIO 26 off");
                        output26State = "off";
                        digitalWrite(output26, LOW);
                    } else if (header.indexOf("GET /27/on") >= 0) {
                        Serial.println("GPIO 27 on");
                        output27State = "on";
                        digitalWrite(output27, HIGH);
                    } else if (header.indexOf("GET /27/off") >= 0) {
                        Serial.println("GPIO 27 off");
                        output27State = "off";
                        digitalWrite(output27, LOW);
                    }
            
                    //htmlページを表示
                    client.println("<!DOCTYPE html><html>");
                    client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
                    client.println("<link rel=\"icon\" href=\"data:,\">");

                    // ON/OFFを切り替えるためのCSSを記述(ON = オレンジ/OFF = 灰色)
                    client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
                    client.println(".button { background-color: #FFAA05; border: none; color: white; padding: 16px 40px;");
                    client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
                    client.println(".button2 {background-color: #555555;}</style></head>");
            
                    //H1として『ESP32 Web Server』と出力
                    client.println("<body><h1>ESP32 Web Server</h1>");
            
                    //26ピン状態とON/OFFを表示
                    client.println("<p>GPIO 26 - State " + output26State + "</p>");
                    //output26StateがOFFなら、OFFを表示     
                    if (output26State=="off") {
                        client.println("<p><a href=\"/26/on\"><button class=\"button button2\">OFF</button></a></p>");
                    } else {
                        client.println("<p><a href=\"/26/off\"><button class=\"button\">ON</button></a></p>");
                    } 
               
                    //27ピン状態とON/OFFを表示
                    client.println("<p>GPIO 27 - State " + output27State + "</p>");
                    //output27StateがOFFなら、OFFを表示        
                    if (output27State=="off") {
                        client.println("<p><a href=\"/27/on\"><button class=\"button button2\">OFF</button></a></p>");
                    } else {
                        client.println("<p><a href=\"/27/off\"><button class=\"button\">ON</button></a></p>");
                    }
                    client.println("</body></html>");
            
                    //HTTPレスポンスを改行で終了
                    client.println();
                    //whileルールを終了
                    break;
                } else { //改行コードを取得したら、currentLineをリセット
                    currentLine = "";
                }
                } else if (c != '\r') {  //改行(¥n)以外のコマンドが来た場合
                    currentLine += c;      // currentLineに足す
                }
            }
        }
        //headerをクリア
        header = "";
        //接続を終了
        client.stop();
//        Serial.println("Client disconnected.");
//        Serial.println("");
    }
}

IPアドレスの確認方法

「ツール→シリアルモニタ」を選択してください。

ESP32_Wi-Fi経由でLED制御3

基板内の『EN』を押します。互換品では『RST』と記載されている場合もあります。

ESP32_Wi-Fi経由でLED制御4

IPアドレスが表示されます。

ESP32_Wi-Fi経由でLED制御5

同じネットワーク(Wi-Fi)に接続したクライアント(スマホ、パソコン、タブレットなど)のブラウザのアドレスバーにIPアドレスを入力します。

ボタンを操作すると必要な部分だけをシリアル通信するように変更できました。

ESP32_Wi-Fi経由でLED制御6

ESP32_Wi-Fi経由でシリアル通信2

ArduinoやESP32でエスケープシーケンスを送る

//e.g.
//ESC
const char ESC  = '\e';
Serial.print(ESC); 

//CR
const char CR   = '\r';
Serial.print(CR); 

//TAB
const char TAB  = '\t';
Serial.print(TAB);
うまし
うまし

よろしければ、サイトやブログでリンクを貼って紹介してもらえると今後のやる気につながります!