Ⅵ. ESP32WebサーバーのリレーモジュールON/OFF制御

 Webサーバーにリレーモジュールを組み合わせて、リモート操作できるスイッチとして動作させることができます。例えば、リレーモジュールに接続された家電製品の電源をON/OFF制御することが可能になります。
 今回は、監視用デバイスに接続した2チャンネルのリレーモジュールへ外部回路を接続して、Webブラウザーのボタンで操作してみます。外部回路は商用電源を扱うこともできますが、ここでは電池と豆電球で接続確認を行います。


 ※スケッチのダウンロードは右側の[Download]ボタンをクリックしてください。    


1.リレーモジュール

 リレーモジュールとして「2 CHANNEL 5V 10A RELAY MODULE」を使うことにしました。以前に購入したセンサーモジュールセットに入っていたものですが、単体ならAmazonで200円前後で入手できると思います。

    


 左写真のように5Vの2チャネル・リレー・インタフェース・ボードで、VCCはESP32の5V(VINピン)から供給し、GNDどうしをつないで使用します。IN1とIN2には、それぞれESP32の作動用GPIOピンを接続します。
 このリレーは負論理で動作します。IN1、IN2の各ピンはLOW信号を送信するとオンになり、HIGH信号を送信するとオフになります。

    

 リレーの高圧側にはCOM(コモン)、NC(ノーマルクローズ)、NO(ノーマルオープン)の3つの端子が2セットあります。それぞれ、COMとNOまたはCOMとNCの間で回路を構成します。
 NCはリレーが動作していない状態で閉じていて、動作すると開きます。NOはその逆になります。ここではリレーが動作した時に回路を閉じたいので、NOを使うことにします。

 高圧側は、AC250V 10AあるいはDC30V 10Aに対応しています。モーターなど始動電流が大きいもの(定格の5~7倍になる)には注意が必要ですが、かなり大電流に対応できます。


2.リレーと電気回路の配線

 リレーモジュールは監視用デバイスに組み込むことにします。リレーの制御側はESP32の該当ピンと下図のように配線します。

    


〔リレー制御側〕
 ・リレー側VCC(赤線) → ESP32側VIN(5V)
 ・リレー側IN1(緑線) → ESP32側GPIO26
 ・リレー側IN2(青線) → ESP32側GPIO27
 ・リレー側GND(黒線) → ESP32側GND

 リレーの接点側には商用電源と電球などを接続できますが、今回は電池と豆電球で通電確認を行います。ホームセンターへ出かけて、写真のような小物を買ってきました。

    

 接点側の配線は次のようにします。

    


〔リレー1接点側〕
 ・リレー側COM(赤線) → 電池マイナス
 ・リレー側NO (黒線) → 赤色豆電球
 ・赤色豆電球 (黒線) → 電池プラス

〔リレー2接点側〕
 ・リレー側COM(黄線) → 電池マイナス
 ・リレー側NO (黒線) → 緑色豆電球
 ・緑色豆電球 (黒線) → 電池プラス



3.コードの解説

①ヘッダーファイルとデータ等の定義

・28~29行 環境に合った情報を設定してください!
・36~39行 リレーのピン番号とON/OFF状態保持用です。
・70~73行 2回路のために2つのボタンと状態表示を配置しています。
#include <Arduino.h>
#include <WiFi.h>

/* Function Prototype */
void doInitialize();
void httpListen();
void httpRequestProccess(String*);
void httpSendResponse(WiFiClient*);
void connectToWifi();

/* 基本属性定義  */
#define SPI_SPEED   115200          // SPI通信速度

// ルーター接続情報
#define WIFI_SSID "your_ssid"
#define WIFI_PASSWORD "your_password"
#define HTTP_PORT 80

// Webサーバーオブジェクト
WiFiServer server(HTTP_PORT);

// リレー制御情報
const int relay1Pin = 26;
const int relay2Pin = 27;
String relay1State = "OFF";
String relay2State = "OFF";

/* HTMLレスポンスヘッダー */
const String strResponseHeader = "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n"
        "Connection:close\r\n\r\n";

