ESP32を使用する場合、WiFiを常に接続し、切断されたら再接続するという場合が多くみられます。
メインルーチンで監視し、WiFiが切断したら再接続するという方法でも良いのですが、WiFi接続には時間を要す場合があるため、データを取得したり、サーバへデータを送信したりとうメインルーチンでの作業に影響がある可能性があります。
その場合、WiFi接続を別のスレッドに定義することが有効です。
また複数の接続ポイントに対応したWiFiMultiというクラスが用意されています。一度設定したSSID/PASSWORDはESP32の不揮発性メモリに記憶させておきます。
下のサンプルではM5 stack core2を使用しています(ボードマネージャー esp32 by Espresslf 2.0.17 / Arduino IDE 2.3.2)。
<_header.h>
C++
#ifndef HEADER_H
#define HEADER_H
#include <M5Core2.h>
//! タスクハンドル(マルチスレッド)
TaskHandle_t thp[1];
//! WiFiアクセスポイント設定
String ssid = "Your SSID";
String pass = "Your PASSWORD";
#endif
<main.ino>
C++
#include "_header.h"
void setup() {
M5.begin();
writePref(ssid, pass);
//! スレッドを実行...
xTaskCreatePinnedToCore(connectWiFi, "connectWiFi", 4096, NULL, 5, &thp[0], 0);
}
void loop() {
Serial.println("WiFi signal strength :" + String(getRSSI()));
delay(3000);
}
<T_WiFi.ino>
C++
#include <Preferences.h> // 不揮発性メモリへの記録(Wi-Fi情報)
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
Preferences preferences; // declare class object
const char* prefKey = "mms"; //! 不揮発性メモリのキー値
/* =================================================================================
機能:preferencesにWIFI情報を書き込む...
引数:第一引数 SSID
第二引数 パスワード
戻値:なし
================================================================================= */
void writePref(String PrefSSID, String PrefPass) {
// Serial.println("Write Pref " + PrefSSID + "/" + PrefPass);
preferences.begin("multi_wifi", false);
//! 何個、情報が書き込まれているか...
int cnt = preferences.getInt("cnt", 0);
//! 1個以上の情報があり、すでに書き込まれていたらすでに書き込まれているか確認...
bool duplication = false;
if (0 < cnt) {
for (int i = 0; i < cnt; i++) {
String tempA = preferences.getString(("ssid_" + String(i + 1)).c_str(), "");
String tempB = preferences.getString(("psk_" + String(i + 1)).c_str(), "");
if ((tempA == PrefSSID) and (tempB == PrefPass)) {
duplication = true;
}
}
}
//! 重複せずSSIDが空でなかったら書き込み...
if (!duplication && PrefSSID != "") {
preferences.putString(("ssid_" + String(cnt + 1)).c_str(), PrefSSID);
preferences.putString(("psk_" + String(cnt + 1)).c_str(), PrefPass);
preferences.putInt("cnt", cnt + 1);
Serial.println("ADD SSID/PSK " + PrefSSID + "/" + PrefPass);
}
preferences.end();
}
/* =================================================================================
機能:WiFiに接続する...
引数:汎用ポインタ
戻値:なし
================================================================================= */
void connectWiFi(void* args) {
while (1) {
if (wifiMulti.run() != WL_CONNECTED) {
// WiFi.mode(WIFI_MODE_NULL);
WiFi.disconnect();
preferences.begin("multi_wifi", true);
//! 何個、情報が書き込まれているか...
int cnt = preferences.getInt("cnt", 0);
Serial.println("WiFi COUNT is " + String(cnt));
delay(1000);
//! 1個以上の情報があり、すでに書き込まれていたらすでに書き込まれているか確認...
Serial.println("========= WiFi List =========");
if (0 < cnt) {
for (int i = cnt; 0 < i; i--) {
String tempA = preferences.getString(("ssid_" + String(i)).c_str(), "");
String tempB = preferences.getString(("psk_" + String(i)).c_str(), "");
if (tempA != "" && tempB != "") {
Serial.println(tempA + "/" + tempB);
wifiMulti.addAP(tempA.c_str(), tempB.c_str());
} else {
Serial.println("--- Empty account, ignore. ---");
}
}
}
preferences.end();
delay(1000);
if (wifiMulti.run() == WL_CONNECTED) {
Serial.println("[WiFi] WiFi connected [" + WiFi.SSID() + "]");
} else {
Serial.println("[WiFi] Could not connect to wifi");
}
}
delay(3000);
}
}
/* =================================================================================
機能:WiFiのステータスを得る
引数:<なし>
戻値:接続していたらtrue そうでないならfalse
================================================================================= */
boolean get_wifi_status() {
return WiFi.status() == WL_CONNECTED;
}
/* =================================================================================
機能:WiFiの電波強度を得る(一般的には-75dBmより大きい数字が理想・切断時は0)
引数:<なし>
戻値:電波強度(dBm)
================================================================================= */
long getRSSI() {
if (WiFi.status() != WL_CONNECTED) {
return 0;
} else {
return WiFi.RSSI();
}
}