小嶋秀樹 | 研究室
日本語 | English
トンペイーノを WiFi につないでみる

トンペイーノの心臓部にあたる ESP-WROOM-02 は,単体で WiFi 機能をもっています.PC のような子機にも,アクセスポイントのような親機にも,両方にもなれます.この WiFi 機能を活用することで,トンペイーノの IoT (Internet of Things) デバイスとして活用できるでしょう.ここでは,トンペーノの WiFi 機能を概説します.

【自宅や学校の無線 LAN に接続する】

トンペイーノを簡易ウェブサーバとして動作させ,自宅や学校の無線 LAN に接続し,同じ LAN に接続している PC やスマホからトンペイーノ上のウェブページにアクセスすることを試します.接続先となるネットワーク名(SSID)とパスワード(WPA2 など)が必要となります.また,多くの LAN 環境がそうであるように,DHCP による IP アドレスの自動割当が行われていることを前提とします.

まずはつぎのプログラムをそのまま動かしてみてください.赤字部分(SSID とパスワード)は,接続先ネットワークに合わせて書き換えてください.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

const char *ssid = "theSSID";        //  *** 書き換え必要 ***
const char *pass = "thePassword";    //  *** 書き換え必要(8文字以上)***
ESP8266WebServer Server(80);         //  ポート番号(HTTP)
int Counter = 0;                     //  お客さんカウンタ

//  クライアントにウェブページ(HTML)を返す関数
void handleRoot() {
  //  レスポンス文字列の生成('\n' は改行; '\' は行継続)
  Counter++;
  Serial.println("handleRoot()");
  String message = "\
<html lang=\"ja\">\n\
<meta charset=\"utf-8\">\n\
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\
<head>\n\
  <title>トンペイーノ</title>\n\
</head>\n\
<body style=\"font-family: sans-serif; background-color: #ffeeaa;\" >\n\
  <h1>トンペイーノによるウェブサーバ</h1>\n\
  <h3>あなたはトンペイーノの "
  + String(Counter)
  + "人目のお客さまです!</h3>\n\
</body>\n\
</html>\n";
  //  クライアントにレスポンスを返す
  Server.send(200, "text/html", message);  
}

//  クライアントにエラーメッセージを返す関数
void handleNotFound() {
  //  ファイルが見つかりません
  Serial.println("handleNotFound()");
  Server.send(404, "text/plain", "File not found in Dongbeino...");
}

//  メインプログラム
void setup() {
  //  シリアルモニタ(動作ログ)
  Serial.begin(115200);               //  ESP 標準の通信速度 115200
  delay(100);                         //  100ms ほど待ってからログ出力可
  Serial.println("\n*** Dongbeino ***");
  //  無線 LAN に接続
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);             //  接続確立まで待つこと
  Serial.println("Connecting...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }
  Serial.println("Connected");
  Serial.println(WiFi.localIP());     //  ESP 自身の IP アドレスをログ出力
  //  ウェブサーバの設定
  Server.on("/", handleRoot);         //  ルートアクセス時の応答関数を設定
  Server.onNotFound(handleNotFound);  //  不正アクセス時の応答関数を設定
  Server.begin();                     //  ウェブサーバ開始
}
void loop() {
  //  クライアントからの要求を処理する
  Server.handleClient();
}

トンペイーノへの書き込みが終了したら,Arduino IDE ウィンドウの右上にある「虫眼鏡アイコン」を押してください.シリアルモニタが開きます.通信速度が 115200 baud になっていることを確かめたら,トンペイーノの黄色いジャンパ線を "+" 側に切り換えてリセットを押してください.すると,このシリアルモニタにつぎのような情報が表示されるはずです.これらは Serial.println() によってプログラムから出力されたログ情報です.

正しく無線 LAN に接続できると,トンペイーノの IP アドレスが表示されます.ここでは "10.0.1.130" となっていますが,それぞれの LAN 環境で異なるでしょう.この IP アドレスに,PC やスマホのウェブブラウザでアクセスしてみてください.つぎのようなウェブページが表示されるはずです.リロードするたび(または別のブラウザからアクセスするたびに)人数カウンタが増えていきます.

