ESP32のWi-Fi設定について

ESP32にはWi-Fi機能が実装されており、APモード(アクセスポイントモード:サーバ)・STAモード(ステーションモード:クライアント)共の機能を持っています。通常はSTAモードを働かせ、アクセスポイントに接続し、クラウドへデータを送信するのが一般的かと思います。

そのアクセスポイントへはSSIDとパスワードにより接続するのですが、その設定においては次の方法があると思います。

  1. プログラムに埋め込む
  2. SDカードなどの外部メディアから読み込む
  3. スマートフォンなどからSmartConfigを用いて設定する
  4. スマートフォンなどから soft APを使い設定する

先の1(プログラムに埋め込む)および2(SDカードなどの外部メディア)については特に記載する必要はないかと思います。そして番号は逆さまになりますが、4のsoft APを使い、スマホなどから設定する方法としてmgo-tec様がESP32をSSHサーバとしてセキュアな方法での設定方法を説明されています。ご本人は素人とご謙遜されていますが、非常に有用な記事です。

Arduino – ESP32 で SSLサーバーを構築し、セキュアな Wi-Fi アクセスポイントセレクターを作ってみました
Arduino - ESP32 で soft AP モードの 「信頼ある」証明書付き SSL サーバーを構築し、スマホの...

この記事は、多くの人が理解できるよう丁寧に記載されおり、きっと苦労して作成されたのだろうという感が伝わってきます。そして詳しく読み込んでいくと非常に勉強になります。

ここではSmartConfigを用いる方法を記載してみたいと思います。まずESP32の場合、一度WiFiを設定すると次の起動で、前回接続情報が呼び出され、新たに設定する必要がありません。またWiFiが切断されても環境が整えば自動的に再度、自動接続してくれます。ただ一方、環境によっては新たにSmartConfigで設定したい場合もあると思います。

起動時、WiFiが10秒以内に接続できない場合、またボタンが長押しされた場合、SmartConfigで設定できるようにしてみます。なおLEDでWiFiの接続状況(SmartConfig設定中は点滅・WiFiが接続されている場合は点灯)が分かるようにします。

ArduinoIDEを用いたプログラムは次の通りです。

#include <WiFi.h>

#define SW  39                                // スイッチのPIN番号
#define LED 33                                // LEDのPIN番号

uint32_t startTime = 0;
enum BTN_STATUS { Release, ON_start, MomentPress_Determined, LongPress_Determined, Continuous_Press }
btnStatus = Release;

void setWiFi() {
  WiFi.mode(WIFI_AP);                         // APモードで動作...
  WiFi.beginSmartConfig();                    // SmartConfigを有効化
  Serial.println("Waiting for SmartConfig."); // 設定待ち
  while (!WiFi.smartConfigDone()) {
    digitalWrite(LED, HIGH);
    delay(250);
    Serial.print(".");
    digitalWrite(LED, LOW);
    delay(250);
  }
  WiFi.mode(WIFI_STA);                        // STAモードで動作...
  WiFi.begin();
}

//=========================================================================
//! 以下、URL情報からソースをいただいています。
//! https://www.mgo-tec.com/blog-entry-m5stack-button-arduino-esp32.html/4
//=========================================================================
uint8_t My_Button(const uint8_t gpio, BTN_STATUS *button_status, uint32_t *start_time, boolean continuous_set, uint32_t chatter_time, uint32_t long_press_time) {
  uint8_t ret_state = Release;
  switch ( digitalRead(gpio) ) {
    case LOW: // LOW = 0
      switch ( *button_status ) {
        case Release:
          *button_status = ON_start;
          *start_time = millis(); //reset start_time
          break;
        case ON_start:
          if ( continuous_set ) {
            if ( Time_Mesure(*start_time) > long_press_time ) {
              *button_status = Continuous_Press;
            }
          } else {
            if ( Time_Mesure(*start_time) > long_press_time ) {
              *button_status = LongPress_Determined;
              ret_state = LongPress_Determined;
            }
          }
          break;
        case Continuous_Press:
          if ( Time_Mesure(*start_time) > long_press_time ) {
            *start_time = millis(); //reset start_time
            return Continuous_Press;
          }
          break;
        default:
          break;
      }
      break;
    case HIGH: // HIGH = 1
      if ( *button_status == ON_start ) {
        if ( Time_Mesure(*start_time) > chatter_time ) {
          ret_state = MomentPress_Determined;
        }
      }
      *button_status = Release;
      break;
    default:
      break;
  }
  return ret_state;
}

uint32_t Time_Mesure( uint32_t st_time ) {
  return millis() - st_time;
}

void setup() {
  Serial.begin(9600);                         // シリアルモニタの設定
  Serial.println("");
  pinMode(SW, INPUT);                         // INPUTモードの設定
  pinMode(LED, OUTPUT);                       // INPUTモードの設定
  // WiFi開始
  WiFi.mode(WIFI_STA);
  WiFi.begin();
  unsigned long ftm = millis() + 10 * 1000;   //! 起動時のWiFi接続のタイムアウト(10秒)
  Serial.println("WiFi connecting...");
  while ((WiFi.status() != WL_CONNECTED) & (millis() < ftm)) {
    Serial.print('*');
    delay(500);
  }
  Serial.println("");
  // 前回情報で接続できなければ、SmartConfigで設定…
  if (WiFi.status() != WL_CONNECTED) setWiFi();
  Serial.printf("Connected, IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("WiFi connected!");
}

void loop() {
  // ボタンが長押し(2秒)されているか確認...
  uint8_t btnState = My_Button(SW, &btnStatus, &startTime, false, 10, 2000);
  // 長押しされたらWiFiを設定する
  if (btnState == LongPress_Determined) setWiFi();
  // WiFiに接続されていれば点灯...
  digitalWrite(LED, (WiFi.status() == WL_CONNECTED));
}

次に手持ちのiPhoneから[iot maker]として検索し、IoT Makerを入手します。Androidでも同様です。

 起動し、SSIDとPasswordを設定し、先のプログラム起動時、またはボタンを長押ししてLEDが点滅している間にSubmitボタンを押します。

出来上がりはこんな感じです。