/* HTMLページ構成要素 */
// (ページヘッダー部)
const String strHtmlHeader = R"rawliteral(
<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      html { font-family: Helvetica; display: inline-block; margin: 0px auto;text-align: center;} 
      h1 {font-size:28px;} 
      .btn_on { padding:12px 30px; text-decoration:none; font-size:24px; background-color:
        #668ad8; color: #FFF; border-bottom: solid 4px #627295; border-radius: 2px;}
      .btn_on:active { -webkit-transform: translateY(0px); transform: translateY(0px);
        border-bottom: none;}
      .btn_off { background-color: #555555; border-bottom: solid 4px #333333;}
      .slider { width: 200px;}
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  </head>
)rawliteral";

// (ページボディー部)
const String strHtmlBody = R"rawliteral(
  <body><h1>%PAGE_TITLE%</h1>
    <p>SW-1 State : %RELAY1_STATE%</p>
    <p>%BUTTON1_STATE%</p>
    <p>SW-2 State : %RELAY2_STATE%</p>
    <p>%BUTTON2_STATE%</p>
  </body>
</html>
)rawliteral";

// (ON/OFFボタン)
const String strButton1On = R"rawliteral(
    <a href="/ON1"><button class="btn_on"> ON </button></a> )rawliteral";
const String strButton1Off = R"rawliteral(
    <a href="/OFF1"><button class="btn_on btn_off">OFF</button></a> )rawliteral";
const String strButton2On = R"rawliteral(
    <a href="/ON2"><button class="btn_on"> ON </button></a> )rawliteral";
const String strButton2Off = R"rawliteral(
    <a href="/OFF2"><button class="btn_on btn_off">OFF</button></a> )rawliteral";


②定型のsetup()とloop()

・setup()では初期化処理とルーター接続の関数を実行します。
・loop()では「HTTPリスン処理」を実行し続けます。
void setup() {
    doInitialize();             // 初期化処理をして
    connectToWifi();            // Wi-Fiルーターに接続する
}

void loop() {
    httpListen();               // HTTP手順を制御する
}


③初期化処理

・シリアルポートを設定し、2回路のリレーをOFF(負論理でHIGH)状態に設定します。
void doInitialize() {
    Serial.begin(SPI_SPEED);
    pinMode(relay1Pin, OUTPUT);
    pinMode(relay2Pin, OUTPUT);
    digitalWrite(relay1Pin, HIGH);
    digitalWrite(relay2Pin, HIGH);
}


④HTTPリスン処理

・「HTTPリスン定型処理」です。
・125行目 「HTTPリクエスト処理」を実行します。
・126行目 「HTTPレスポンス処理」を実行します。
void httpListen() {
    String strBuffer = "";
    WiFiClient client = server.available();

    if (client) {                         // クライアントから着信があれば
        Serial.println("New Client.");
        String currentLine = "";
        while (client.connected()) {      // 接続中に以下を繰り返す
            if (client.available()) {     // 着信データがあれば
                char c = client.read();   // 1バイト読み込んで
                strBuffer += c;           // 受信文を形成する
                if (c == '\n') {
                    // 復帰改行文字で受信領域が空なら、リクエスト処理とレスポンス
                    // を送信してループを脱出する
                    if (currentLine.length() == 0) {
                        httpRequestProccess(&strBuffer);
                        httpSendResponse(&client);
                        break;
                    } else {              // 後続文字があればラインバッファをクリア
                        currentLine = "";
                    }
                } else if (c != '\r') {   // 改行以外ならラインバッファに結合する
                    currentLine += c;
                }
            }
        }
        // コネクションを閉じる
        client.stop();
        Serial.println("Client disconnected.\n");
    }
}


⑤HTTPリクエスト処理

