第11章 ESP32 WiFi 完整教學:Wi-Fi 連線、WiFi Scan、IP、RSSI 與自動重連

發布日期: |更新日期:
文章主圖:第11章 ESP32 WiFi 完整教學:Wi-Fi 連線、WiFi Scan、IP、RSSI 與自動重連

ESP32 前面的 GPIO、ADC、PWM、I²C、SPI、UART 等功能,主要都在處理「ESP32 與周邊硬體之間的連接」。從本章開始,我們正式進入 ESP32 最重要、也最有價值的特色之一:Wi-Fi 無線網路與 IoT 網路應用。

ESP32 本身整合 Wi-Fi 功能,因此不像 Arduino UNO R3 通常需要另外加裝 Wi-Fi Shield、ESP8266 或其他網路模組。只要透過 Arduino IDE 內建於 ESP32 Core 的 WiFi.h,就能讓 ESP32 連接家中路由器、手機熱點或公司的無線網路。

連上 Wi-Fi 之後,ESP32 就可以進一步實作:

  • 網頁伺服器 Web Server
  • HTTP / HTTPS API
  • MQTT
  • IoT 感測器
  • 手機遠端控制
  • 雲端資料上傳
  • 網路時間 NTP
  • OTA 無線更新
  • Home Assistant
  • LINE / Telegram 通知
  • 即時環境監控

因此,學會 ESP32 WiFi 是從一般微控制器專題跨入真正 IoT 系統的重要分水嶺。

本章將完整介紹:

WiFi.h、Station Mode、STA、SSID、Password、DHCP、IP Address、RSSI、MAC Address、Wi-Fi Scan 與 Wi-Fi 自動重連,最後完成一個:

ESP32 Wi-Fi 掃描器 + 網路狀態顯示器

讓 ESP32 可以掃描附近基地台、連接指定 Wi-Fi,並持續顯示 IP、MAC、SSID、RSSI 與目前連線狀態。

一、什麼是 ESP32 Wi-Fi?

ESP32 內建 Wi-Fi 無線網路功能,可以直接和無線基地台 Access Point、Wi-Fi Router 或手機熱點通訊。

Arduino ESP32 官方 Wi-Fi API 支援 Station、Access Point 以及 Wi-Fi 網路掃描等功能。目前官方 Arduino-ESP32 文件也持續以 WiFi.h 作為 Arduino 環境下操作 ESP32 Wi-Fi 的主要介面。

ESP32 常見的 Wi-Fi 運作模式主要有三種:

ESP32 Wi-Fi 運作模式比較
模式 說明 常見用途
STA Station Mode ESP32 連接家中 Router
AP Access Point Mode 手機直接連 ESP32
AP + STA 同時使用 AP 與 STA 設定介面、IoT Gateway

本章首先學習最重要也最常使用的:

STA Station Mode

二、什麼是 Station Mode?

Station Mode 簡稱:

STA

在 STA 模式中,ESP32 的角色就和:

  • Notebook
  • iPhone
  • Android 手機
  • 平板電腦
  • Smart TV

類似。

也就是:

ESP32
  │
  │ Wi-Fi
  ▼
Wireless Router
  │
  ├── LAN
  │
  └── Internet

ESP32 主動加入現有 Wi-Fi 網路,而不是自己建立一個 Wi-Fi 基地台。

Arduino ESP32 官方文件將 STA 定義為 ESP32 連接到 Access Point 的模式;如果 ESP32 專案需要透過既有網路連上 Internet,STA 就是最主要的使用方式。

程式中通常使用:

WiFi.mode(WIFI_STA);

設定 ESP32 為 Station Mode。

三、ESP32 WiFi.h 函式庫

Arduino IDE 開發 ESP32 Wi-Fi 最重要的函式庫就是:

#include <WiFi.h>

只要安裝好:

ESP32 Arduino Core

通常不需要另外安裝第三方 Wi-Fi Library。

最基本的 ESP32 WiFi 程式只有幾行:

#include <WiFi.h>

const char* ssid = "你的WiFi名稱";
const char* password = "你的WiFi密碼";

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi Connected!");

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
}

官方 Arduino ESP32 文件也是以:

WiFi.begin(ssid, password);

開始 STA 連線,並使用:

WiFi.status() == WL_CONNECTED

判斷是否完成連線,再使用:

WiFi.localIP()

取得 IP Address。

四、什麼是 SSID?

SSID 全名是:

Service Set Identifier

簡單來說,就是:

Wi-Fi 網路名稱。

例如手機看到:

WCST_2.4G
ASUS_WIFI
Jason_Home
TP-Link_A520
iPhone

這些就是 SSID。

ESP32 程式通常寫成:

const char* ssid = "WCST_WIFI";

連線時:

WiFi.begin(ssid, password);

五、Password Wi-Fi 密碼

如果 Wi-Fi 有 WPA / WPA2 / WPA3 等密碼保護,就需要提供 Password。

例如:

const char* password = "12345678";

再使用:

WiFi.begin(ssid, password);

完整形式:

const char* ssid = "WCST_WIFI";
const char* password = "your_password";

WiFi.begin(ssid, password);

正式產品中不建議直接將真正 Wi-Fi 密碼公開在 GitHub 或公開下載的 .ino 程式裡。

比較好的做法是另外建立:

secrets.h

例如:

#define WIFI_SSID "WCST_WIFI"
#define WIFI_PASSWORD "your_password"

然後:

#include "secrets.h"

這對未來 ESP32 IoT 專案會非常重要。

六、WiFi.status():判斷 ESP32 網路狀態

ESP32 可以利用:

WiFi.status()

取得目前 Wi-Fi 狀態。

最常使用的是:

if (WiFi.status() == WL_CONNECTED)

代表 ESP32 已經成功連接 Wi-Fi。

例如:

if (WiFi.status() == WL_CONNECTED) {
  Serial.println("WiFi Connected");
}
else {
  Serial.println("WiFi Disconnected");
}

常見 Wi-Fi 狀態

常見狀態包括:

ESP32 常見 Wi-Fi 連線狀態
狀態 意義
WL_CONNECTED 已成功連線
WL_NO_SSID_AVAIL 找不到指定 SSID
WL_CONNECT_FAILED Wi-Fi 連線失敗
WL_CONNECTION_LOST 連線中斷
WL_DISCONNECTED 尚未連線或已斷線
WL_IDLE_STATUS Wi-Fi 正在處理

因此不要只在 ESP32 開機時檢查 Wi-Fi。

真正穩定的 IoT 程式還必須持續監控:

WiFi.status()

七、什麼是 DHCP?

ESP32 連接 Wi-Fi 之後還需要一個 IP Address 才能進行 TCP/IP 網路通訊。

一般情況不需要自己指定。

家庭 Router 通常會執行:

DHCP Server

自動分配:

  • IP Address
  • Gateway
  • Subnet Mask
  • DNS Server

給 ESP32。

例如:

ESP32
   │
   ▼
Wi-Fi Router
   │
   ├── IP:192.168.1.105
   ├── Gateway:192.168.1.1
   ├── Mask:255.255.255.0
   └── DNS:192.168.1.1

這就是:

DHCP 自動取得 IP。

所以最基本的程式:

WiFi.begin(ssid, password);

連線成功之後,一般就會由網路中的 DHCP Server 分配 IP。

若未來有需要,也可以使用 WiFi.config() 設定 Static IP;Arduino ESP32 官方 API 提供 local IP、Gateway、Subnet 與 DNS 的自訂設定能力。

八、取得 ESP32 IP Address

Wi-Fi 連線完成之後,可以使用:

WiFi.localIP()

讀取 ESP32 的 IP Address。

例如:

Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

Serial Monitor 可能顯示:

IP Address: 192.168.1.105

這個 IP 非常重要。

下一章開始建立:

ESP32 Web Server

時,瀏覽器就是利用這個 IP 找到 ESP32。

例如:

http://192.168.1.105/

九、ESP32 MAC Address 是什麼?

除了 IP Address 之外,每個網路介面還具有 MAC Address。

MAC 是:

Media Access Control Address

一般格式例如:

24:6F:28:12:34:56

ESP32 可以使用:

WiFi.macAddress()

讀取 Station Wi-Fi MAC Address:

Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());

輸出可能是:

