前回に引き続いて ESP32 の無線 LAN 通信の電力を削減する Tips を紹介します.
はじめに
前回は,ESP32 のソフトを変更することで,無線 LAN 通信時間を削減しました.一方,紹介した内容を取り込んでも,アクセスポイントに接続してから SYSTEM_EVENT_STA_GOT_IP イベントが発生するまでに 1 秒以上消費していることが多いかと思います.
今回は,ネットワーク側の設定を変更することで,この部分の時間を大幅に短縮する方法を紹介します.
問題
ESP32 のDHCP 関連の動作ログを出力させてみると下記のようになります.ポイントとなる箇所を黄色背景にしてあります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@ 881 ms dhcp_start(netif=0x3ffc5700) st1 @ 881 ms dhcp_start(): starting new DHCP client @ 881 ms dhcp_start(): allocated dhcp@ 881 ms dhcp_start(): starting DHCP configuration @ 881 ms dhcp_discover() @ 881 ms transaction id xid(81da2d19) @ 891 ms dhcp_discover: making request @ 891 ms dhcp_discover: realloc()ing @ 891 ms dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT) @ 901 ms dhcp_discover: deleting()ing @ 911 ms dhcp_discover: SELECTING @ 911 ms dhcp_discover(): set request timeout 500 msecs @1111 ms dhcp_coarse_tmr() @1111 ms dhcp_fine_tmr(): request timeout @1111 ms dhcp_timeout() @1111 ms dhcp_timeout(): restarting discovery @1111 ms dhcp_discover() @1111 ms transaction id xid(81da2d19) @1111 ms dhcp_discover: making request @1121 ms dhcp_discover: realloc()ing @1121 ms dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT) @1131 ms dhcp_discover: deleting()ing @1131 ms dhcp_discover: SELECTING @1131 ms dhcp_discover(): set request timeout 1000 msecs @1911 ms dhcp_recv(pbuf = 0x3ffc58b8) from DHCP server 192.168.2.2 port 67 |
最初,500ms のタイプアウト設定で DHCP DISCOVER を送信し,それがタイムアウトした後,タイプアウト時間を 1000ms に変更して再度 DHCP DISCOVER を送信しています.そして,最初に DISCOVER を送信してから 1 秒近く経過してから応答を受け取っています.
ここから,SYSTEM_EVENT_STA_GOT_IP イベントの発生に時間がかかっているのは,DHCP サーバ側の応答が遅いことにに起因することがわかります.
実は,多くの DHCP サーバでは DISCOVER メッセージに対して OFFER メッセージで応答する前に,割り当て予定の IP アドレスがすでに使われていないかチェックする機能を持っています.このチェックは,割り当て予定の IP アドレスに対して Ping を行い,一定時間に応答が無いことを確認することで行われます.従って,この機能を使う限り,DHCP サーバーの応答には一定時間のディレイが生じてしまいます.
解決策
問題が DHCP サーバーの挙動によるものなので,DHCP サーバーの種類によって解決策も異なります.ここでは,下記の2つの場合について紹介します.
- ISC DHCP server
- Yamaha ルータ
これ以外の DHCP サーバを使っている場合でも,「DHCP チェック」などのキーワードでマニュアルを調べると,設定方法があるかもしれません.
ISC DHCP server の場合
Linux 等で DHCP サーバーを運用している場合はこちらが該当します.この場合,対策には大きく次の 2 つの方法があります.
- IP アドレスの固定化
- Ping チェックの廃止
IP アドレスの固定化は,dhcpd.conf に下記のように MAC アドレスと IP アドレスの組を記載することで行います.
1 2 3 4 |
host ESP32-outdoor { hardware ethernet xx:xx:xx:xx:xx:xx; # ESP32 のMAC アドレス fixed-address 192.168.XX.XX; # 割り当てる IP アドレス } |
この方法の利点としては,Ping チェックは依然として有効なので,ネットワークに行儀の悪いクライアントがいても従来通り安定運用できることが挙げられます.
一方,Ping チェックがそもそも不要,という場合は下記の設定を行います.
1 |
ping-check false; |
Yamaha ルータの場合
Yamaha ルータの場合,「dhcp duplicate check」というキーワードで検索すると,Ping チェックを無効かする方法が紹介されています.
IP アドレスの固定化でも効果は得られると思いますが,こちらは試していません.
効果
この設定を行うことで,無線LAN 接続時間は下図のように,大きく減少します.
動作ログを確認すると,下記のようになります.dhcp_start
から dhcp_recv
まで 40ms 程度しかかかっていません.対策前は約 1 秒かかっていたので,大幅な時間短縮です.
1 2 3 4 5 6 7 8 9 10 11 12 |
@ 871ms dhcp_start(netif=0x3ffc52a0) st1 @ 871ms dhcp_start(): starting new DHCP client @ 871ms dhcp_start(): allocated dhcp@ 871ms dhcp_start(): starting DHCP configuration @ 881ms dhcp_discover() @ 881ms transaction id xid(4457806d) @ 881ms dhcp_discover: making request @ 891ms dhcp_discover: realloc()ing @ 891ms dhcp_discover: sendto(DISCOVER, IP_ADDR_BROADCAST, DHCP_SERVER_PORT) @ 901ms dhcp_discover: deleting()ing @ 901ms dhcp_discover: SELECTING @ 901ms dhcp_discover(): set request timeout 500 msecs @ 911ms dhcp_recv(pbuf = 0x3ffc5458) from DHCP server 192.168.2.2 port 67 |
環境にもよると思いますが,前回の内容と今回の内容を適用することで,手元の環境では無線 LAN 接続開始から通信可能になるまでの時間は約 4秒 → 約 1 秒に大幅に短縮できました.
前回記載したように,Deep Sleep モードを活用する場合,平均消費電力は無線 LAN 通信時間に比例するので,紹介した内容によって平均消費電力を 1/4 に削減できたことになります.
備考
今回はネットワーク側の設定変更で対応しましたが,下記で議論されている内容が ESP-IDF に織り込まれれば,二度目以降は DHCP DISCOVER がスキップされるようになるので,特に気にしなくて良くなりそうです.
[TW#14022] Wifi — SYSTEM_EVENT_STA_GOT_IP is taking over 4 seconds #799
補足
DHCP の動作ログを時間付きで出力するには,ESP-IDF に下記の変更を行います.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
diff --git a/components/lwip/include/lwip/lwip/debug.h b/components/lwip/include/lwip/lwip/debug.h index 973a633..b13fea2 100755 --- a/components/lwip/include/lwip/lwip/debug.h +++ b/components/lwip/include/lwip/lwip/debug.h @@ -32,6 +32,8 @@ #ifndef LWIP_HDR_DEBUG_H #define LWIP_HDR_DEBUG_H +#include "esp_log.h" + #include "lwip/arch.h" #include "lwip/opt.h" @@ -102,6 +104,7 @@ ((debug) & LWIP_DBG_ON) && \ ((debug) & LWIP_DBG_TYPES_ON) && \ ((s16_t)((debug) & LWIP_DBG_MASK_LEVEL) >= LWIP_DBG_MIN_LEVEL)) { \ + printf("@%4dms ", esp_log_timestamp()); \ LWIP_PLATFORM_DIAG(message); \ if ((debug) & LWIP_DBG_HALT) { \ while(1); \ diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index 4652c6d..59e2eb8 100644 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -762,7 +762,7 @@ enum { /** * DHCP_DEBUG: Enable debugging in dhcp.c. */ -#define DHCP_DEBUG LWIP_DBG_OFF +#define DHCP_DEBUG LWIP_DBG_ON #define LWIP_DEBUG LWIP_DBG_OFF #define TCP_DEBUG LWIP_DBG_OFF |
コメント