ここではアクセス数(人数)のカウント機能しか持たせてありませんが,同じような枠組みで,トンペイーノがセンシングした情報(たとえば気象情報,加速度情報など)をウェブサービスとしてクライアントに提供するといった応用ができるでしょう.

複数の無線 LAN を使うには: たとえば自宅と学校など,複数のアクセスポイント(のいずれか)に接続するような設定も可能です.つぎのコードを参考にしてください.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;

void setup() {
  ...
  //  無線 LAN に接続
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP("university", "passwordUniv");
  wifiMulti.addAP("myhome",     "passwordHome");
  wifiMulti.addAP("company",    "passwordCom");
  Serial.println("Connecting...");    //  接続確立まで待つこと
  while (wifiMulti.run() != WL_CONNECTED) {
    delay(1000);
  }
  Serial.println(WiFi.localIP());     //  ESP 自身の IP アドレスをログ出力
  //  ウェブサーバの設定
  ...
}
void loop() {
  //  必要ならば再接続
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("Re-connecting...");
    delay(1000);
  }
  //  クライアントからの要求を処理する
  Server.handleClient();
}

これで,接続可能なアクセスポイントの中で最も電波(電界強度)の強いものに接続します.切断された場合は再接続を試みます.

ホスト名で接続するには: IP アドレスではなく,たとえば dongbei1 のように名前でトンペイーノに接続できると便利です.そのために使う機能が mDNS (multicast Domain Name Service) です.つぎのように改造すれば,"dongbei1.local" という名前で(同一のローカルネットワークから)接続できます.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <FS.h>
...
void setup() {
   ...
  //  無線 LAN に接続
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);             //  接続確立まで待つこと
  Serial.println("Connecting...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }
  //  mDNS の呼びかけに応答できるように仕込む
  Serial.println("Setting up mDNS...");
  if (MDNS.begin("dongbei1"))         //  "dongbei1.local" で応答
    Serial.println("mDNS started");
  else
    Serial.println("mDNS failed to start");
  //  ウェブサーバの設定
  ...
}
...
【独立ネットワークのアクセスポイントをつくる】

トンペイーノだけで独立したネットワーク(とアクセスポイント)を構成することもできます.これなら,利用可能な無線 LAN のないところでも,クライアントにウェブサービスを提供できます.

上で取り上げた例を改造します.赤字部分が変更すべき箇所です.たったこれだけで独立ネットワーク dongbeino1 のアクセスポイントがつくられ,自動的に設定された IP アドレス(デフォルトで "192.168.4.1")上で動作するウェブサーバとなります.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

const char *ssid = "dongbeino1";
const char *pass = "topsecret";      //  8文字以上
ESP8266WebServer Server(80);         //  ポート番号(HTTP)
int Counter = 0;                     //  お客さんカウンタ

//  クライアントにウェブページ(HTML)を返す関数
void handleRoot() {
  ... 変更なし ...
}

//  クライアントにエラーメッセージを返す関数
void handleNotFound() {
  ... 変更なし ...
}

//  メインプログラム
void setup() {
  //  シリアルモニタ(動作ログ)
  Serial.begin(115200);               //  ESP 標準の通信速度 115200
  delay(100);                         //  100ms ほど待ってからログ出力可
  Serial.println("\n*** Dongbeino ***");
  //  アクセスポイントの構成
  WiFi.mode(WIFI_AP);    
  WiFi.softAP(ssid, pass);
  Serial.print("network: "); Serial.println(ssid);
  Serial.print("address: "); Serial.println(WiFi.softAPIP());
  //  ウェブサーバの設定
  Server.on("/", handleRoot);         //  ルートアクセス時の応答関数を設定
  Server.onNotFound(handleNotFound);  //  不正アクセス時の応答関数を設定
  Server.begin();                     //  ウェブサーバ開始
}
void loop() {
  ... 変更なし ...
}

このプログラムをトンペイーノに書き込み,シリアルモニタを開いた状態で黄色いジャンパ線を "+" 側に切り換えてリセットすると,トンペイーノの IP アドレスが表示されます.

PC やスマホの WiFi 接続先ネットワークを "dongbeino1" に変更してから,ブラウザで 上記の IP アドレスにアクセスしてください.上の例と同じように,ウェブページを見ることができます.