MAC Address: 24:6F:28:12:34:56

IP 與 MAC 有什麼差別?

可以簡單理解為:

MAC Address → 網路卡身分
IP Address  → 目前所在網路上的通訊地址

例如:

MAC Address 與 IP Address 範例
項目 範例
MAC 24:6F:28:12:34:56
IP 192.168.1.105

DHCP 分配的 IP 可能會改變,但 MAC 通常用來識別同一個網路裝置。

因此 Router 的:

DHCP Reservation

功能通常也是根據 MAC Address 幫 ESP32 固定 IP。

十、RSSI:判斷 ESP32 Wi-Fi 訊號強度

ESP32 可以讀取目前 Wi-Fi 訊號強度:

WiFi.RSSI()

RSSI:

Received Signal Strength Indicator

單位通常為:

dBm

例如:

Serial.print("RSSI: ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");

可能輸出:

RSSI: -48 dBm

RSSI 數字為什麼是負數?

Wi-Fi RSSI 越接近:

0

代表訊號越強。

所以:

-40 dBm

比:

-80 dBm

強很多。

可大致用下表判斷:

ESP32 Wi-Fi RSSI 訊號品質參考
RSSI 訊號品質
-30 ~ -50 dBm 非常強
-50 ~ -60 dBm 很好
-60 ~ -67 dBm 良好
-67 ~ -70 dBm 普通
-70 ~ -80 dBm 偏弱
小於 -80 dBm 很弱

這只是實務上的概略判斷值,實際連線品質還會受到:

  • AP 品質
  • 天線
  • ESP32 模組
  • 牆壁
  • 金屬遮蔽
  • Wi-Fi Channel
  • 同頻干擾

影響。

十一、ESP32 WiFi Scan 是什麼?

ESP32 不只可以連接 Wi-Fi,也可以像手機一樣:

搜尋附近所有 Wi-Fi 基地台。

最重要的函式為:

WiFi.scanNetworks();

例如:

int n = WiFi.scanNetworks();

n 就代表掃描到多少個 Wi-Fi Network。

官方 Wi-Fi API 的 scanNetworks() 同時支援同步、非同步、隱藏網路與指定 Channel 等進階參數;掃描完成後也可以利用 scanDelete() 清除上一輪掃描資料、釋放相關記憶體。

十二、第一個 ESP32 Wi-Fi Scan 程式

先做一個最基本的掃描程式。

#include <WiFi.h>

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  delay(1000);

  Serial.println("Scanning WiFi...");

  int n = WiFi.scanNetworks();

  if (n == 0) {
    Serial.println("No WiFi networks found.");
  }
  else {
    Serial.print(n);
    Serial.println(" networks found:");

    for (int i = 0; i < n; i++) {

      Serial.print(i + 1);
      Serial.print(": ");

      Serial.print(WiFi.SSID(i));

      Serial.print("  RSSI=");
      Serial.print(WiFi.RSSI(i));

      Serial.print(" dBm  CH=");
      Serial.println(WiFi.channel(i));
    }
  }

  WiFi.scanDelete();
}

void loop() {
}

Serial Monitor 可能看到:

Scanning WiFi...

6 networks found:

1: WCST_WIFI      RSSI=-41 dBm  CH=6
2: ASUS_HOME      RSSI=-54 dBm  CH=11
3: TP-Link_1234   RSSI=-63 dBm  CH=1
4: iPhone         RSSI=-70 dBm  CH=6
5: Office_WIFI    RSSI=-78 dBm  CH=11
6: Guest          RSSI=-85 dBm  CH=1

此時 ESP32 已經變成簡單的:

Wi-Fi Scanner。

十三、Wi-Fi Channel 是什麼?

掃描結果中還可以取得:

WiFi.channel(i)

例如:

CH 1
CH 6
CH 11

代表 Wi-Fi 使用的無線頻道。

如果附近有很多基地台都集中在相同頻道,就可能造成:

Wi-Fi Interference

因此 ESP32 WiFi Scan 不只是找 SSID,也可以作為簡單的:

2.4 GHz Wi-Fi 環境分析工具。

十四、ESP32 連接指定 Wi-Fi

現在加入真正的 Wi-Fi Connection。