・リクエストメッセージを解析してアクションを起こします。
・145~153行目 リレー1のON/OFFボタンのクリックによりリレー1を設定(負論理)します。
・154~162行目 リレー2のON/OFFボタンのクリックによりリレー2を設定(負論理)します。
void httpRequestProccess(String* strbuf) {
    // 受信メッセージを判別してリレーをオン/オフする
    if (strbuf->indexOf("GET /ON1") >= 0) {
        Serial.println("GET /ON1");
        relay1State = "ON";
        digitalWrite(relay1Pin, LOW);
    } else if (strbuf->indexOf("GET /OFF1") >= 0) {
        Serial.println("GET /OFF1");
        relay1State = "OFF";
        digitalWrite(relay1Pin, HIGH);
    }
    if (strbuf->indexOf("GET /ON2") >= 0) {
        Serial.println("GET /ON2");
        relay2State = "ON";
        digitalWrite(relay2Pin, LOW);
    } else if (strbuf->indexOf("GET /OFF2") >= 0) {
        Serial.println("GET /OFF2");
        relay2State = "OFF";
        digitalWrite(relay2Pin, HIGH);
    }
    Serial.print("Switch1 State: "); Serial.println(relay1State);
    Serial.print("Switch2 State: "); Serial.println(relay2State);
}


⑦HTTPレスポンス処理

・HTTPレスポンスヘッダー、ページヘッダー、ボディー部を順番にクライアントへ送信します。
・176行 編集のために、生の文字リテラルで定義したボディー部を作業エリアに取り込みます。
・181,186行 クリックされているボタンによって次のボタン表示を設定します。
void httpSendResponse(WiFiClient* client) {
    // HTTPレスポンスヘッダーを送信
    client->println(strResponseHeader);

    // ページヘッダーを送信
    client->println(strHtmlHeader);
    
    // ページボディー部を編集して送信
    String buf = strHtmlBody;
    buf.replace("%PAGE_TITLE%", "Web Switch");
    buf.replace("%RELAY1_STATE%", relay1State);
    buf.replace("%RELAY2_STATE%", relay2State);
    //(ON/OFFボタンの設定)
    if (relay1State == "OFF") {
        buf.replace("%BUTTON1_STATE%", strButton1On);
    } else {
        buf.replace("%BUTTON1_STATE%", strButton1Off);
    }
    if (relay2State == "OFF") {
        buf.replace("%BUTTON2_STATE%", strButton2On);
    } else {
        buf.replace("%BUTTON2_STATE%", strButton2Off);
    }
    client->println(buf);
    client->println();     // 最後に、HTTP終端の空行を送信
}


⑧コネクション確立用

・以前と同じ定型のロジックです。
/* Wi-Fiルーターに接続する */
void connectToWifi() {
    // Wi-Fi接続して
    Serial.print("Connecting to Wi-Fi ");
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    // モニターにローカル IPアドレスを表示する
    Serial.println("WiFi connected.");
    Serial.print("  *IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();
}


4.動作検証

 シリアルモニターを立ち上げて実行を開始します。Wi-Fi接続が完了すると「割り当てられたIPアドレス」が表示されます(ここでは192.168.0.30)。
 パソコンまたはスマートフォンのWebブラウザーを起動して、アドレスバーに「割り当てられたIPアドレス」を入力すると次のような状態の「Web Switch」画面(写真上)が表示され、2つの豆電球は消灯しています。
  ・SW1 State: OFF
  ・[ON]ボタン
  ・SW2 State: OFF
  ・[ON]ボタン
 上の[ON]ボタンをクリックまたはタップすると[OFF]ボタンに反転し、写真・中のように赤色豆電球が点灯して、SW1 Stateが「ON」に変わります。
 続いて下の[ON]ボタンをクリックまたはタップすると、同様に[OFF]ボタンに反転し、図右・下のように緑色豆電球が点灯して、SW2 Stateが「ON」に変わります(写真下)。
 これらの過程はシリアルモニターに図左のように表示されます。


 今回も定型化したHTTPリスンメソッドをベースにしましたが、このようにして簡単にリレーモジュールを制御できることがわかりました。スマートホームの一部などに応用できそうです。

 スケッチ全体は、ページ先頭の[Download]ボタンでダウンロードしてください。
 ESP32をWebサーバーに仕立てたWi-Fi通信の実験はこれで終わりにします。
 最終回では、開発したローカルサーバーを公開して、外部のどこからでも接続・制御できるようにします。
 お楽しみに!


 
Copyright (C) 2011-2024 Marchan, All rights reserved.