以下基本範例是利用 ESP32 作為一個 Wi-Fi 熱點,讓其他裝置連線後,透過網頁控制ESP32板上的內建 LED 燈開關。整體功能包含以下幾個部分:
- Wi-Fi 熱點設定:透過 WiFi.softAP() 建立 ESP32 自己的無線網路,並可自訂 IP、閘道與子網路遮罩。
- 事件監控:能即時偵測裝置連線與斷線,並顯示其 MAC 與 IP 位址。
- 裝置清單顯示:除了控制功能,也列出目前有幾台裝置連線到 ESP32。
- 建立Web Server:利用 ESP32 內建 HTTP 伺服器,當用戶透過瀏覽器連上 ESP32 時,能透過網頁控制 LED 燈開關。
const int ledPin = 2; // 第2腳接LED燈(內建)
//-------------------------------------------------------------------------------------------------------------------------
#include <WiFi.h> // 引用WiFi函式庫
const char *ssid="SSID"; // 熱點名稱
const char *password="密碼"; // 熱點密碼
void startAP() // 啟用熱點
{
/*
IPAddress local_ip(192,168,31,31); // 設定熱點的IP位址
IPAddress gateway(192,168,31,2); // 設定熱點的閘道位址
IPAddress subnet(255,255,255,0); // 設定熱點的子網路遮罩位址
WiFi.softAPConfig(local_ip, gateway, subnet); // 設定熱點參數(未設定時,熱點IP位址預設為192.168.4.1)
*/
while(!WiFi.softAP(ssid, password)) // 若熱點尚未啟動,則每0.5秒印出一個點
{
delay(500);
Serial.print(".");
}
Serial.println("\n----------------------------------");
Serial.println("熱點啟動成功");
Serial.print("IP Address: ");
Serial.println(WiFi.softAPIP()); // 印出熱點的IP位址
}
//-------------------------------------------------------------------------------------------------------------------------
#include <esp_wifi.h> // 引用esp_wifi函式庫
void WiFiEvent(WiFiEvent_t event, arduino_event_info_t info) // WiFi事件處理函式
{
uint8_t* mac = nullptr; // 宣告MAC位址指標
char macStr[18] = {0}; // 儲存格式化MAC位址的字串緩衝區
switch (event)
{
case ARDUINO_EVENT_WIFI_AP_STACONNECTED: // 裝置已連線
// 從事件資訊中提取MAC位址,並將MAC位址格式化為字串(XX:XX:XX:XX:XX:XX)
mac = info.wifi_ap_staconnected.mac;
snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.println("\n[事件] 裝置已連線");
Serial.print("MAC: ");
Serial.println(macStr);
listConnectedStations(); // 更新並顯示當前連線裝置清單
break;
case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: // 裝置斷開連線
// 從事件資訊中提取MAC位址,並將MAC位址格式化為字串(XX:XX:XX:XX:XX:XX)
mac = info.wifi_ap_stadisconnected.mac;
snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Serial.println("\n[事件] 裝置已斷開連線");
Serial.print("MAC: ");
Serial.println(macStr);
listConnectedStations(); // 更新並顯示當前連線裝置清單
break;
}
}
//-------------------------------------------------------------------------------------------------------------------------
void listConnectedStations() // 印出已連線裝置清單
{
wifi_sta_list_t station_list; // 儲存連線裝置列表的結構
esp_wifi_ap_get_sta_list(&station_list); // 獲取當前連接到AP的所有裝置列表
Serial.println("--------- 當前連線裝置清單 ---------");
Serial.print("連線裝置數量: ");
Serial.println(station_list.num);
Serial.println("----------------------------------");
if (station_list.num > 0) {
Serial.println("編號 MAC 位址 IP 位址");
Serial.println("----------------------------------");
for (int i = 0; i < station_list.num; i++) {
wifi_sta_info_t station = station_list.sta[i];
// 取得 MAC 位址
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",station.mac[0], station.mac[1], station.mac[2], station.mac[3], station.mac[4], station.mac[5]);
// 取得 IP 位址 (需要透過 DHCP 租約列表)
IPAddress ip = WiFi.softAPIP();
ip[3] = i + 2; // 預設分配從 .2 開始
// 顯示裝置資訊
Serial.printf("%2d %s %s\n", i + 1, macStr, ip.toString().c_str());
}
} else {
Serial.println("目前沒有裝置連線");
}
Serial.println("----------------------------------");
}
//-------------------------------------------------------------------------------------------------------------------------
#include <WebServer.h>
WebServer server(80); // 建立WebServer物件, port為80
void handleRoot() // 根目錄
{
String html ="<h1>歡迎光臨!請點選下列按鈕:</h1> <h2><a href=\"/on\">LED ON</a></h2> <h2><a href=\"/off\">LED OFF</a></h2>";
server.send(200, "text/html; charset=UTF-8", html);
}
void handleOn() // LED ON
{
digitalWrite(ledPin, HIGH);
String html ="<h1>歡迎光臨!請點選下列按鈕:</h1> <h2><span style=\"color:#ff0000\"><strong>LED ON</strong></span></h2> <h2><a href=\"/off\">LED OFF</a></h2> <h2><a href=\"/\">首頁</a></h2>";
server.send(200, "text/html; charset=UTF-8", html);
}
void handleOff() // LED OFF
{
digitalWrite(ledPin, LOW);
String html ="<h1>歡迎光臨!請點選下列按鈕:</h1> <h2><a href=\"/on\">LED ON</a></h2> <h2><span style=\"color:#ff0000\"><strong>LED OFF</strong></span></h2> <h2><a href=\"/\">首頁</a></h2>";
server.send(200, "text/html; charset=UTF-8", html);
}
void handleNotFound() // 找不到網頁
{
String html = "找不到網頁";
server.send(404, "text/html; charset=UTF-8", html);
}
//-------------------------------------------------------------------------------------------------------------------------
void setup() {
pinMode(ledPin, OUTPUT); // 設定LED為輸出腳
Serial.begin(9600); // 啟用串列埠監看視窗
startAP(); // 啟用熱點
WiFi.onEvent(WiFiEvent); // 啟用WiFi事件處理
listConnectedStations(); // 印出已連線裝置清單
//---------------------------WebServer設定---------------------------
server.on("/", handleRoot); // 在/時,前往handleRoot()
server.on("/on", handleOn); // 在/on時,前往handleOn()
server.on("/off", handleOff); // 在/off時,前往handleOff()
server.onNotFound(handleNotFound); // 找不到網頁時,前往handleNotFound()
server.begin();
Serial.println("Server已啟動");
//-------------------------------------------------------------------
}
void loop() {
server.handleClient(); // 檢查是否有客戶端向ESP32 WebServer發送請求
}
利用 線上網頁編輯器 及 HTML to Arduino ,可將網頁內容轉換成 ESP32 Arduino 字串,再使用server.sent()方法送到 WebServer 。






