ESP32で『LED点滅サーバ』を作る

ESP32

ネットワーク経由でハードウェアを制御する

ネットワーク接続にも慣れてきたところで、そろそろ IoT っぽいことをやってみましょう。ESP32-Devkitは単体で無線LANに接続でき、多数の入出力端子ももっていますので、『ネットワーク経由で機器を操作する』とか『センサの読み取り値をネットワーク経由で送信する』という装置が比較的簡単に作れます。

LED点滅サーバ

というわけで今回は、ネットワーク接続したPCからの操作で、LEDを点滅させる実験を行います。一度やり方が理解できれば、これを応用して操作対象をLEDからサーボなどのアクチュエータに変更したり、さらにそれを複数に増やしたりするのも可能です。

今回も試作は可能な限り簡単にするため、またここまでの記事のソースを使い回すため(苦笑)、以下の仕様にします。

ESP32-DevkitCはサーバとして動作する。起動時にはLEDを消灯する。
PCからtelnetによって接続し、”on”と入力するとLED点灯、”off”と入力するとLED消灯する。
また、”exit”と入力するとLED消灯の上で通信を切断する。
複数のクライアントの同時接続については考慮しない。

名付けて『LED点滅サーバ』、通称『Lチカサーバ』(あまりにもそのまんまな命名…)です。

製作・事件

回路

回路はLチカの時とまったく同じで、LEDと電流制限抵抗を接続するだけです。

配線

実体配線図および実物の写真もLチカの時とまったく同じです。部品の解説はLチカの記事を参照してください。

プログラム

全ソースコード

メインプログラム LEDSwitchServer
C++
#include "WiFi.h"
#include "wifisecret.h"

// リスンポートを23番としてサーバのインスタンスを作成
IPAddress serverIP(192,168,0,101);
IPAddress gatewayIP(192,168,0,1);
IPAddress subnetMask(255,255,255,0);
uint16_t  listenPort=23;
WiFiServer server(listenPort);

// LED点滅関係
#define LED_PIN 12

void setup(){
  // シリアルインターフェイスの初期化
  Serial.begin(115200);
  delay(1000);

  // LED接続端子の設定
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  // 無線LANへの接続
  Serial.print("接続中...");
  if(!WiFi.config(serverIP, gatewayIP, subnetMask)){
    Serial.println("サーバアドレスの設定に失敗しました");
  }
  WiFi.begin(_SSID, _PASS);
  while(true){
    if(WiFi.status() == WL_CONNECTED)break;
    Serial.print(".");
    delay(1000);
  }
  Serial.println("完了");
  
  // ESP32に割り当てられたIPアドレスの確認
  Serial.print("IPアドレス:");
  Serial.println(WiFi.localIP());

  // サーバの起動
  server.begin();
}

void loop(){
  WiFiClient client = server.available();
  if(client){
    // クライアントと接続した時の処理
    while(true){
      // 1行入力
      String currentLine = "";
      while(true){
        if(!client.connected()){
          currentLine = "exit";
          break;
        }
        if(client.available()){
          // 受信した文字がある場合
          char c = client.read();
          if(c == '\n'){
            break;
          }
          if(c != '\r'){
            currentLine += c;
          }
        }
      }
      // 入力された文字列によって処理振り分け
      if(currentLine=="on"){          // 入力が"on"ならLED点灯
        digitalWrite(LED_PIN, HIGH);  // LED点灯
        client.println("LED ON");
        Serial.println("LED ON");
      }else if(currentLine=="off"){   // 入力が"off"ならLED消灯
        digitalWrite(LED_PIN, LOW);   // LED消灯
        client.println("LED OFF");
        Serial.println("LED OFF");
      }else if(currentLine=="exit"){  // 入力が"exit"なら終了
        digitalWrite(LED_PIN, LOW);   // LED消灯
        client.println("LED OFF");
        client.println("Bye");
        Serial.println("LED OFF");
        Serial.println("client stop.");
        client.stop();                // クライアントと切断
        break;                        // クライアント処理ループ脱出
      }
    }
  }
}