#include <WiFi.h>

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

void setup() {

  Serial.begin(115200);

  WiFi.mode(WIFI_STA);

  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi Connected!");

  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  Serial.print("MAC Address: ");
  Serial.println(WiFi.macAddress());

  Serial.print("RSSI: ");
  Serial.print(WiFi.RSSI());
  Serial.println(" dBm");
}

void loop() {
}

十五、為什麼不建議永遠卡在 while 等 Wi-Fi?

很多初學範例會寫:

while (WiFi.status() != WL_CONNECTED) {
  delay(500);
}

教學沒有問題,但正式系統要小心。

假設:

  • Router 關機
  • SSID 寫錯
  • Password 寫錯
  • AP 故障

ESP32 就可能永遠卡在:

while()

後面的:

  • 感測器
  • 按鍵
  • LCD
  • Relay
  • Safety Control

全部不會執行。

比較好的方式是加入:

Connection Timeout。

例如:

unsigned long startTime = millis();

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED &&
       millis() - startTime < 15000) {

  delay(500);
  Serial.print(".");
}

最多等:

15 秒

如果仍連不上,ESP32 可以繼續做其他事情。

這才比較符合 IoT 裝置的實際設計。

十六、ESP32 Wi-Fi 自動重連

IoT 裝置通常 24 小時開機。

如果 Router:

  • 重新開機
  • 短暫斷電
  • Wi-Fi Restart
  • 訊號短暫消失

ESP32 不應該需要人工 Reset。

Arduino ESP32 提供:

WiFi.setAutoReconnect(true);

啟用自動重新連線。

例如:

WiFi.mode(WIFI_STA);

WiFi.setAutoReconnect(true);

WiFi.begin(ssid, password);

另外還可以手動執行:

WiFi.reconnect();

目前 Arduino ESP32 官方文件仍提供 reconnect() 與 setAutoReconnect();相較之下,舊的 setAutoConnect() 已被標示為 deprecated,因此新程式不建議再依賴 setAutoConnect()。

十七、推薦的 Wi-Fi 重連機制

正式程式最好同時保留:

Auto Reconnect
+
定期 Status Check
+
Manual Reconnect Fallback

例如:

if (WiFi.status() != WL_CONNECTED) {

  Serial.println("WiFi disconnected!");

  WiFi.reconnect();
}

但也不建議每一次 loop() 都執行 reconnect。

因為 loop() 可能一秒執行幾千甚至幾萬次。

應該加入時間控制。

例如每 10 秒檢查一次:

unsigned long lastReconnectAttempt = 0;

void loop() {

  if (WiFi.status() != WL_CONNECTED) {

    if (millis() - lastReconnectAttempt >= 10000) {

      lastReconnectAttempt = millis();

      Serial.println("Trying WiFi reconnect...");

      WiFi.reconnect();
    }
  }
}

這就是非常典型的 IoT 網路恢復設計。

十八、實作:ESP32 Wi-Fi 掃描器 + 網路狀態顯示

接下來把本章所有功能整合在一起。

功能包括:

  • ESP32 設定為 STA Mode
  • 掃描附近 Wi-Fi
  • 顯示 SSID
  • 顯示 RSSI
  • 顯示 Wi-Fi Channel
  • 連接指定 SSID
  • 取得 DHCP IP
  • 顯示 MAC Address
  • 顯示目前 Wi-Fi RSSI
  • 每 5 秒顯示一次 Network Status
  • Wi-Fi 中斷後自動重連
  • 避免程式因 Wi-Fi 故障永久卡死

完整程式

/*
 * 第 11 章
 * ESP32 Wi-Fi 掃描器 + 網路狀態顯示
 *
 * 功能:
 * 1. 掃描附近 Wi-Fi
 * 2. 顯示 SSID / RSSI / Channel
 * 3. 連接指定 Wi-Fi
 * 4. 顯示 IP / MAC / RSSI
 * 5. 持續監控 Wi-Fi 狀態
 * 6. Wi-Fi 中斷自動重連
 */

#include <WiFi.h>

// =====================================================
// Wi-Fi 設定
// =====================================================

