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亮灭,整个链条一目了然。

ESP8266 AP模式 LED控制流程 1. 初始化 WiFi.mode(WIFI_AP) 2. 创建热点 softAP("ESP8266_Control") 3. 启动Web服务器 server.begin() 等待手机连接热点 手机连接热点 Wi-Fi设置中选择SSID 浏览器访问 http://192.168.4.1 服务器返回网页 handleRoot() 用户点击按钮 /led/on 或 /led/off 执行控制 digitalWrite(LED_PIN) 💡 关键点 AP模式IP固定为 192.168.4.1

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或者上位机调用

我个人习惯先把基础框架搭好,再逐步加功能。这样出了问题好排查,每加一个功能都能验证是否正常工作。你刚开始做的时候,也建议按这个节奏来。