作業練習:依下列頁面要求,利用 ESP32 的熱點模式,透過網頁遠端控制ESP32內建LED燈開、關、閃爍(使用millis()函式,每0.5秒切換一次)。





思考方向參考:
//-------------------------------------------------------------------------------------
const int ledPin = 2; // LED接腳
bool ledState = LOW; // LED狀態,初始值為LOW(OFF)
bool blinkEnable = LOW; // 閃爍控制,初始值為LOW (停止)
unsigned long previousMillis = 0; // 前一次的millis()時間
int interval = 500; // 預設計時的時間(ms)
//-------------------------------------------------------------------------------------
#include <WiFi.h> // 引用WiFi函式庫
const char *ssid="SSID"; // 熱點名稱
const char *password="密碼"; // 熱點密碼
//-------------------------------------------------------------------------------------
void startAP() // 啟用熱點
{
// 不變
}
//-------------------------------------------------------------------------------------
#include <esp_wifi.h> // 引用esp_wifi函式庫
void WiFiEvent(WiFiEvent_t event, arduino_event_info_t info) // WiFi事件處理函式
{
// 不變
}
//-------------------------------------------------------------------------------------
void listConnectedStations() // 印出已連線裝置清單
{
// 不變
}
//-------------------------------------------------------------------------------------
#include <WebServer.h>
WebServer server(80); // 建立WebServer物件, port為80
void handleRoot() // 根目錄
{
String html = "根目錄頁面內容";
server.send(200, "text/html; charset=UTF-8", html);
}
void handleOn() // LED ON
{
blinkEnable = false;
digitalWrite(ledPin, HIGH);
String html = "/on頁面內容";
server.send(200, "text/html; charset=UTF-8", html);
}
void handleOff() // LED OFF
{
blinkEnable = false;
digitalWrite(ledPin, LOW);
String html = "/off頁面內容";
server.send(200, "text/html; charset=UTF-8", html);
}
void handleBlink() // LED Blink
{
blinkEnable = !blinkEnable;
String html;
if (blinkEnable == true)
{
html ="正在閃爍頁面內容";
}
else
{
html = "停止閃爍頁面內容";
}
server.send(200, "text/html; charset=UTF-8", html);
}
void handleNotFound() // 找不到網頁
{
String html = "找不到網頁";
server.send(404, "text/html; charset=UTF-8", html);
}
//-------------------------------------------------------------------------------------
void setup() {
pinMode(ledPin, OUTPUT); // 設定LED為輸出腳
Serial.begin(9600); // 啟用串列埠監看視窗
//--------------------------- softAP設定 ----------------------------
// 不變
//---------------------------WebServer設定---------------------------
// 不變
server.on("/blink", handleBlink); // 在/blink時,前往handleBlink()
// 不變
//-------------------------------------------------------------------
}
void loop() {
server.handleClient(); // 檢查是否有客戶端向ESP32 WebServer發送請求
//--------------------------------------------------------------------------
// 控制啟動或停止LED燈閃爍
//--------------------------------------------------------------------------
}