【花雕学编程】239种传感器执行器系列实验(资料代码+仿真编程+图形编程)
实验二百四十六:ESP8266串口wifi模块 NodeMCU Lua V3物联网开发板 CH340
实验项目之十四:ESP8266 Web 服务器:从手机控制组件
来自百科,“Web 服务器是服务器软件或专门用于运行此软件的硬件,可以满足万维网上的客户端请求”。本例子中,使用ESP8266(NodeMCU V3)的功能来充当我们的 Web 服务器并托管我们的网站。在浏览器中键入 Web 服务器的地址发出“请求”,并收到了 html 标记形式的“响应”。NodeMCU ESP8266 Web 服务器接收此请求并使用 HTML 响应进行回复。它还处理我们组件的接口,因此它会检查来自 Web 浏览器的请求并采取相应的行动。ESP8266 芯片及其最新的 ESP32 芯片都是关于 wifi 和连接的。这使其非常适合我们的物联网 (IOT) 项目。
实验开源代码
/*
【花雕学编程】239种传感器执行器系列实验(资料代码+仿真编程+图形编程)
实验二百四十六:ESP8266串口wifi模块 NodeMCU Lua V3物联网开发板 CH340
实验项目之十四:ESP8266 Web 服务器:从手机控制组件
*/
#include <ESP8266WiFi.h> // 包含ESP8266WiFi库,用于WiFi连接
#include <ESP8266WebServer.h> // 包含ESP8266WebServer库,用于创建Web服务器
/********** 请修改以下内容 *************************/
const char* ssid = "zhz3"; // 设置Wi-Fi名称
const char* password = "z156721"; // 设置Wi-Fi密码
ESP8266WebServer server(80); // 创建一个Web服务器对象,监听80端口
uint8_t LEDPin = D3; // 定义LED连接的引脚
bool LEDStatus = LOW; // 定义LED的初始状态(低电平)
uint8_t buzzerPin = D4; // 定义蜂鸣器连接的引脚
bool buzzerStatus = LOW; // 定义蜂鸣器的初始状态(低电平)
void setup() {
Serial.begin(115200); // 初始化串口通信,波特率为115200
Serial.println(" ");
Serial.println("正在连接Wi-Fi网络...");
pinMode(LEDPin, OUTPUT); // 设置LED引脚为输出模式
pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式
Serial.println("正在连接Wi-Fi网络...");
Serial.println(ssid);
// 连接到本地Wi-Fi网络
WiFi.begin(ssid, password);
// 检查Wi-Fi是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println("");
Serial.println("Wi-Fi连接成功!");
Serial.print("获取到的IP地址: ");
Serial.println(WiFi.localIP()); // 打印ESP8266的IP地址
// 设置Web服务器的路由和处理函数
server.on("/", handleRoot); // 根路径的处理函数
server.on("/toggleLED", updateLED); // 切换LED状态的处理函数
server.on("/toggleBuzzer", updateBuzzerSound); // 切换蜂鸣器状态的处理函数
server.onNotFound(handleNotFound); // 未找到路径的处理函数
server.begin(); // 启动Web服务器
Serial.println("HTTP服务器已启动");
}
void loop() {
server.handleClient(); // 处理客户端请求
}
// 处理根路径请求
void handleRoot() {
server.send(200, "text/html", prepareHTML()); // 返回HTML页面
}
// 切换LED状态
void updateLED() {
Serial.println("正在更新LED状态...");
LEDStatus = !LEDStatus; // 切换LED状态
digitalWrite(LEDPin, LEDStatus); // 更新LED引脚电平
server.send(200, "text/html", prepareHTML()); // 返回更新后的HTML页面
}
// 切换蜂鸣器状态
void updateBuzzerSound() {
Serial.println("正在更新蜂鸣器状态...");
buzzerStatus = !buzzerStatus; // 切换蜂鸣器状态
if (buzzerStatus)
tone(buzzerPin, 1200); // 打开蜂鸣器,频率为1200Hz
else
noTone(buzzerPin); // 关闭蜂鸣器
server.send(200, "text/html", prepareHTML()); // 返回更新后的HTML页面
}
// 处理未找到的路径
void handleNotFound() {
server.send(404, "text/plain", "路径未找到"); // 返回404错误
}
// 生成HTML页面
String prepareHTML() {
String html = "<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
"<title>NodeMCU ESP8266 Web Server</title>"
"<style>"
"/* 样式代码省略 */"
"</style>"
"</head>"
"<body>"
"<nav class=\"nav\" tabindex=\"-1\" onclick=\"this.focus()\">"
"<div class=\"container\">"
"<a class=\"pagename current\" href=\"#\">wwww.ESP8266.com</a>"
"</div>"
"</nav>"
""
"<div class=\"container\">"
"<div class=\"hero\">"
"<h1>NodeMCU ESP8266 Web Server</h1>"
"<div class=\"flex-container\">"
" <div class=\"flex-child magenta\">"
"<span class=\"component-label\">LED</span>"
" </div>"
" <div class=\"flex-child green\">"
"<div class=\"grid-child green\">"
"<div style=\"display: inline\">"
"<div class=\"onoffswitch\">";
if (LEDStatus)
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"ledSwitch\" tabindex=\"0\" checked onclick=\"window.location.href='toggleLED'\">";
else
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"ledSwitch\" tabindex=\"0\" onclick=\"window.location.href='toggleLED'\">";
html = html +
"<label class=\"onoffswitch-label\" for=\"ledSwitch\">"
"<span class=\"onoffswitch-inner\"></span>"
"<span class=\"onoffswitch-switch\"></span>"
"</label>"
"</div>"
"</div>"
"</div>"
" </div>"
"</div>"
"<div class=\"flex-container\">"
" <div class=\"flex-child magenta\">"
"<span class=\"component-label\">蜂鸣器</span>"
" </div>"
" <div class=\"flex-child green\">"
"<div class=\"grid-child green\">"
"<div style=\"display: inline\">"
"<div class=\"onoffswitch\">";
if (buzzerStatus)
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"buzzerSwitch\" tabindex=\"0\" checked onclick=\"window.location.href='toggleBuzzer'\">";
else
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"buzzerSwitch\" tabindex=\"0\" onclick=\"window.location.href='toggleBuzzer'\">";
html = html +
"<label class=\"onoffswitch-label\" for=\"buzzerSwitch\">"
"<span class=\"onoffswitch-inner\"></span>"
"<span class=\"onoffswitch-switch\"></span>"
"</label>"
"</div>"
"</div>"
"</div>"
" </div>"
"</div>"
"</div>"
"</div>"
"</body>"
"</html>";
return html; // 返回生成的HTML页面
}
以下是代码的详细注释,逐行解释每一部分的功能和作用:
1. 引入库
#include <ESP8266WiFi.h> // 引入ESP8266 Wi-Fi库,用于连接和管理Wi-Fi网络
#include <ESP8266WebServer.h> // 引入ESP8266 Web服务器库,用于创建HTTP服务器
2. 定义Wi-Fi配置
/********** 请修改以下内容 *************************/
const char* ssid = "<请输入您的Wi-Fi SSID>"; // 定义Wi-Fi名称(SSID)
const char* password = "<请输入您的Wi-Fi密码>"; // 定义Wi-Fi密码
3. 创建Web服务器对象
ESP8266WebServer server(80); // 创建一个Web服务器对象,监听80端口(HTTP默认端口)
4. 定义引脚和状态变量
uint8_t LEDPin = D7; // 定义LED连接的引脚(D7)
bool LEDStatus = LOW; // 定义LED的初始状态(低电平,表示关闭)
uint8_t buzzerPin = D1; // 定义蜂鸣器连接的引脚(D1)
bool buzzerStatus = LOW; // 定义蜂鸣器的初始状态(低电平,表示关闭)
5. setup() 函数
setup() 函数在设备启动时运行一次,用于初始化硬件和配置。
void setup() {
Serial.begin(115200); // 初始化串口通信,波特率为115200,用于调试信息输出
pinMode(LEDPin, OUTPUT); // 设置LED引脚为输出模式
pinMode(buzzerPin, OUTPUT); // 设置蜂鸣器引脚为输出模式
Serial.println("正在连接Wi-Fi网络...");
Serial.println(ssid);
// 连接到本地Wi-Fi网络
WiFi.begin(ssid, password);
// 检查Wi-Fi是否连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(1000); // 每隔1秒检查一次
Serial.print("."); // 打印连接状态(...)
}
Serial.println("");
Serial.println("Wi-Fi连接成功!");
Serial.print("获取到的IP地址: ");
Serial.println(WiFi.localIP()); // 打印ESP8266的IP地址,用于访问Web服务器
// 设置Web服务器的路由和处理函数
server.on("/", handleRoot); // 根路径("/")的处理函数
server.on("/toggleLED", updateLED); // 切换LED状态的路由("/toggleLED")的处理函数
server.on("/toggleBuzzer", updateBuzzerSound); // 切换蜂鸣器状态的路由("/toggleBuzzer")的处理函数
server.onNotFound(handleNotFound); // 未找到路径的处理函数
server.begin(); // 启动Web服务器
Serial.println("HTTP服务器已启动");
}
6. loop() 函数
loop() 函数在设备运行期间不断循环,用于处理客户端请求。
void loop() {
server.handleClient(); // 处理客户端请求
}
7. 处理根路径请求
当用户访问根路径(/)时,返回一个HTML页面。
void handleRoot() {
server.send(200, "text/html", prepareHTML()); // 返回HTTP状态码200和HTML页面
}
8. 切换LED状态
当用户访问 /toggleLED 路径时,切换LED的状态。
void updateLED() {
Serial.println("正在更新LED状态...");
LEDStatus = !LEDStatus; // 切换LED状态(开/关)
digitalWrite(LEDPin, LEDStatus); // 更新LED引脚电平
server.send(200, "text/html", prepareHTML()); // 返回更新后的HTML页面
}
9. 切换蜂鸣器状态
当用户访问 /toggleBuzzer 路径时,切换蜂鸣器的状态。
void updateBuzzerSound() {
Serial.println("正在更新蜂鸣器状态...");
buzzerStatus = !buzzerStatus; // 切换蜂鸣器状态(开/关)
if (buzzerStatus)
tone(buzzerPin, 1200); // 打开蜂鸣器,频率为1200Hz
else
noTone(buzzerPin); // 关闭蜂鸣器
server.send(200, "text/html", prepareHTML()); // 返回更新后的HTML页面
}
10. 处理未找到的路径
当用户访问未定义的路径时,返回404错误。
void handleNotFound() {
server.send(404, "text/plain", "路径未找到"); // 返回HTTP状态码404和错误信息
}
11. 生成HTML页面
动态生成包含LED和蜂鸣器控制开关的HTML页面。
String prepareHTML() {
String html = "<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset=\"UTF-8\">"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
"<title>NodeMCU ESP8266 Web Server</title>"
"<style>"
"/* 样式代码省略 */"
"</style>"
"</head>"
"<body>"
"<nav class=\"nav\" tabindex=\"-1\" onclick=\"this.focus()\">"
"<div class=\"container\">"
"<a class=\"pagename current\" href=\"#\">wwww.donskytech.com</a>"
"</div>"
"</nav>"
""
"<div class=\"container\">"
"<div class=\"hero\">"
"<h1>NodeMCU ESP8266 Web Server</h1>"
"<div class=\"flex-container\">"
" <div class=\"flex-child magenta\">"
"<span class=\"component-label\">LED</span>"
" </div>"
" <div class=\"flex-child green\">"
"<div class=\"grid-child green\">"
"<div style=\"display: inline\">"
"<div class=\"onoffswitch\">";
if (LEDStatus)
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"ledSwitch\" tabindex=\"0\" checked onclick=\"window.location.href='toggleLED'\">";
else
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"ledSwitch\" tabindex=\"0\" onclick=\"window.location.href='toggleLED'\">";
html = html +
"<label class=\"onoffswitch-label\" for=\"ledSwitch\">"
"<span class=\"onoffswitch-inner\"></span>"
"<span class=\"onoffswitch-switch\"></span>"
"</label>"
"</div>"
"</div>"
"</div>"
" </div>"
"</div>"
"<div class=\"flex-container\">"
" <div class=\"flex-child magenta\">"
"<span class=\"component-label\">蜂鸣器</span>"
" </div>"
" <div class=\"flex-child green\">"
"<div class=\"grid-child green\">"
"<div style=\"display: inline\">"
"<div class=\"onoffswitch\">";
if (buzzerStatus)
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"buzzerSwitch\" tabindex=\"0\" checked onclick=\"window.location.href='toggleBuzzer'\">";
else
html = html + "<input type=\"checkbox\" name=\"onoffswitch\" class=\"onoffswitch-checkbox\" id=\"buzzerSwitch\" tabindex=\"0\" onclick=\"window.location.href='toggleBuzzer'\">";
html = html +
"<label class=\"onoffswitch-label\" for=\"buzzerSwitch\">"
"<span class=\"onoffswitch-inner\"></span>"
"<span class=\"onoffswitch-switch\"></span>"
"</label>"
"</div>"
"</div>"
"</div>"
" </div>"
"</div>"
"</div>"
"</div>"
"</body>"
"</html>";
return html; // 返回生成的HTML页面
}
代码功能总结
Wi-Fi连接:ESP8266连接到指定的Wi-Fi网络。
Web服务器:创建一个Web服务器,监听HTTP请求。
LED控制:通过Web页面控制LED的开关状态。
蜂鸣器控制:通过Web页面控制蜂鸣器的开关状态。
HTML页面生成:动态生成包含LED和蜂鸣器控制开关的HTML页面。
路由处理:处理根路径、LED切换、蜂鸣器切换以及未找到路径的请求。
通过这段代码,用户可以通过浏览器访问ESP8266的IP地址,控制连接的LED和蜂鸣器。
实验串口返回情况
在手机端打开浏览器,输入IP地址:192.168.28.40
控制LED和蜂鸣器后的实验串口返回情况
实验场景图
实验记录视频(32秒)
【【花雕学编程】Arduino动手做(246)---ESP8266 Web 服务器:从手机控制组件】
评论