M5Stack Core2 を用いて,WiFi にマイコンを接続しましょう。
本記事では M5Stack Core2 を使用していますが,他のシリーズでも対応するライブラリがインストールしてあれば同じようにできるはずです(保証はできませんが...)。
また,本記事中では客観的に見ると好まれない表現があるかもしれません。
何かお気づきの際は,コメント等で教えていただけると幸いです。
前提
以下を前提に,進んでいきます。
- 使用IDE:Arduino IDE
- Arduino IDE に,M5Stack Core2 のライブラリが追加されている(ない場合:環境構築編を参照)
- 書いたプログラムをマイコン(M5Stack Core2)上で実行できる(できない場合:環境構築編を参照)
接続フローについて
よくプログラムに直接 SSID, パスワードを記述して WiFi と接続する記事がありますが,本記事では,汎用性高く,ユーザーがスマホ等から接続設定を行えるようにしてみましょう(プログラム中に情報を埋め込まないでWiFiに接続します)。
以下のフローチャートの動作になるように,開発を行います。
実は,これを実現するためのプログラムを,M5Stack の方で用意してくださっています。ですので,そちらをありがたく使わせていただきます。
WiFi設定のExampleプログラムを実行してみる
後ほど,Exampleプログラムの修正を行います。「修正なんかやってないで,早く動作させたい!」という方は,下に示す最終コードを利用してください。
File > Examples > Examples from Custom Libraries
の,M5Core2 > Advanced > WiFi > WiFiSetting
を開きます。
ちなみに,このソースコードは,GitHub(公式レポジトリ)からも確認できます。
MITライセンスで公開されています。ありがたき幸せ。
WiFiSetting.ino
が開かれます。
何も変更を加えずに,これを実行してみましょう。
実行結果
アクセスポイントに接続する
この時,最初に示したフローチャートを辿ると,「セットアップモード(AP)」に入っています。APはアクセスポイントのことで,Wi-Fiの電波を送受信する機器と説明されるようです(ちょっと違いますが,今はルーターとして機能していると思ってください)。
つまり,今,このマイコンはルーター(みたいなもの)です。ですから,この「ルーター」に接続してみましょう。
Starting Web Server at: 192.168.4.1
Starting Access Point at "M5STACK_SETUP"
とあるので,SSIDがM5STACK_SETUP
となっているWiFiに接続します(パスワードフリーです)。
WiFi接続設定を行う
接続後,ブラウザから「192.168.4.1」にアクセスしましょう。
ものすごくシンプルなページが表示されます。
マイコンが後ほど接続する(本物の)ルーターの認証情報を入力します。SSIDを選択し,パスワードを入力後,送信
をクリックしましょう。
送信後,「Setup complete.」というページが表示されます。
入力情報を本体のストレージ(NVS)に保存し,M5Stack が再起動します(APモードが終了するので,M5STACK_SETUP
からの接続も切れます)。
再起動後...
前項での操作が成功していれば,
WIFI-SSID: [謎の文字]
WIFI-PASSWD: [謎の文字]
Waiting for Wi-Fi connection...
Connected!
Starting Web Server at 192.168.11.24
本操作に失敗している場合,Starting Access Point at "M5STACK_SETUP"
が再度表示されます。通常はWiFiのパスワード打ち間違えです。
「アクセスポイントに接続する」からやり直してください。
[謎の文字]なんか表示されず,正常に表示されるよ!?という方もいるでしょう。これについては,[謎の文字]を修正項を参照してください。
今度は,最初に示したフローチャートを辿ると,「稼働モード(STA)」に入っています。STAは,ステーションモードのことで,端末(無線LAN子機)としてWi-Fiアクセスポイント(AP)に接続するモードと説明されるようです(先程はルーター扱いでしたが,今度はスマホやPCのような,ルーターに接続する側となります)。
(私の場合)192.168.11.24
にアクセスできるようなので,先ほどと同様,このipアドレスにアクセスしてみます。
マイコンが接続している WiFi と操作端末が接続している WiFi が一致していることをご確認ください。
Reset Wi-Fi Settings
をクリックすると,保存されているWiFi設定を消去することができます。
消去が完了すると,再起動します(再度使うには,アクセスポイントに接続するからやり直しとなります)。
プログラムを修正する
Webページを日本語対応する
現状,ipアドレスにアクセスして表示されるWebページですが,日本語が文字化けします。WebページのエンコードをUTF-8
に設定してあげましょう。
makePage
関数を修正します。
String makePage(String title, String contents) {
- String s = "<!DOCTYPE html><html><head>";
+ String s = "<!DOCTYPE html><html lang='ja'><head>";
s += "<meta name=\"viewport\" "
"content=\"width=device-width,user-scalable=0\">"
+ "<meta charset='UTF-8'>";
s += "<title>";
s += title;
- s += "</title></head><body>";
+ s += "</title></head><body style='font-family: SF Pro JP, SF Pro Text, SF Pro Icons, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3,"
+ "メイリオ, Meiryo, MS Pゴシック, Helvetica Neue, Helvetica, Arial, sans-serif'>";
s += contents;
s += "</body></html>";
return s;
}
コピー用はこちら
String makePage(String title, String contents) {
String s = "<!DOCTYPE html><html lang='ja'><head>";
s += "<meta name='viewport' content='width=device-width,user-scalable=0'>"
"<meta charset='UTF-8'><title>";
s += title;
s += "</title></head><body style='font-family: SF Pro JP, SF Pro Text, SF Pro Icons, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3,"
"メイリオ, Meiryo, MS Pゴシック, Helvetica Neue, Helvetica, Arial, sans-serif'>";
s += contents;
s += "</body></html>";
return s;
}
ページを日本語にする
もう少し詳しく,かつ日本語のページを表示させましょう。ここは完全に個人の好みで修正しています。必要なら参照ください。
startWebServer
関数を修正します。
void startWebServer() { // Open the web service. 打开Web服务
if (settingMode) { // If the setting mode is on. 如果设置模式处于开启状态
M5.Lcd.print("Starting Web Server at: ");
M5.Lcd.print(
WiFi.softAPIP()); // Output AP address (you can change the address
// you want through apIP at the beginning).
// 输出AP地址(可通过开头的apIP更改自己想要的地址)
webServer.on(
"/settings", []() { // AP web interface settings. AP网页界面设置
String s =
- "<h1>Wi-Fi Settings</h1><p>Please enter your password by "
- "selecting the SSID.</p>";
+ "<h1>Wi-Fi 設定</h1><p>以下からSSIDを選び,そのパスワードを入力して「送信」ボタンを押してください。</p>";
s += "<form method=\"get\" action=\"setap\"><label>SSID: "
"</label><select name=\"ssid\">";
s += ssidList;
- s += "</select><br>Password: <input name=\"pass\" length=64 "
+ s += "</select><br>パスワード: <input name=\"pass\" length=64 "
"type=\"password\"><input type=\"submit\"></form>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
});
webServer.on("/setap", []() {
String ssid = urlDecode(webServer.arg("ssid"));
M5.Lcd.printf("SSID: %s\n", ssid);
String pass = urlDecode(webServer.arg("pass"));
M5.Lcd.printf("Password: %s\n\nWriting SSID to EEPROM...\n", pass);
// Store wifi config. 存储wifi配置信息
M5.Lcd.println("Writing Password to nvr...");
preferences.putString("WIFI_SSID", ssid);
preferences.putString("WIFI_PASSWD", pass);
M5.Lcd.println("Write nvr done!");
String s =
- "<h1>Setup complete.</h1><p>device will be connected to \"";
+ "<h1>WiFi設定を保存しました</h1><p>2秒後に再起動し,\"";
s += ssid;
- s += "\" after the restart.";
+ s += "\"に自動で接続されます。<br>操作端末との接続も切れます。</p>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
delay(2000);
ESP.restart(); // Restart MPU. 重启MPU
});
webServer.onNotFound([]() {
String s =
- "<h1>AP mode</h1><p><a href=\"/settings\">Wi-Fi "
- "Settings</a></p>";
+ "<h1>WiFi設定ウィザード</h1><p>ようこそ。以下からWiFi接続設定を開始してください。</p>"
+ "<p><a href='/settings'>Wi-Fi設定を始める</a></p>";
webServer.send(200, "text/html", makePage("AP mode", s));
});
} else { // If the setting mode is off. 如果设置模式处于关闭状态
M5.Lcd.print("Starting Web Server at ");
M5.Lcd.println(WiFi.localIP());
webServer.on("/", []() { // AP web interface settings. AP网页界面设置
String s =
- "<h1>STA mode</h1><p><a href=\"/reset\">Reset Wi-Fi "
- "Settings</a></p>";
+ "<h1>稼働モード</h1><p><a href=\"/reset\">Wi-Fi設定を削除する</a></p>";
webServer.send(200, "text/html", makePage("STA mode", s));
});
webServer.on("/reset", []() {
// reset the wifi config
preferences.remove("WIFI_SSID");
preferences.remove("WIFI_PASSWD");
String s =
- "<h1>Wi-Fi settings was reset.</h1><p>Please reset device.</p>";
+ "<h1>Wi-Fi設定を削除しました</h1><p>2秒後にデバイスが再起動します。</p>";
webServer.send(200, "text/html",
makePage("Reset Wi-Fi Settings", s));
delay(2000);
ESP.restart();
});
}
webServer.begin(); // Start web service. 开启web服务
}
コピー用はこちら
void startWebServer() { // Open the web service. 打开Web服务
if (settingMode) { // If the setting mode is on. 如果设置模式处于开启状态
M5.Lcd.print("Starting Web Server at: ");
M5.Lcd.print(
WiFi.softAPIP()); // Output AP address (you can change the address
// you want through apIP at the beginning).
// 输出AP地址(可通过开头的apIP更改自己想要的地址)
webServer.on(
"/settings", []() { // AP web interface settings. AP网页界面设置
String s =
"<h1>Wi-Fi 設定</h1><p>以下からSSIDを選び,そのパスワードを入力して「送信」ボタンを押してください。</p>";
s += "<form method=\"get\" action=\"setap\"><label>SSID: "
"</label><select name=\"ssid\">";
s += ssidList;
s += "</select><br>パスワード: <input name=\"pass\" length=64 "
"type=\"password\"><input type=\"submit\"></form>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
});
webServer.on("/setap", []() {
String ssid = urlDecode(webServer.arg("ssid"));
M5.Lcd.printf("SSID: %s\n", ssid);
String pass = urlDecode(webServer.arg("pass"));
M5.Lcd.printf("Password: %s\n\nWriting SSID to EEPROM...\n", pass);
// Store wifi config. 存储wifi配置信息
M5.Lcd.println("Writing Password to nvr...");
preferences.putString("WIFI_SSID", ssid);
preferences.putString("WIFI_PASSWD", pass);
M5.Lcd.println("Write nvr done!");
String s =
"<h1>WiFi設定を保存しました</h1><p>2秒後に再起動し,\"";
s += ssid;
s += "\"に自動で接続されます。<br>操作端末との接続も切れます。</p>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
delay(2000);
ESP.restart(); // Restart MPU. 重启MPU
});
webServer.onNotFound([]() {
String s =
"<h1>WiFi設定ウィザード</h1><p>ようこそ。以下からWiFi接続設定を開始してください。</p>"
"<p><a href='/settings'>Wi-Fi設定を始める</a></p>";
webServer.send(200, "text/html", makePage("AP mode", s));
});
} else { // If the setting mode is off. 如果设置模式处于关闭状态
M5.Lcd.print("Starting Web Server at ");
M5.Lcd.println(WiFi.localIP());
webServer.on("/", []() { // AP web interface settings. AP网页界面设置
String s =
"<h1>稼働モード</h1><p><a href=\"/reset\">Wi-Fi設定を削除する</a></p>";
webServer.send(200, "text/html", makePage("STA mode", s));
});
webServer.on("/reset", []() {
// reset the wifi config
preferences.remove("WIFI_SSID");
preferences.remove("WIFI_PASSWD");
String s =
"<h1>Wi-Fi設定を削除しました</h1><p>2秒後にデバイスが再起動します。</p>";
webServer.send(200, "text/html",
makePage("Reset Wi-Fi Settings", s));
delay(2000);
ESP.restart();
});
}
webServer.begin(); // Start web service. 开启web服务
}
この修正で,日本語のページも正常に表示されるようになりました。
[謎の文字]を修正
ここのところで,WIFI-SSID
やWIFI-PASSWD
のとこが正しく表示されず,変な表示となっています。これ,検証をしてみると,それぞれ13字までは正常に表示され,14字以降はこのように[謎の文字]が表示されてしまうようです(原因は全くわからん!!)。
SSID・PASSWDともに1234567890abc
SSIDは1234567890abc
,PASSWDは1234567890abcd
これの原因は,プログラムが足りていない箇所があります。
まず,startWebServer
関数です。
void startWebServer() { // Open the web service. 打开Web服务
if (settingMode) { // If the setting mode is on. 如果设置模式处于开启状态
M5.Lcd.print("Starting Web Server at: ");
M5.Lcd.print(
WiFi.softAPIP()); // Output AP address (you can change the address
// you want through apIP at the beginning).
// 输出AP地址(可通过开头的apIP更改自己想要的地址)
webServer.on(
"/settings", []() { // AP web interface settings. AP网页界面设置
String s =
"<h1>Wi-Fi 設定</h1><p>以下からSSIDを選び,そのパスワードを入力して「送信」ボタンを押してください。</p>";
s += "<form method=\"get\" action=\"setap\"><label>SSID: "
"</label><select name=\"ssid\">";
s += ssidList;
s += "</select><br>パスワード: <input name=\"pass\" length=64 "
"type=\"password\"><input type=\"submit\"></form>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
});
webServer.on("/setap", []() {
String ssid = urlDecode(webServer.arg("ssid"));
- M5.Lcd.printf("SSID: %s\n", ssid);
+ M5.Lcd.printf("SSID: %s\n", ssid.c_str());
String pass = urlDecode(webServer.arg("pass"));
- M5.Lcd.printf("Password: %s\n\nWriting SSID to EEPROM...\n", pass);
+ M5.Lcd.printf("Password: %s\n\nWriting SSID to EEPROM...\n", pass.c_str());
// Store wifi config. 存储wifi配置信息
M5.Lcd.println("Writing Password to nvr...");
preferences.putString("WIFI_SSID", ssid);
preferences.putString("WIFI_PASSWD", pass);
M5.Lcd.println("Write nvr done!");
String s =
"<h1>WiFi設定を保存しました</h1><p>2秒後に再起動し,\"";
s += ssid;
s += "\"に自動で接続されます。<br>操作端末との接続も切れます。</p>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
delay(2000);
ESP.restart(); // Restart MPU. 重启MPU
});
webServer.onNotFound([]() {
String s =
"<h1>WiFi設定ウィザード</h1><p>ようこそ。以下からWiFi接続設定を開始してください。</p>"
"<p><a href='/settings'>Wi-Fi設定を始める</a></p>";
webServer.send(200, "text/html", makePage("AP mode", s));
});
} else { // If the setting mode is off. 如果设置模式处于关闭状态
M5.Lcd.print("Starting Web Server at ");
M5.Lcd.println(WiFi.localIP());
webServer.on("/", []() { // AP web interface settings. AP网页界面设置
String s =
"<h1>稼働モード</h1><p><a href=\"/reset\">Wi-Fi設定を削除する</a></p>";
webServer.send(200, "text/html", makePage("STA mode", s));
});
webServer.on("/reset", []() {
// reset the wifi config
preferences.remove("WIFI_SSID");
preferences.remove("WIFI_PASSWD");
String s =
"<h1>Wi-Fi設定を削除しました</h1><p>2秒後にデバイスが再起動します。</p>";
webServer.send(200, "text/html",
makePage("Reset Wi-Fi Settings", s));
delay(2000);
ESP.restart();
});
}
webServer.begin(); // Start web service. 开启web服务
}
続いて,restoreConfig
関数です。
boolean restoreConfig() { /* Check whether there is wifi configuration information
storage, if there is 1 return, if no return 0.
检测是否有wifi配置信息存储,若有返回1,无返回0 */
wifi_ssid = preferences.getString("WIFI_SSID");
wifi_password = preferences.getString("WIFI_PASSWD");
M5.Lcd.printf(
"WIFI-SSID: %s\n",
- wifi_ssid); // Screen print format string. 屏幕打印格式化字符串
+ wifi_ssid.c_str()); // Screen print format string. 屏幕打印格式化字符串
- M5.Lcd.printf("WIFI-PASSWD: %s\n", wifi_password);
+ M5.Lcd.printf("WIFI-PASSWD: %s\n", wifi_password.c_str());
WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str());
if (wifi_ssid.length() > 0) {
return true;
} else {
return false;
}
}
要するに,c_str()
で string を従来の,C言語文字配列へのポインタでprintf
に渡す必要があったようです。(もう一回言いますが,何故13字までは上手く行ったのか,よくわかりません。有識者の方,教えてください...)
最終コード
オリジナルはプロトタイプ宣言を含んでいましたが,ここではプロトタイプ宣言を消す代わりに関数の位置を上下ひっくり返しました。
/*
*******************************************************************************
* Copyright (c) 2021 by M5Stack
* Equipped with M5Core2 sample source code
* 配套 M5Core2 示例源代码
* Visit for more information: https://docs.m5stack.com/en/core/core2
* 获取更多资料请访问: https://docs.m5stack.com/zh_CN/core/core2
*
* Describe: WiFi connect. wifi连接
* Date: 2021/7/27
*******************************************************************************
*/
#include <M5Core2.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiClient.h>
#include "WebServer.h"
#include <Preferences.h>
const IPAddress apIP(
192, 168, 4, 1); // Define the address of the wireless AP. 定义无线AP的地址
const char* apSSID = "M5STACK_SETUP"; // Define the name of the created
// hotspot. 定义创建热点的名称
boolean settingMode;
String ssidList;
String wifi_ssid; // Store the name of the wireless network. 存储无线网络的名称
String wifi_password; // Store the password of the wireless network.
// 存储无线网络的密码
// DNSServer dnsServer;. webServer的类
WebServer webServer(80);
// wifi config store. wifi配置存储的类
Preferences preferences;
String makePage(String title, String contents) {
String s = "<!DOCTYPE html><html lang='ja'><head>";
s += "<meta name='viewport' content='width=device-width,user-scalable=0'>"
"<meta charset='UTF-8'><title>";
s += title;
s += "</title></head><body style='font-family: SF Pro JP, SF Pro Text, SF Pro Icons, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3,"
"メイリオ, Meiryo, MS Pゴシック, Helvetica Neue, Helvetica, Arial, sans-serif'>";
s += contents;
s += "</body></html>";
return s;
}
String urlDecode(String input) {
String s = input;
s.replace("%20", " ");
s.replace("+", " ");
s.replace("%21", "!");
s.replace("%22", "\"");
s.replace("%23", "#");
s.replace("%24", "$");
s.replace("%25", "%");
s.replace("%26", "&");
s.replace("%27", "\'");
s.replace("%28", "(");
s.replace("%29", ")");
s.replace("%30", "*");
s.replace("%31", "+");
s.replace("%2C", ",");
s.replace("%2E", ".");
s.replace("%2F", "/");
s.replace("%2C", ",");
s.replace("%3A", ":");
s.replace("%3A", ";");
s.replace("%3C", "<");
s.replace("%3D", "=");
s.replace("%3E", ">");
s.replace("%3F", "?");
s.replace("%40", "@");
s.replace("%5B", "[");
s.replace("%5C", "\\");
s.replace("%5D", "]");
s.replace("%5E", "^");
s.replace("%5F", "-");
s.replace("%60", "`");
return s;
}
void startWebServer() { // Open the web service. 打开Web服务
if (settingMode) { // If the setting mode is on. 如果设置模式处于开启状态
M5.Lcd.print("Starting Web Server at: ");
M5.Lcd.print(
WiFi.softAPIP()); // Output AP address (you can change the address
// you want through apIP at the beginning).
// 输出AP地址(可通过开头的apIP更改自己想要的地址)
webServer.on(
"/settings", []() { // AP web interface settings. AP网页界面设置
String s =
"<h1>Wi-Fi 設定</h1><p>以下からSSIDを選び,そのパスワードを入力して「送信」ボタンを押してください。</p>";
s += "<form method=\"get\" action=\"setap\"><label>SSID: "
"</label><select name=\"ssid\">";
s += ssidList;
s += "</select><br>パスワード: <input name=\"pass\" length=64 "
"type=\"password\"><input type=\"submit\"></form>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
});
webServer.on("/setap", []() {
String ssid = urlDecode(webServer.arg("ssid"));
M5.Lcd.printf("SSID: %s\n", ssid.c_str());
String pass = urlDecode(webServer.arg("pass"));
M5.Lcd.printf("Password: %s\n\nWriting SSID to EEPROM...\n", pass.c_str());
// Store wifi config. 存储wifi配置信息
M5.Lcd.println("Writing Password to nvr...");
preferences.putString("WIFI_SSID", ssid);
preferences.putString("WIFI_PASSWD", pass);
M5.Lcd.println("Write nvr done!");
String s =
"<h1>WiFi設定を保存しました</h1><p>2秒後に再起動し,\"";
s += ssid;
s += "\"に自動で接続されます。<br>操作端末との接続も切れます。</p>";
webServer.send(200, "text/html", makePage("Wi-Fi Settings", s));
delay(2000);
ESP.restart(); // Restart MPU. 重启MPU
});
webServer.onNotFound([]() {
String s =
"<h1>WiFi設定ウィザード</h1><p>ようこそ。以下からWiFi接続設定を開始してください。</p>"
"<p><a href='/settings'>Wi-Fi設定を始める</a></p>";
webServer.send(200, "text/html", makePage("AP mode", s));
});
} else { // If the setting mode is off. 如果设置模式处于关闭状态
M5.Lcd.print("Starting Web Server at ");
M5.Lcd.println(WiFi.localIP());
webServer.on("/", []() { // AP web interface settings. AP网页界面设置
String s =
"<h1>稼働モード</h1><p><a href=\"/reset\">Wi-Fi設定を削除する</a></p>";
webServer.send(200, "text/html", makePage("STA mode", s));
});
webServer.on("/reset", []() {
// reset the wifi config
preferences.remove("WIFI_SSID");
preferences.remove("WIFI_PASSWD");
String s =
"<h1>Wi-Fi設定を削除しました</h1><p>2秒後にデバイスが再起動します。</p>";
webServer.send(200, "text/html",
makePage("Reset Wi-Fi Settings", s));
delay(2000);
ESP.restart();
});
}
webServer.begin(); // Start web service. 开启web服务
}
boolean restoreConfig() { /* Check whether there is wifi configuration information
storage, if there is 1 return, if no return 0.
检测是否有wifi配置信息存储,若有返回1,无返回0 */
wifi_ssid = preferences.getString("WIFI_SSID");
wifi_password = preferences.getString("WIFI_PASSWD");
M5.Lcd.printf(
"WIFI-SSID: %s\n",
wifi_ssid.c_str()); // Screen print format string. 屏幕打印格式化字符串
M5.Lcd.printf("WIFI-PASSWD: %s\n", wifi_password.c_str());
WiFi.begin(wifi_ssid.c_str(), wifi_password.c_str());
if (wifi_ssid.length() > 0) {
return true;
} else {
return false;
}
}
boolean checkConnection() { // Check wifi connection. 检测wifi连接情况
int count = 0; // count. 计数
M5.Lcd.print("Waiting for Wi-Fi connection");
while (
count <
30) { /* If you fail to connect to wifi within 30*350ms
(10.5s), return false; otherwise return true.
若在30*500ms(15s)内未能连上wifi,返回false;否则返回true
*/
if (WiFi.status() == WL_CONNECTED) {
M5.Lcd.printf("\nConnected!\n");
return (true);
}
delay(350);
M5.Lcd.print(".");
count++;
}
M5.Lcd.println("Timed out.");
return false;
}
void setupMode() {
WiFi.mode(WIFI_MODE_STA); // Set Wi-Fi mode to WIFI_MODE_STA.
// 设置Wi-Fi模式为WIFI_MODE_STA
WiFi.disconnect(); // Disconnect wifi connection. 断开wifi连接
delay(100);
int n = WiFi.scanNetworks(); // Store the number of wifi scanned into n.
// 将扫描到的wifi个数存储到n中
delay(100);
M5.Lcd.println("");
for (int i = 0; i < n; ++i) { // Save each wifi name scanned to ssidList.
// 将扫描到的每个wifi名称保存到ssidList中
ssidList += "<option value=\"";
ssidList += WiFi.SSID(i);
ssidList += "\">";
ssidList += WiFi.SSID(i);
ssidList += "</option>";
}
delay(100);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(apSSID); // Turn on Ap mode. 开启Ap模式
WiFi.mode(WIFI_MODE_AP); // Set WiFi to soft-AP mode. 设置WiFi为soft-AP模式
startWebServer(); // Open the web service. 打开Web服务
M5.Lcd.printf("\nStarting Access Point at \"%s\"\n\n", apSSID);
}
void setup() {
M5.begin(); // Init M5Core2. 初始化M5Core2
M5.Lcd.setTextColor(
YELLOW); // Set the font color to yellow. 设置字体颜色为黄色
preferences.begin("wifi-config");
delay(10);
if (restoreConfig()) { // Check if wifi configuration information has been
// stored. 检测是否已存储wifi配置信息
if (checkConnection()) { // Check wifi connection. 检测wifi连接情况
settingMode = false; // Turn off setting mode. 关闭设置模式
startWebServer(); // Turn on network service. 开启网络服务
return; // Exit setup(). 退出setup()
}
}
settingMode =
true; // If there is no stored wifi configuration information, turn on
// the setting mode. 若没有已存储的wifi配置信息,则开启设置模式
setupMode();
}
void loop() {
if (settingMode) {
}
webServer
.handleClient(); // Check that there is no facility to send requests to
// the M5StickC Web server over the network.
// 检查有没有设备通过网络向M5Core2网络服务器发送请求
}
関数を結びつけたフローチャート
上のプログラムはM5Stackの方で丁寧に英語でのコメントを残してくださっているので,プログラムを順に追っていけばどこで何をやっているのかわかると思います。
参考までに,最初に提示したフローチャートとプログラム内のどこの関数が結びついているか,を明記したフローチャートを下に載せておきます。
一応解説
基本的にはプログラム上のコメント,上のフローチャートを見てください。ここでは,いろいろ初めての方用に,特に触れてこなかった部分の解説を残しておきます。
makePage関数
この関数が何をしているか,htmlでページを作ったことがある方はわかると思います。
String s = "<!DOCTYPE html><html lang='ja'><head>";
s += "<meta name='viewport' content='width=device-width,user-scalable=0'>"
"<meta charset='UTF-8'><title>";
s += title;
s += "</title></head><body style='font-family: SF Pro JP, SF Pro Text, SF Pro Icons, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3,"
"メイリオ, Meiryo, MS Pゴシック, Helvetica Neue, Helvetica, Arial, sans-serif'>";
s += contents;
s += "</body></html>";
return s;
これ,こういう書き方になるとわかりづらいですね。見慣れているhtmlのコードに直してみましょう。
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta name='viewport' content='width=device-width,user-scalable=0'>
<meta charset='UTF-8'>
<title>【title】</title>
</head>
<body style='font-family: SF Pro JP, SF Pro Text, SF Pro Icons, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, メイリオ, Meiryo, MS Pゴシック, Helvetica Neue, Helvetica, Arial, sans-serif'>
【contents】
</body>
</html>
何も難しいことやっていませんでしたね。単純に,上のコードの改行がないものを生成するだけの関数でした。
startWebServer関数
webServer.on("/xx", [](){FUNC});
はIPアドレス/xx
にアクセスされた時,FUNC
部を実行します。
webServer.send
はクライアント(操作端末)にレスポンスを送信します。本関数内では,200
(リクエスト成功)というレスポンスとともに,text/html
形式のデータを送り付けます。要するに,新たなhtmlコードを送りつけてクライアント側に新たなページを表示させるわけです。
Preferencesとは
Preferences は,NVS(不揮発性ストレージ)領域にデータを保存・読み取りができるものです。
Preferences preferences
を定義のもと...
-
preferences.begin("wifi-config");
でデータセットに移動 -
preferences.getString("WIFI_SSID");
でStringデータを取得(wifi-config/WIFI_SSID
内の) -
preferences.putString("WIFI_SSID", ssid);
でStringデータを保存(wifi-config/WIFI_SSID
内に) -
preferences.remove("WIFI_SSID");
でデータを消去(wifi-config/WIFI_SSID
内の)
詳しい情報に関しては,
https://docs.espressif.com/projects/arduino-esp32/en/latest/tutorials/preferences.html
にあります。
WiFiについて
WiFi.
の部分に関しては,公式ドキュメント
https://docs.m5stack.com/ja/arduino/m5core/wifi
にサンプルとともに概要が示されているので,こちらを参照ください。
結果
- SSIDやパスワードが14字以上でも,正常にLCDに表示された
- IPアドレスにアクセスして表示されるページが日本語に対応した
- スマホ等から設定したWiFiに接続できた
本記事は以上です。お疲れ様でした。
参考文献