nihsokのアイコン画像
nihsok 2024年06月17日作成 (2024年06月20日更新) © GPL-3.0+
セットアップや使用方法 セットアップや使用方法 閲覧数 364
nihsok 2024年06月17日作成 (2024年06月20日更新) © GPL-3.0+ セットアップや使用方法 セットアップや使用方法 閲覧数 364

今どきのESP32(ファームウェアv1.23.0)でのWi-Fi接続設定

前提

ESP32を使ってMiroPythonでWi-Fiに接続したい。
公式ドキュメント (https://docs.micropython.org/en/latest/esp32/quickref.html#networking) では以下のようなサンプルプログラムが載っているが、提供されている機能が活用されておらずやや物足りない。

def do_connect(): import network wlan = network.WLAN(network.STA_IF) wlan.active(True) if not wlan.isconnected(): print('connecting to network...') wlan.connect('ssid', 'key') while not wlan.isconnected(): pass print('network config:', wlan.ifconfig())

環境

ハードウェア:ESP32-WROOM-32D on ESP32-Devkit4
ファームウェア:ESP32_GENERIC-20240602-v1.23.0.bin (https://micropython.org/download/ESP32_GENERIC/) 後述するように、古いファームウェアだと設定されていない定数があるので注意
Raspberry Pi PicoWでも同様の機能が利用できるはずだが、バージョン等細かな差異はあると思われる。

スクリプト

wifi.py

import utime def connect(r=10): import network with open('wifi.txt') as f: ssid,passwd = f.read().split("\r\n") wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.config(reconnects=1) #2.5s/1try if wlan.isconnected(): wlan.disconnect() wlan.connect(ssid,passwd) stat = wlan.status() while not wlan.isconnected(): utime.sleep(1) stat = wlan.status() if (stat == network.STAT_IDLE): continue #1000 if (stat == network.STAT_CONNECTING): continue #1001 break if (stat == network.STAT_GOT_IP): #1010 print('GOT_IP') return wlan.ifconfig() elif (stat == network.STAT_WRONG_PASSWORD): print('WRONG_PASSWORD') #202 print(ssid+' is found, but password is incorrect.') elif (stat == network.STAT_NO_AP_FOUND): print('NO_AP_FOUND') #201 print([tuple[0] for tuple in wlan.scan() if tuple[0] != b'']) else: print('unknown error: '+stat)

main.py

import wifi print(wifi.connect())

wifi.txt

任意のSSID 任意のパスワード

動作の説明

wifi.txtに記述されているSSIDとパスワードを使いWi-Fi接続を試みる。

  • network.STAT_IDLEかnetwork.STAT_CONNECTINGの状態の間はループし続ける。
  • 成功した場合はIPを返す
  • パスワードが違う場合はその旨をコンソールに表示。返り値は無し
  • アクセスポイントが見つからない場合はアクセスポイントのスキャン結果一覧を表示。返り値は無し

注意点

  • wlan.status()で得られるステータスのうち、主なものはここに書いてある (https://docs.micropython.org/en/latest/library/network.WLAN.html)

  • wlan.scan()の返答はここに書いてある通り https://docs.micropython.org/en/latest/library/network.WLAN.html
    タプル (ssid, bssid, channel, RSSI, security, hidden) のうちssid以外はいらないので削っている。また、なぜか空のSSIDがいくつも見つかるのでそれも捨てている。

  • Python3.10で再送されたmatch-caseはMicroPythonでは使えないので、elifで場合分けしている。

  • if wlan.isconnected(): wlan.disconnect() のところでいちど切断するようにしているが、完全にはリセットされずに前の状態を引き継いでいるおりエラーが解消されないことがある。ルーター側の挙動もありそう。電源を外して放置すれば解消するが、できればソフトウェア的に解消したい。(今後の課題)

備考

networkで定義されている定数の一覧

>>> dir(network) ['__class__', '__init__', '__name__', 'AP_IF', 'AUTH_MAX', 'AUTH_OPEN', 'AUTH_OWE', 'AUTH_WAPI_PSK', 'AUTH_WEP', 'AUTH_WPA2_ENTERPRISE', 'AUTH_WPA2_PSK', 'AUTH_WPA2_WPA3_PSK', 'AUTH_WPA3_PSK', 'AUTH_WPA_PSK', 'AUTH_WPA_WPA2_PSK', 'ETH_CONNECTED', 'ETH_DISCONNECTED', 'ETH_GOT_IP', 'ETH_INITIALIZED', 'ETH_STARTED', 'ETH_STOPPED', 'LAN', 'MODE_11B', 'MODE_11G', 'MODE_11N', 'MODE_LR', 'PHY_DM9051', 'PHY_DP83848', 'PHY_IP101', 'PHY_KSZ8041', 'PHY_KSZ8081', 'PHY_KSZ8851SNL', 'PHY_LAN8710', 'PHY_LAN8720', 'PHY_RTL8201', 'PHY_W5500', 'PPP', 'STAT_ASSOC_FAIL', 'STAT_BEACON_TIMEOUT', 'STAT_CONNECTING', 'STAT_GOT_IP', 'STAT_HANDSHAKE_TIMEOUT', 'STAT_IDLE', 'STAT_NO_AP_FOUND', 'STAT_WRONG_PASSWORD', 'STA_IF', 'WLAN', '__dict__', 'country', 'hostname', 'phy_mode']
1
1
  • nihsok さんが 2024/06/17 に 編集 をしました。 (メッセージ: 初版)
  • nihsok さんが 2024/06/20 に 編集 をしました。 (メッセージ: ファームウェアバージョンの記述を修正)
ログインしてコメントを投稿する