クライアント数の上限: アクセスポイントにした ESP に同時接続できるクライアントの数は,デフォルトで 4 となっています.

チャンネル: アクセスポイントにした ESP は,デフォルトで 1ch を使います.別のチャンネルを割り当てたい場合は,WiFi.softAP(ssid, pass, 5) とすれば 5ch となります.(複数のチャンネルを同時使用する環境であれば,1ch, 5ch, 9ch, 13ch のように割り当てるとよいでしょう.)

なお,ウェブサーバの IP アドレス(上の例では "192.168.4.1")を特定の固定アドレスに変更したい場合は,setup() をつぎのように変更してください.

IPAddress serverIP(192, 168, 2, 19);
IPAddress gatewayIP(192, 168, 2, 19);
IPAddress subnetMask(255, 255, 255, 0);

void setup() {
  //  シリアルモニタ(動作ログ)
  Serial.begin(115200);               //  ESP 標準の通信速度 115200
  delay(100);                         //  100ms ほど待ってからログ出力可
  Serial.println("\n*** Dongbeino ***");
  //  アクセスポイントの構成
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(serverIP, gatewayIP, subnetMask);
  WiFi.softAP(ssid, pass);
  Serial.print("network: "); Serial.println(ssid);
  Serial.print("address: "); Serial.println(WiFi.softAPIP());
  //  ウェブサーバの設定
  Server.on("/", handleRoot);         //  ルートアクセス時の応答関数を設定
  Server.onNotFound(handleNotFound);  //  不正アクセス時の応答関数を設定
  Server.begin();                     //  ウェブサーバ開始
}

あまりオススメしませんが,アクセスポイントをパスワードなしで構成したい場合は,WiFi.softAP(ssid) のように,引数を ssid のみに変更してください.

トンペイーノで遠隔制御・遠隔センシング
【ウェブブラウザから LED を制御する】

「独立ネットワークのアクセスポイントをつくる」を応用して,トンペイーノの LED をウェブブラウザから制御してみましょう.ウェブページにボタンを配置し,それを押すことで LED(標準の IO13)をオン・オフするというものです.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

const char *ssid = "xkozima";        //  ご近所と重複ないように
const char *pass = "dongbeino";      //  8文字以上
ESP8266WebServer Server(80);         //  ポート番号(HTTP)

//  クライアントにウェブページ(HTML)を返す関数
void handleLED() {
  //  LED の制御
  Serial.print("handleLED: ");
  if (Server.method() == HTTP_POST) {
    String val = Server.arg("led");
    if (val == "1") {
      //  LED オン
      digitalWrite(13, HIGH);
      Serial.println("ON");
    }
    else if (val == "0") {
      //  LED オフ
      digitalWrite(13, LOW);
      Serial.println("OFF");
    }
  }
  //  レスポンス文字列の生成('\n' は改行; '\' は行継続)
  String message = "\
<html lang=\"ja\">\n\
<meta charset=\"utf-8\">\n\
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\
<head>\n\
  <title>トンペイーノ</title>\n\
</head>\n\
<body style=\"font-family: sans-serif; background-color: #ffeeaa;\" >\n\
  <h1>トンペイーノによる LED の遠隔制御</h1>\n\
  <p><form action='' method='post'>\n\
       <button name='led' value='1'>オン</button>\n\
     </form>\n\
     <form action='' method='post'>\n\
       <button name='led' value='0'>オフ</button>\n\
     </form>\n\
   </p>\n\
</body>\n\
</html>\n";
  //  クライアントにメッセージを返す
  Server.send(200, "text/html", message);
}

//  クライアントにエラーメッセージを返す関数
void handleNotFound() {
  //  ファイルが見つかりません
  Serial.println("handleNotFound()");
  Server.send(404, "text/plain", "File not found in Dongbeino...");
}

//  メインプログラム
void setup() {
  //  LED 出力
  pinMode(13, OUTPUT);
  //  シリアルモニタ(動作ログ)
  Serial.begin(115200);               //  ESP 標準の通信速度 115200
  delay(100);                         //  100ms ほど待ってからログ出力可
  Serial.println("\n*** Dongbeino ***");
  //  アクセスポイントの構成
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, pass);
  Serial.print("network: "); Serial.println(ssid);
  Serial.print("address: "); Serial.println(WiFi.softAPIP());
  //  ウェブサーバの設定
  Server.on("/led/", handleLED);      //  /led/ アクセス時の応答関数を設定
  Server.onNotFound(handleNotFound);  //  不正アクセス時の応答関数を設定
  Server.begin();                     //  ウェブサーバ開始
}
void loop() {
  //  クライアントからの要求を処理する
  Server.handleClient();
}

