20
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ESP32をWebサーバにしてGroveセンサーを制御してみる

Last updated at Posted at 2020-05-03

最近、「ESP32 & Arduino 電子工作プログラミング入門」という本を購入したため、復習の意味を兼ねて、ESP32をWebサーバにして、Groveセンサーを制御するプログラムを作ってみます。

本の中では、「第5章 各種のライブラリを使う」のところに「ESP32をWebサーバとして動作させる」という章があり、ここを参考にしながら進めていきます。
ここではスピーカーと接続して音を鳴らすサンプルになっていますが、今回はGroveセンサーのLEDをON/OFFしたいと思います。

環境

今回は、ESP32-DevKitCを使用します。
開発環境はArduino IDEを使用します。

ハードウェア

まず、LEDのピンは以下のようになっています。

image.png

こちらを参考にして、それぞれを、ESP32-DevKitCのピンに割り当てます。

Seeeduino Grove-Red Led ESP32-DevKitC
5V Red 5V
GND Black GND
Not Conencted White Not Connect
D2 Yellow IO4(No.26)

これらをブレッドボード経由で接続します。

DSC_0013.JPG

ケーブルの色を合わせると、接続するところを間違えずに済みます。
(ESP32-DevKitCの文字が小さいのが辛いですが ^^;)

ソフトウェア

プログラムは以下のようになります。

宣言

まず、ヘッダファイルを呼び出します。
Webサーバとして作成するときには「WebServer」クラスを使用します。

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

WebServerクラスのインスタンスを、外部変数として作成します。
ポート番号は80を指定します。

WebServer server(80)

今回はWiFiでネットに接続するため、アクセスポイントのSSIDとパスワードを指定します。
(下では仮の文字列にしてあります)

const char* ssid = "wifi_ssid";
const char* pass = "wifi_pass";

初期化

初期化関数「setup()」内で、以下の処理を行います。

  • シリアルポートの初期化
  • WiFiのアクセスポイントに接続
  • Groveセンサーの初期化
  • Webサーバの起動

まず、シリアルポートとの速度を指定して開始します。

    // シリアルポートの初期化
    Serial.begin(115200);

続いて、WiFiのアクセスポイントの接続します。

    // WiFiのアクセスポイントに接続
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
    }
    // ESP32のIPアドレスを出力
    Serial.println("WiFi Connected.");
    Serial.print("IP = ");
    Serial.println(WiFi.localIP());

動作させるとき、WebサーバのIPアドレスがわからないとアクセスできませんので、シリアルポートに出力します。

次に、今回使用するLEDの初期化を行います。

    pinMode(4, OUTPUT);

今回は、IO4から出力しますので、そのように設定しています。

最後にWebサーバを起動します。
起動する際、アドレスごとにコールバック関数を定義しておきます。

    // 処理するアドレスを定義
    server.on("/", handleRoot);
    server.on("/led", handleLED);
    server.onNotFound(handleNotFound);
    // Webサーバーを起動
    server.begin();

それぞれ、「/」「/led」「それ以外」にアクセスされたときの処理を行う関数を定義します。

処理ループ

処理ループ関数「loop()」内では、「WebServer.handleClient()」を呼び出すだけになっており、実際の処理は、初期化時に指定したコールバック関数内で記述します。

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

コールバック関数

初期化時に指定した、以下の関数に処理を記述します。

  • 初期画面
  • LEDをON/OFFする
  • 存在しないアドレスが指定された時

まず、初期画面を作成します。

void handleRoot(void)
{
    String html;

    // HTMLを組み立てる
    html = "<!DOCTYPE html>";
    html += "<html>";
    html += "<head>";
    html += "<meta charset=\"utf-8\">";
    html += "<title>LEDをON/OFFする</title>";
    html += "</head>";
    html += "<body>";
    html += "<p>リンクをクリックするとLEDがON/OFFします</p>";
    html += "<ul>";
    html += "<li><a href=\"/led?s=on\">ON</a></li>";
    html += "<li><a href=\"/led?s=off\">OFF</a></li>";
    html += "</ul>";
    html += "</body>";
    html += "</html>";

    // HTMLを出力する
    server.send(200, "text/html", html);
}

この画面では、LEDをON/OFFするためのURLへのリンクをHTMLで記述しています。
この程度の内容なので短いですが、もっと長くなるようであれば、もうちょっと記述方法を工夫したほうがよいかもしれません。