なお、client.println()Serial.println() は動作確認のためのものなので、不要ならば消してしまっても構いません。

wifisecret.h
C++
#define _SSID "xxxxxxxx"
#define _PASS "yyyyyyyy"

※ご利用の無線LAN環境にあわせて、”xxxxxxxx” の部分には SSID、”yyyyyyyy” の部分にはパスワードを記述してください。

プログラムの解説

オウム返しサーバとほとんど同じです。違う部分のみ解説します。

出力端子の定義
C++
// LED点滅関係
#define LED_PIN 12

Lチカのプログラムにもあった、LEDを接続した出力端子を表す定数 LED_PIN の定義です。プログラム中に直接番号を記述してもいいのですが、このように定数として定義しておいた方が後々変更があったときに間違いが起こりにくくなります。

アドレスなどの設定
C++
// リスンポートを23番としてサーバのインスタンスを作成
IPAddress serverIP(192,168,0,101);
IPAddress gatewayIP(192,168,0,1);
IPAddress subnetMask(255,255,255,0);
uint16_t  listenPort=23;
WiFiServer server(listenPort);
C++
  // 無線LANへの接続
  Serial.print("接続中...");
  if(!WiFi.config(serverIP, gatewayIP, subnetMask)){
    Serial.println("サーバアドレスの設定に失敗しました");
  }

ネットワークの各種設定部分を少々変更しました。実はconfig()関数はDNSの設定を省略できるようなので、前回の『オウム返しサーバ』からDNS設定を削除しました。このプログラム中からはドメイン名でアクセスをすることはないので、DNSの設定がなくても何も問題ありません。

出力端子の設定
C++
  // LED接続端子の設定
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

初期設定では、LED_PIN を出力に設定し、かつ出力を LOW レベル(LED消灯)にします。

入力された文字列に応じた処理
C++
      // 入力された文字列によって処理振り分け
      if(currentLine=="on"){          // 入力が"on"ならLED点灯
        digitalWrite(LED_PIN, HIGH);  // LED点灯
        client.println("LED ON");
        Serial.println("LED ON");
      }else if(currentLine=="off"){   // 入力が"off"ならLED消灯
        digitalWrite(LED_PIN, LOW);   // LED消灯
        client.println("LED OFF");
        Serial.println("LED OFF");
      }else if(currentLine=="exit"){  // 入力が"exit"なら終了
        digitalWrite(LED_PIN, LOW);   // LED消灯
        client.println("LED OFF");
        Serial.println("LED OFF");
        client.println("disconnect");
        Serial.println("disconnect");
        client.stop();                // クライアントと切断
        break;                        // クライアント処理ループ脱出
      }

クライアントから受信した一行(改行コードが送られてくるまでの文字を連結したもの)の文字列によって処理を振り分けています。

currentLine(受信文字列)が “on” だった場合、

LED_PIN に HIGH を出力(LEDが点灯)
クライアントおよびシリアル通信に文字列 “LED ON” を出力

currentLine が “off” だった場合、

LED_PIN に LOW を出力(LEDが消灯)
クライアントおよびシリアル通信に文字列 ”LED OFF” を出力

currentLine が “exit” だった場合

LED_PIN に LOW を出力(LEDが消灯)
クライアントおよびシリアル通信に文字列 “LED OFF” および ”disconnect” を出力
クライアントとの通信を切断

といった処理を行っています。

実験結果

telnetやTeraTermでESP32に接続し(プログラム例の場合は 192.168.0.101)、”on”、”off”と入力してみましょう。

※telnetやTeraTermのインストール方法・操作方法については『HelloWorldサーバ』または『オウム返しサーバ』を参考にしてください。

まとめ

  • ESP32を使用すれば、ネットワーク経由で電子回路の制御が出来る

コメント

タイトルとURLをコピーしました