このプログラムをトンペイーノで動かし,PC やスマホの接続先ネットワークを,たとえば xkozima に変更します.ブラウザから 192.168.4.1/led/ にアクセスすると,つぎのようなウェブページが現れるはずです.(URL の末尾にあるスラッシュ "/" を忘れずに!)

「オン」「オフ」のボタンを押すと,その情報がウェブサーバ(トンペイーノ)に POST されます.トンペイーノでは handleLED() が POST された情報に応じて LED をオン・オフするとともに,ウェブページの情報をクライアント(PC やスマホのウェブブラウザ)に返しています.

【ウェブブラウザからスイッチの状態を読み取る】

トンペイーノに装着したスイッチの状態をウェブページから読み取ります.ここでは IO4 に接続したスイッチ(あるいは GND への接続・切断が可能なジャンパ線)の状態を読み取ります.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

const char *ssid = "xkozima";        //  ご近所と重複ないように
const char *pass = "dongbeino";      //  8文字以上
ESP8266WebServer Server(80);         //  ポート番号(HTTP)

//  クライアントにウェブページ(HTML)を返す関数
void handleSW() {
  //  スイッチの読み取り
  Serial.print("handleSW: ");
  int swMode = digitalRead(4);
  if (swMode == HIGH) {
    Serial.println("HIGH");
  }
  else {
    Serial.println("LOW");
  }
  //  レスポンス文字列の生成('\n' は改行; '\' は行継続)
  String message = "\
    <html lang=\"ja\">\n\
    <meta charset=\"utf-8\">\n\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\
    <head>\n\
      <title>トンペイーノ</title>\n\
    </head>\n\
    <body style=\"font-family: sans-serif; background-color: #ffeeaa;\" >\n\
      <h1>トンペイーノによるスイッチの遠隔センシング</h1>\n\
      <p>スイッチは " + String((swMode == HIGH)? "off" : "ON") + " です。</p>\n\
    </body>\n\
  </html>\n";
  //  クライアントにメッセージを返す
  Server.send(200, "text/html", message);
}

//  クライアントにエラーメッセージを返す関数
void handleNotFound() {
  //  ファイルが見つかりません
  Serial.println("handleNotFound()");
  Server.send(404, "text/plain", "File not found in Dongbeino...");
}

//  メインプログラム
void setup() {
  //  スイッチ入力出力
  pinMode(4, INPUT_PULLUP);
  //  シリアルモニタ(動作ログ)
  Serial.begin(115200);               //  ESP 標準の通信速度 115200
  delay(100);                         //  100ms ほど待ってからログ出力可
  Serial.println("\n*** Dongbeino ***");
  //  アクセスポイントの構成
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, pass);
  Serial.print("network: "); Serial.println(ssid);
  Serial.print("address: "); Serial.println(WiFi.softAPIP());
  //  ウェブサーバの設定
  Server.on("/sw/", handleSW);        //  /sw/ アクセス時の応答関数を設定
  Server.onNotFound(handleNotFound);  //  不正アクセス時の応答関数を設定
  Server.begin();                     //  ウェブサーバ開始
}
void loop() {
  //  クライアントからの要求を処理する
  Server.handleClient();
}

このプログラムをトンペイーノで動かし,PC やスマホの接続先ネットワークを,たとえば xkozima に変更します.ブラウザから 192.168.4.1/sw/ にアクセスすると,つぎのようなウェブページが現れるはずです.(URL の末尾にあるスラッシュ "/" を忘れずに!)

ウェブページをリロードするたびに,最新のスイッチ状態が ON / off で表示されます.試してみてください.なお,ブラウザ側で定期的なリロードを設定するには,プログラム中の文字列 message に <meta http-equiv="Refresh" content="1"> を加えてください.これで 1s ごとに自動リロードされるようになります。