次に、LEDをON/OFFするコールバック関数を作成します。

void handleLED(void)
{
    String msg;

    // 「/led?s=○」のパラメータが指定されているかどうかを確認
    if (server.hasArg("s"))
    {
        // 「○」の値に応じて、LEDをON/OFFする
        if (server.arg("s").equals("on"))
        {
            digitalWrite(4, HIGH);
            msg = "LEDをONにしました";
        }
        else if (server.arg("s").equals("off"))
        {
            digitalWrite(4, LOW);
            msg = "LEDをOFFにしました";
        }
        else
        {
            msg = "パラメータが正しく指定されていません";
        }
    }

    // 変数msgの文字列を送信する
    server.send(200, "text/plain; charset=utf-8", msg);
}

「/led」が呼ばれた際のパラメータで、LEDをON/OFFするようにしています。
まずパラメータ名が「s」であるかを確認し、その値が「on」「off」であるかを確認しています。
それぞれ、IO4に対してHIGH/LOWの値を指定して、LEDのON/OFFを実現し、画面にもその結果を表示するようにしています。
(HTMLで書くほどではないので、ただのテキストで出力しています)

最後に、存在しないアドレスが指定された時の処理を作成します。

void handleNotFound(void)
{
    server.send(404, "text/plain", "Not Found.");
}

ただ「Not Found」と出力しているだけです。

実行

実行してみると、シリアルモニタにWebサーバのIPアドレスが表示されます。
image.png

そのIPアドレスに、Webブラウザでアクセスすると、以下のような画面が表示されます。
image.png

「ON」をクリックすると、LEDが光ります。
image.png
DSC_0015.JPG

「OFF」をクリックすると、LEDが消えます。
image.png
DSC_0017.JPG

まとめ

ゴリゴリHTMLを書くのが面倒ですが、コールバックの仕組みを使えば、簡単にセンサーの制御ができます。
またGroveセンサーも問題なくつなぐことができます。

ソースコード

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

WebServer server(80);

// WiFi情報
const char* ssid = "wifi_ssid";
const char* pass = "wifi_pass";

// 初期画面
void handleRoot(void)
{
    String html;

    // HTMLを組み立てる
    html = "<!DOCTYPE html>";
    html += "<html>";
    html += "<head>";
    html += "<meta charset=\"utf-8\">";
    html += "<title>LEDをON/OFFする</title>";
    html += "</head>";
    html += "<body>";
    html += "<p>リンクをクリックするとLEDがON/OFFします</p>";
    html += "<ul>";
    html += "<li><a href=\"/led?s=on\">ON</a></li>";
    html += "<li><a href=\"/led?s=off\">OFF</a></li>";
    html += "</ul>";
    html += "</body>";
    html += "</html>";

    // HTMLを出力する
    server.send(200, "text/html", html);
}

// LEDのON/OFF
void handleLED(void)
{
    String msg;

    // 「/led?s=○」のパラメータが指定されているかどうかを確認
    if (server.hasArg("s"))
    {
        // 「○」の値に応じて、LEDをON/OFFする
        if (server.arg("s").equals("on"))
        {
            digitalWrite(4, HIGH);
            msg = "LEDをONにしました";
        }
        else if (server.arg("s").equals("off"))
        {
            digitalWrite(4, LOW);
            msg = "LEDをOFFにしました";
        }
        else
        {
            msg = "パラメータが正しく指定されていません";
        }
    }

    // 変数msgの文字列を送信する
    server.send(200, "text/plain; charset=utf-8", msg);
}

// 存在しないアドレスが指定された時の処理
void handleNotFound(void)
{
    server.send(404, "text/plain", "Not Found.");
}

// 初期化
void setup()
{
    // シリアルポートの初期化
    Serial.begin(115200);

    // WiFiのアクセスポイントに接続
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
    }
    // ESP32のIPアドレスを出力
    Serial.println("WiFi Connected.");
    Serial.print("IP = ");
    Serial.println(WiFi.localIP());
    
    // Groveセンサーの初期化
    pinMode(4, OUTPUT);

    // 処理するアドレスを定義
    server.on("/", handleRoot);
    server.on("/led", handleLED);
    server.onNotFound(handleNotFound);
    // Webサーバーを起動
    server.begin();
}

// 処理ループ
void loop()
{
    server.handleClient();
}
20
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?