const char* WIFI_SSID     = "YOUR_SSID";
const char* WIFI_PASSWORD = "YOUR_PASSWORD";

// =====================================================
// 時間設定
// =====================================================

unsigned long lastStatusTime = 0;
unsigned long lastReconnectTime = 0;

const unsigned long STATUS_INTERVAL    = 5000;
const unsigned long RECONNECT_INTERVAL = 10000;


// =====================================================
// Wi-Fi 狀態文字
// =====================================================

String getWiFiStatusText() {

  switch (WiFi.status()) {

    case WL_CONNECTED:
      return "CONNECTED";

    case WL_NO_SSID_AVAIL:
      return "SSID NOT FOUND";

    case WL_CONNECT_FAILED:
      return "CONNECT FAILED";

    case WL_CONNECTION_LOST:
      return "CONNECTION LOST";

    case WL_DISCONNECTED:
      return "DISCONNECTED";

    case WL_IDLE_STATUS:
      return "IDLE";

    default:
      return "UNKNOWN";
  }
}


// =====================================================
// RSSI 品質判斷
// =====================================================

String getRSSIQuality(int32_t rssi) {

  if (rssi >= -50)
    return "Excellent";

  else if (rssi >= -60)
    return "Very Good";

  else if (rssi >= -67)
    return "Good";

  else if (rssi >= -70)
    return "Fair";

  else if (rssi >= -80)
    return "Weak";

  else
    return "Very Weak";
}


// =====================================================
// 掃描附近 Wi-Fi
// =====================================================

void scanWiFi() {

  Serial.println();
  Serial.println("========================================");
  Serial.println("          ESP32 Wi-Fi Scanner");
  Serial.println("========================================");

  Serial.println("Scanning Wi-Fi networks...");

  int networkCount = WiFi.scanNetworks();

  if (networkCount <= 0) {

    Serial.println("No Wi-Fi networks found.");
  }

  else {

    Serial.print("Networks found: ");
    Serial.println(networkCount);

    Serial.println();
    Serial.println("No | SSID | RSSI | Channel");
    Serial.println("----------------------------------------");

    for (int i = 0; i < networkCount; i++) {

      Serial.print(i + 1);
      Serial.print(" | ");

      Serial.print(WiFi.SSID(i));
      Serial.print(" | ");

      Serial.print(WiFi.RSSI(i));
      Serial.print(" dBm | CH ");

      Serial.println(WiFi.channel(i));

      delay(10);
    }
  }

  WiFi.scanDelete();

  Serial.println("========================================");
}


// =====================================================
// 連接 Wi-Fi
// =====================================================

void connectWiFi() {

  Serial.println();
  Serial.println("Connecting to Wi-Fi...");

  Serial.print("SSID: ");
  Serial.println(WIFI_SSID);

  WiFi.mode(WIFI_STA);

  WiFi.setAutoReconnect(true);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  unsigned long startTime = millis();

  while (WiFi.status() != WL_CONNECTED &&
         millis() - startTime < 15000) {

    delay(500);

    Serial.print(".");
  }

  Serial.println();

  if (WiFi.status() == WL_CONNECTED) {

    Serial.println();
    Serial.println("*** Wi-Fi Connected ***");

    printNetworkInfo();
  }

  else {

    Serial.println();
    Serial.println("*** Wi-Fi Connection Failed ***");
    Serial.println("Program will continue and retry later.");
  }
}


// =====================================================
// 顯示網路資料
// =====================================================

void printNetworkInfo() {

  if (WiFi.status() != WL_CONNECTED) {

    Serial.println("Wi-Fi is not connected.");

    return;
  }

  Serial.println();
  Serial.println("========================================");
  Serial.println("          Network Information");
  Serial.println("========================================");

  Serial.print("SSID       : ");
  Serial.println(WiFi.SSID());

  Serial.print("IP Address : ");
  Serial.println(WiFi.localIP());

  Serial.print("MAC Address: ");
  Serial.println(WiFi.macAddress());

  int32_t rssi = WiFi.RSSI();

  Serial.print("RSSI       : ");
  Serial.print(rssi);
  Serial.println(" dBm");

  Serial.print("Signal     : ");
  Serial.println(getRSSIQuality(rssi));

  Serial.print("Status     : ");
  Serial.println(getWiFiStatusText());

  Serial.println("========================================");
}


