前提
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)
- ただし、STAT_CONNECT_FAILは未定義だった
- 実際の数字との対応はこちらに従っている https://mpython.readthedocs.io/en/latest/library/micropython/network.html#network.WLAN.status
- 古いファームウェアだとnetwork.STAT_WRONG_PASSWORDやnetwork.STAT_NO_AP_FOUNDが定義されていなかったり、別の数字が割り当てられていたりした
ファームウェアは最新のものを使うこと
-
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']
投稿者の人気記事
-
nihsok
さんが
2024/06/17
に
編集
をしました。
(メッセージ: 初版)
-
nihsok
さんが
2024/06/20
に
編集
をしました。
(メッセージ: ファームウェアバージョンの記述を修正)
ログインしてコメントを投稿する