4、ESP8266 AP模式实战:创建热点、Web服务器搭建、手机浏览器控制LED
这一章咱们来点真家伙。前面几章把ESP8266的基础讲透了,现在该让它自己当家做主了——不依赖家里的路由器,自己开一个Wi-Fi热点出来。说白了,就是让ESP8266当个小基站,手机直接连上去,通过浏览器控制它。
我在项目里经常用这个模式做设备配网。新买回来的智能设备,第一次怎么告诉它你家Wi-Fi密码?就是靠这个AP模式。先开热点,手机连上去,在网页里填好Wi-Fi信息,设备再切换到STA模式去连路由器。嗯,这个流程咱们后面章节会细讲,今天先把AP模式的基础打牢。
4.1 AP模式的核心概念
AP是Access Point的缩写,也就是接入点。ESP8266工作在AP模式时,它自己就是一个Wi-Fi网络的中心。其他设备(比如手机、电脑)可以搜索到它发出的信号,连接上来。
你想想看,这跟路由器有什么区别?其实本质上是一样的。只不过ESP8266的AP能力比较弱——它最多只能带4-5个客户端,覆盖范围也就十几米。但做调试、做配网、做小范围的设备控制,完全够用了。
AP模式 vs STA模式 对比
| 特性 | AP模式 | STA模式 |
|---|---|---|
| 角色 | 热点创建者 | 热点连接者 |
| 网络依赖 | 不依赖外部网络 | 需要已有Wi-Fi网络 |
| 客户端数量 | 通常≤5个 | 无限制(取决于路由器) |
| 典型用途 | 配网、本地控制 | 联网通信 |
| IP地址 | 固定为192.168.4.1 | 由路由器分配 |
4.2 创建Wi-Fi热点
先写一个最简单的程序,让ESP8266把自己的热点开起来。代码不长,但每一步都有讲究。
#include <ESP8266WiFi.h>
void setup() {
Serial.begin(115200);
delay(100);
Serial.println();
Serial.println("正在创建热点...");
// 设置AP模式
WiFi.mode(WIFI_AP);
// 创建热点
// 参数:SSID名称,密码(空=开放),信道,是否隐藏
WiFi.softAP("ESP8266_Demo", "12345678", 1, 0);
Serial.print("热点已创建!");
Serial.print("SSID: ESP8266_Demo");
Serial.print("IP地址: ");
Serial.println(WiFi.softAPIP());
}
void loop() {
// 暂时什么都不做
}
这里有几个细节我得提醒你。WiFi.softAP()函数的四个参数,我一个个说:
- SSID:热点名称,最好别用中文,有些手机连不上带中文的SSID。我踩过这个坑。
- 密码:至少8位。如果传空字符串"",就是开放热点,谁都能连。调试阶段可以开放,但正式产品一定要加密。
- 信道:1-13可选。默认1就行。如果周围Wi-Fi多,可以换个信道减少干扰。
- 隐藏:0表示广播SSID,手机能搜到。1表示隐藏,需要手动输入名称才能连。
小技巧:调试时我习惯把波特率设成115200,信息刷得快。但如果你用SoftwareSerial或者跟其他模块通信,可能要降到9600。看情况调整。
4.3 搭建Web服务器
热点开起来了,但光有热点没用。手机连上去之后,得有个东西让手机访问。这就是Web服务器的活儿。
ESP8266的Web服务器库用起来很简单。我一般用ESP8266WebServer这个库,它把HTTP请求的解析、路由、响应都封装好了。
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
// 创建Web服务器对象,监听80端口
ESP8266WebServer server(80);
void setup() {
Serial.begin(115200);
// 创建热点
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP8266_Control", "12345678");
Serial.print("AP IP: ");
Serial.println(WiFi.softAPIP());
// 设置路由
server.on("/", handleRoot);
server.on("/led/on", handleLedOn);
server.on("/led/off", handleLedOff);
// 启动服务器
server.begin();
Serial.println("Web服务器已启动");
}
void loop() {
// 处理客户端请求
server.handleClient();
}
// 处理根路径请求
void handleRoot() {
String html = "<h1>ESP8266 LED控制</h1>";
html += "<a href='/led/on'><button>开灯</button></a>";
html += "<a href='/led/off'><button>关灯</button></a>";
server.send(200, "text/html", html);
}
// 处理开灯请求
void handleLedOn() {
digitalWrite(LED_BUILTIN, LOW); // 注意:有些模块是低电平亮
server.send(200, "text/plain", "LED已打开");
}
// 处理关灯请求
void handleLedOff() {
digitalWrite(LED_BUILTIN, HIGH);
server.send(200, "text/plain", "LED已关闭");
}
这段代码的逻辑很直白:手机浏览器访问ESP8266的IP(192.168.4.1),服务器返回一个带按钮的网页。点"开灯"按钮,浏览器就请求/led/on这个地址,服务器收到后把LED引脚拉低,灯就亮了。
为什么会用LOW表示亮?这跟硬件设计有关。很多ESP8266开发板上的LED是共阳极接法,引脚输出低电平时LED两端电压差最大,灯就亮。如果你用的板子不一样,改成HIGH试试。
4.4 完整的控制流程
把上面两段代码合并,再加上LED引脚初始化,就是一个完整的AP模式LED控制程序了。
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define LED_PIN 2 // GPIO2,对应NodeMCU的D4
ESP8266WebServer server(80);
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH); // 初始状态:关闭
WiFi.mode(WIFI_AP);
WiFi.softAP("ESP8266_Control", "12345678");
Serial.println("");
Serial.print("热点已创建,IP: ");
Serial.println(WiFi.softAPIP());
server.on("/", handleRoot);
server.on("/led/on", handleLedOn);
server.on("/led/off", handleLedOff);
server.begin();
Serial.println("Web服务器已启动");
}
void loop() {
server.handleClient();
}
void handleRoot() {
String html = "<!DOCTYPE html>";
html += "<html>";
html += "<head>";
html += "<meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<title>LED控制</title>";
html += "<style>";
html += "body{text-align:center;font-family:Arial;margin-top:50px}";
html += "button{font-size:24px;padding:15px 30px;margin:10px;border-radius:8px}";
html += ".on{background-color:#4CAF50;color:white}";
html += ".off{background-color:#f44336;color:white}";
html += "</style>";
html += "</head>";
html += "<body>";
html += "<h1>ESP8266 LED 控制面板</h1>";
html += "<a href='/led/on'><button class='on'>💡 开灯</button></a>";
html += "<a href='/led/off'><button class='off'>🔌 关灯</button></a>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleLedOn() {
digitalWrite(LED_PIN, LOW);
server.send(200, "text/html",
"<h1>LED已打开</h1><a href='/'>返回</a>");
}
void handleLedOff() {
digitalWrite(LED_PIN, HIGH);
server.send(200, "text/html",
"<h1>LED已关闭</h1><a href='/'>返回</a>");
}
注意:这段HTML是硬编码在代码里的。如果页面复杂了,这样写会很难维护。我建议把HTML存成字符串常量,或者用SPIFFS文件系统存成独立文件。后面章节会讲文件系统,到时候再优化。
4.5 知识体系与流程
这一章的核心逻辑,我用一张图给你理清楚。从ESP8266启动,到手机控制LED亮灭,整个链条一目了然。
4.6 避坑指南
这一套流程看起来简单,但实际跑起来可能会遇到几个问题。我把自己踩过的坑列出来,你遇到了直接对照排查。
坑1:手机连不上热点
我曾经遇到过手机搜不到ESP8266热点的情况。排查后发现是信道问题——国内有些手机只支持1-11信道,如果代码里设了13,手机就搜不到。解决办法:信道参数改成1到11之间的值。
坑2:网页打不开
手机连上热点后,浏览器输入192.168.4.1却打不开页面。原因通常是:手机自动获取的IP跟ESP8266不在同一个网段。检查手机Wi-Fi详情,看看IP是不是192.168.4.x。如果不是,在手机上设置静态IP,手动填192.168.4.100,网关填192.168.4.1。
坑3:LED不亮
代码烧进去,网页也打开了,点按钮LED没反应。先确认LED引脚号对不对。NodeMCU上板载LED是GPIO2,但有些模块是GPIO1或者GPIO16。另外注意电平逻辑——有的板子是低电平亮,有的是高电平亮。用万用表量一下最靠谱。
4.7 扩展思路
这一章只是AP模式的基础应用。你掌握了这个框架之后,可以往里面加很多东西:
- 多页面路由:不止控制LED,还可以加状态页面、配置页面
- AJAX异步刷新:不用每次点按钮都刷新整个页面,用JavaScript局部更新
- 参数传递:通过URL传参,比如/led/brightness?value=500,实现PWM调光
- RESTful API:用JSON格式返回数据,方便App或者上位机调用
我个人习惯先把基础框架搭好,再逐步加功能。这样出了问题好排查,每加一个功能都能验证是否正常工作。你刚开始做的时候,也建议按这个节奏来。