// =====================================================
// Setup
// =====================================================

void setup() {

  Serial.begin(115200);

  delay(1000);

  Serial.println();
  Serial.println("ESP32 Wi-Fi Scanner + Network Monitor");
  Serial.println();

  // 設為 STA
  WiFi.mode(WIFI_STA);

  // 先掃描附近 Wi-Fi
  scanWiFi();

  // 再連接指定 Wi-Fi
  connectWiFi();
}


// =====================================================
// Loop
// =====================================================

void loop() {

  // -------------------------------------------------
  // Wi-Fi 已連線
  // -------------------------------------------------

  if (WiFi.status() == WL_CONNECTED) {

    if (millis() - lastStatusTime >= STATUS_INTERVAL) {

      lastStatusTime = millis();

      printNetworkInfo();
    }
  }

  // -------------------------------------------------
  // Wi-Fi 已斷線
  // -------------------------------------------------

  else {

    if (millis() - lastReconnectTime >= RECONNECT_INTERVAL) {

      lastReconnectTime = millis();

      Serial.println();
      Serial.print("Wi-Fi Status: ");
      Serial.println(getWiFiStatusText());

      Serial.println("Trying to reconnect...");

      WiFi.reconnect();
    }
  }
}

十九、修改自己的 SSID 與 Password

上傳程式之前請修改:

const char* WIFI_SSID = "YOUR_SSID";

改成自己的 Wi-Fi,例如:

const char* WIFI_SSID = "WCST_WIFI";

Password:

const char* WIFI_PASSWORD = "YOUR_PASSWORD";

例如:

const char* WIFI_PASSWORD = "12345678";

二十、Arduino IDE 設定

以一般 ESP32-WROOM-32 / ESP32 Dev Module 為例:

Tools
→ Board
→ ESP32 Arduino
→ ESP32 Dev Module

再選擇正確:

COM Port

Serial Monitor Baud Rate 設定:

115200

因為程式使用:

Serial.begin(115200);

二十一、程式執行結果

正常啟動後可能看到:

ESP32 Wi-Fi Scanner + Network Monitor

========================================
          ESP32 Wi-Fi Scanner
========================================
Scanning Wi-Fi networks...

Networks found: 5

No | SSID | RSSI | Channel
----------------------------------------
1 | WCST_WIFI | -42 dBm | CH 6
2 | ASUS_HOME | -55 dBm | CH 11
3 | TP-Link | -64 dBm | CH 1
4 | Guest | -72 dBm | CH 6
5 | iPhone | -83 dBm | CH 11

========================================

Connecting to Wi-Fi...
SSID: WCST_WIFI
......

*** Wi-Fi Connected ***

========================================
          Network Information
========================================
SSID       : WCST_WIFI
IP Address : 192.168.1.105
MAC Address: 24:6F:28:12:34:56
RSSI       : -43 dBm
Signal     : Excellent
Status     : CONNECTED
========================================

之後每:

5 秒

更新一次 Wi-Fi 狀態。

二十二、測試 Wi-Fi 自動重連

這是一個很值得實際操作的實驗。

  1. ESP32 正常連接 Router。;應看到:;Status : CONNECTED
  2. 將 Router Wi-Fi 暫時關閉。;ESP32 將變成:;Wi-Fi Status: CONNECTION LOST Trying to reconnect...;或:;Wi-Fi Status: DISCONNECTED
  3. 重新開啟 Wi-Fi Router。;ESP32 不需要 Reset。;Auto Reconnect 與程式中的重試機制會嘗試重新恢復連線。;這正是實際 IoT 裝置非常重要的:;Fault Recovery / Connection Recovery;能力。

二十三、Wi-Fi Scan、RSSI 與 IoT 有什麼實際用途?

很多人第一次看到:

WiFi.scanNetworks();

會認為只是示範程式。

其實 WiFi Scan 在正式產品上非常實用。

應用一:Wi-Fi 設定介面

ESP32 第一次開機時:

掃描附近 AP
        ↓
列出 SSID
        ↓
使用者選 Wi-Fi
        ↓
輸入 Password
        ↓
ESP32 儲存設定
        ↓
自動連線

很多 IoT 裝置第一次設定網路就是使用類似方式。

應用二:Wi-Fi 訊號品質監測

例如:

int rssi = WiFi.RSSI();

若:

RSSI < -75 dBm

可以顯示:

Wi-Fi Signal Weak

甚至透過 LCD / OLED 顯示訊號。

應用三:IoT 設備安裝測試

ESP32 放在:

  • 工廠
  • 倉庫
  • 溫室
  • 機房
  • 屋頂
  • 戶外控制箱

時,可以先測:

RSSI

確認 Wi-Fi 訊號是否足夠。

應用四:選擇較好的 Access Point

大型環境可能有:

AP-1
AP-2
AP-3

利用 Scan 搭配 RSSI,就能判斷哪個 Access Point 訊號最好。

未來還可以進一步使用:

WiFiMulti

管理多組 AP。

Arduino ESP32 官方 Wi-Fi API 也提供 WiFiMulti,可以預先加入多組 Access Point,讓 ESP32 在 Station 模式下管理多個候選 Wi-Fi。

二十四、ESP32 WiFi 常見問題

Q1:ESP32 一直顯示 Connecting WiFi 怎麼辦?

先檢查:

SSID
Password

是否正確。

另外確認 ESP32 與 Router 的頻段相容。

Q2:Wi-Fi 找得到但連不上?

可能包括:

  • Password 錯誤
  • AP Security 設定
  • Router 黑名單
  • MAC Filter
  • DHCP 問題
  • Wi-Fi 訊號太弱
  • Router 同時連線數過多

可以先執行:

WiFi.scanNetworks();

確認 ESP32 是否能看到該 SSID。

Q3:ESP32 IP 每次都不一樣?

因為一般使用:

DHCP

所以 Router 可能每次分配不同 IP。

解決方式可以使用:

方法一

Router:

DHCP Reservation

利用 ESP32 MAC Address 固定 IP。

方法二

ESP32 使用:

WiFi.config()

設定 Static IP。

一般家庭或企業 IoT 專案,我比較建議:

由 Router 做 DHCP Reservation。

管理會比每一台 ESP32 都寫死 Static IP 更方便。

二十五、ESP32 WiFi 常用指令整理

ESP32 WiFi 常用指令整理
功能 指令
引入 Wi-Fi #include <WiFi.h>
STA Mode WiFi.mode(WIFI_STA)
連接 Wi-Fi WiFi.begin(ssid,password)
Wi-Fi 狀態 WiFi.status()
是否連線 WL_CONNECTED
IP Address WiFi.localIP()
SSID WiFi.SSID()
RSSI WiFi.RSSI()
MAC Address WiFi.macAddress()
Scan WiFi.scanNetworks()
Scan SSID WiFi.SSID(i)
Scan RSSI WiFi.RSSI(i)
Channel WiFi.channel(i)
清除掃描資料 WiFi.scanDelete()
自動重連 WiFi.setAutoReconnect(true)
手動重連 WiFi.reconnect()
斷開連線 WiFi.disconnect()

二十六、ESP32 與 Arduino UNO 的網路能力差異

這也是 ESP32 相對 Arduino UNO R3 最大的優勢之一。

Arduino UNO R3 與 ESP32 網路能力比較
功能 Arduino UNO R3 ESP32
GPIO ✓ ✓
ADC ✓ ✓
PWM ✓ ✓
UART ✓ ✓
SPI ✓ ✓
I²C ✓ ✓
Wi-Fi × ✓
Bluetooth × ✓
Web Server 需網路模組 ✓
IoT 需額外硬體 ✓

Arduino UNO 若要上網,通常需要:

UNO
+
ESP8266

或:

UNO
+
Ethernet Shield

ESP32 則直接具備無線網路能力。

因此 ESP32 特別適合:

Sensor
   ↓
ESP32
   ↓ Wi-Fi
Router
   ↓
Internet
   ↓
Cloud / Server / App

二十七、ESP32 WiFi 的完整學習路線

本章可以視為 ESP32 IoT 教材的真正起點。

目前我們已經完成:

ESP32
 │
 ├── GPIO
 ├── Digital Input
 ├── ADC
 ├── PWM
 ├── Touch
 ├── I²C
 ├── SPI
 ├── UART
 │
 └── Wi-Fi ← 本章

接下來就可以開始:

Wi-Fi
 ↓
TCP/IP
 ↓
HTTP
 ↓
Web Server
 ↓
REST API
 ↓
MQTT
 ↓
Cloud
 ↓
完整 IoT 系統

從這裡開始,ESP32 已經不再只是一塊「控制 LED 與感測器的開發板」。

它開始成為真正的:

Networked Embedded System

也就是:

具備網路能力的嵌入式系統。

二十八、本章實作架構

本章完成的:

ESP32 Wi-Fi 掃描器 + 網路狀態顯示

整體流程如下:

ESP32 開機
    │
    ▼
WiFi.mode(WIFI_STA)
    │
    ▼
掃描附近 Wi-Fi
    │
    ├── SSID
    ├── RSSI
    └── Channel
    │
    ▼
WiFi.begin()
    │
    ▼
連接 Router
    │
    ▼
DHCP
    │
    ▼
取得 IP Address
    │
    ├── SSID
    ├── IP
    ├── MAC
    └── RSSI
    │
    ▼
每 5 秒檢查 Wi-Fi
    │
    ├── Connected ──→ 顯示網路狀態
    │
    └── Disconnected
              │
              ▼
        WiFi.reconnect()
              │
              ▼
          恢復連線

這個程式架構後面可以直接沿用在:

  • ESP32 Web Server
  • ESP32 MQTT
  • ESP32 HTTP Client
  • ESP32 Firebase
  • ESP32 ThingSpeak
  • ESP32 Home Assistant
  • ESP32 IoT Sensor
  • ESP32 遠端控制

等專案中。

二十九、本章重點整理

完成本章後,應該掌握以下觀念:

1. ESP32 WiFi 函式庫

#include <WiFi.h>

2. Station Mode

WiFi.mode(WIFI_STA);

ESP32 連接現有 Router。

3. SSID 與 Password

WiFi.begin(ssid, password);

4. 判斷連線

WiFi.status() == WL_CONNECTED

5. DHCP

一般情況由 Router 自動分配 IP。

6. IP Address

WiFi.localIP();

7. MAC Address

WiFi.macAddress();

8. RSSI

WiFi.RSSI();

數字越接近 0,通常代表訊號越強。

9. WiFi Scan

WiFi.scanNetworks();

搜尋附近 Access Point。

10. Wi-Fi 自動重連

WiFi.setAutoReconnect(true);

並搭配:

WiFi.reconnect();

提高 IoT 系統長時間運行的可靠性。

三十、結語

ESP32 最重要的價值,不只是 GPIO 比 Arduino UNO 多、CPU 比 Arduino UNO 快,而是它把:

微控制器
+
Wi-Fi
+
TCP/IP
+
Bluetooth

整合在同一顆 MCU 中。

因此當我們學會:

ESP32 WiFi、ESP32 WiFi Scan、SSID、DHCP、IP Address、RSSI、MAC Address 與 Wi-Fi 自動重連

之後,就已經完成進入 IoT 世界最重要的基礎建設。

本章的 ESP32 Wi-Fi 掃描器 + 網路狀態顯示器 不只是練習程式。

它實際建立了後面所有網路專案都會使用的共同架構:

搜尋網路
→ 連接網路
→ 取得 IP
→ 判斷網路品質
→ 持續監控
→ 斷線恢復

下一階段就可以在這套 Wi-Fi 基礎之上建立:

ESP32 Web Server

讓手機或電腦直接透過瀏覽器存取 ESP32,正式進入 ESP32 網頁控制與 IoT 應用。

下一步學習

不要停在這一篇,接著把內容做成自己的實作

目前主題:Arduino。從完整學習路線、免費資源、會員下載,再接到實作所需材料。

同系列:ESP32 |  已是會員?直接前往 Getfile
相關資源與會員文章下載
文章可免費閱讀;下載完整 DOCX 或 PDF 需登入免費基本會員。
查看相關資源 會員免費下載 DOCX 會員免費 PDF/列印

← 回文章列表