基于 ESP32-S3 开发板和 Arduino 框架,结合 ESPAsyncWebServer 实现一个本地环境采集与控制系统,包含温湿度、烟感、光照监测,以及蜂鸣器、WS2812 LED 联动控制,设计符合现代 UI 交互的 Web 界面。
PC端界面:

硬件架构与手机端界面:

一、需求分析
1.1 核心需求
本项目旨在基于 ESP32-S3 开发一款低成本、可视化、可交互的室内环境监测系统,满足以下核心诉求:
-
多维度环境感知:实时采集温度、湿度、烟雾浓度、光照强度四类核心环境数据;
-
智能联动控制:烟雾浓度超标时自动触发蜂鸣器报警,光照强度异常时自动控制 WS2812 LED 灯色变化;
-
远程可视化交互:通过 WiFi 构建 Web 服务,提供手机 / 电脑端可视化界面,支持阈值配置、自动联动开关等交互操作;
-
实时数据同步:采用 WebSocket 实现前端与设备的双向实时通信,配置修改即时生效,数据更新无延迟;
-
移动端适配:优化界面布局,确保手机端一屏完整显示所有监测卡片,提升易用性。
1.2 非功能性需求
-
稳定性:传感器数据采集频率 1Hz,连续运行无数据丢失;
-
易用性:Web 界面操作直观,阈值调节、开关控制无需专业知识;
-
兼容性:支持主流浏览器(Chrome、Edge、Safari),适配手机 / 平板 / 电脑等终端;
-
可扩展性:代码模块化设计,便于后续新增传感器或功能。
二、功能分析
2.1 核心功能模块
|----------|----------------------------------------------------|
| 模块名称 | 功能描述 |
| 传感器数据采集 | 采集 DHT11 温湿度、MQ2 烟雾 ADC 值、BH1750 光照强度(lux),做异常值过滤 |
| 智能联动控制 | 1. 烟雾浓度超阈值 → PWM 间歇控制蜂鸣器报警;2. 光照强度联动 WS2812 LED 灯色 |
| Web 服务 | 提供 HTTP 服务,加载自定义可视化界面;WebSocket 实现双向实时通信 |
| 前端交互 | 1. 实时显示传感器数据;2. 调节烟雾 / 光照阈值;3. 开关自动联动功能;4. 状态可视化提示 |
| 数据通信 | JSON 序列化传感器 / 配置数据,WebSocket 广播同步至所有客户端 |
2.2 功能流程

三、核心实现
3.1 硬件层实现
3.1.1 硬件配置
|------------|---------------|------------------------------------|
| 硬件模块 | 引脚定义 | 功能说明 |
| DHT11 温湿度 | 13 | 模拟 / 数字混合传感器,采集温度(°C)、湿度(%) |
| MQ2 烟雾传感器 | 7 | 模拟输入,输出 0-4095 ADC 值表征烟雾浓度 |
| 无源蜂鸣器 | 20(PWM 通道 0) | 4500Hz 频率、80 占空比,间歇报警(500ms 响 / 停) |
| BH1750 光照 | SCL=39/SDA=40 | I2C 通信,输出 lux 级光照强度 |
| WS2812 LED | 48 | 单灯珠,根据光照强度显示蓝 / 绿 / 黄三色 |
3.1.2 硬件初始化(initHardware())
- 初始化 DHT11、BH1750(I2C 总线)、WS2812 LED(初始关灯);
- 配置 MQ2 引脚为输入模式,蜂鸣器 PWM 初始化(频率 4500Hz、8 位分辨率);
- 异常处理:无(传感器初始化失败会导致后续数据为 0,串口可观测)。
3.2 数据采集层实现
3.2.1 数据结构设计
// 传感器数据结构体:存储核心感知数据
struct SensorData {
float temperature; // 温度 (°C)
float humidity; // 湿度 (%)
int mq2Value; // 烟感模拟值
float lightValue; // 光照值 (lux)
unsigned long updateTime; // 最后更新时间
};
// 报警配置结构体:存储可配置参数
struct AlarmConfig {
int mq2Threshold; // 烟感报警阈值(默认800)
bool mq2AutoAlarm; // 烟感自动报警开关(默认开启)
bool mq2AlarmState; // 烟感报警状态(是否超阈值)
int lightLowThreshold; // 光照低阈值(100lux,蓝灯)
int lightHighThreshold; // 光照高阈值(500lux,黄灯)
bool lightAutoMode; // 光照自动联动开关(默认开启)
};
3.2.2 数据采集逻辑(updateSensorData())
- 温湿度采集 :调用
dht.readTemperature()/dht.readHumidity(),过滤nan异常值(置 0); - 烟雾采集 :
analogRead(MQ2_PIN)读取 12 位 ADC 值(0-4095); - 光照采集 :
lightMeter.readLightLevel()读取 lux 值,过滤nan异常值; - 报警状态更新 :对比 MQ2 ADC 值与阈值,更新
mq2AlarmState(仅表征是否超阈值,与蜂鸣器解耦)。
3.3 智能控制层实现
3.3.1 烟雾报警逻辑(handleMQ2Alarm())
- 核心逻辑:仅当「自动报警开关开启」且「烟雾超阈值」时触发报警;
- 报警方式:PWM 间歇控制(
millis() % 1000 < 500),蜂鸣器 500ms 响、500ms 停,避免持续噪音; - 边界处理:自动报警关闭时,强制关闭蜂鸣器,防止误报警。
3.3.2 光照 LED 联动(handleLightLED())
- 核心逻辑:仅当「自动联动开关开启」时生效,否则关闭 LED;
- 灯色规则:
- 光照 < 100lux → 蓝色(环境光弱);
- 100lux ≤ 光照 ≤ 500lux → 绿色(正常);
- 光照 > 500lux → 黄色(环境光强);
- 亮度控制:固定 50% 亮度(
strip.setBrightness(128)),避免刺眼。
3.4 通信层实现
3.4.1 JSON 数据序列化(getSensorJson())
- 使用
StaticJsonDocument<256>轻量化序列化,包含:
- 传感器数据:温度、湿度、MQ2 ADC、光照强度;
- 配置数据:烟雾阈值、自动报警开关、光照高低阈值、自动联动开关;
- 状态数据:烟雾报警状态;
- 优势:结构化数据,前端解析便捷,传输体积小。
3.4.2 WebSocket 通信(onWsEvent())
- 双向通信逻辑:
- 设备 → 前端:每秒广播一次序列化后的传感器 / 配置数据;
- 前端 → 设备:接收前端修改的配置(阈值、开关),更新本地
alarmConfig,立即调用handleMQ2Alarm()/handleLightLED()应用配置; - 异常处理:JSON 解析失败时打印错误日志,不影响系统运行。
3.5 Web 服务层实现
3.5.1 服务器初始化
- 异步 Web 服务器:
AsyncWebServer server(80),非阻塞式处理 HTTP 请求,避免影响传感器采集; - WebSocket 挂载:
server.addHandler(&ws),绑定/ws路径用于实时通信; - 静态页面路由:根路径
/返回内嵌的 HTML 界面,无需外置文件系统。
3.5.2 前端界面核心设计
- 布局优化:
- 栅格布局(
grid-template-columns),适配多终端; - 手机端(<480px)单列显示,卡片内边距 / 字体精简,一屏完整显示 3 个卡片;
- 交互组件:
- 滑块(
input[type="range"]):调节烟雾 / 光照阈值,实时显示当前值; - 开关(自定义 slider):控制自动报警 / LED 联动;
- 状态徽章:不同颜色 + 文字提示当前状态(正常 / 报警 / 光线弱 / 强);
- 实时更新 :WebSocket 监听
onmessage事件,接收数据后更新 DOM,状态徽章动态切换样式。
3.6 主循环逻辑
- 定时采集:
millis()实现 1 秒定时,避免delay()阻塞; - 流程顺序:采集数据 → 执行联动控制 → 广播数据 → 串口调试输出;
- 资源清理:
ws.cleanupClients()清理闲置 WebSocket 客户端,释放内存。
四、编程流程
4.1 整体编程流程
预处理阶段:引入依赖库,定义硬件引脚/参数,声明全局对象/结构体;
工具函数定义:硬件初始化、数据采集、联动控制、数据序列化、WebSocket 事件处理;
前端界面定义:内嵌 HTML/CSS/JS,实现可视化与交互;
setup() 函数: - 串口初始化 → 硬件初始化 → WiFi 连接 → Web 服务器/WebSocket 启动;
loop() 函数: - 每秒执行:数据采集 → 联动控制 → 数据广播 → 串口输出; - 持续清理闲置 WebSocket 客户端,保证稳定性。
4.2 核心亮点
- 定时采集使用
millis()而非delay(),确保系统响应性。
4.2.3 解耦设计
- 报警状态与执行逻辑解耦:
mq2AlarmState仅表征是否超阈值,handleMQ2Alarm()负责执行报警,便于扩展多方式报警; - 前端与设备解耦:通过 JSON 标准化数据交互,前端修改不影响设备核心逻辑。
4.2.4 移动端适配
- 响应式布局:媒体查询(
@media (max-width: 480px))适配手机端; - 卡片高度优化:精简内边距 / 字体 / 间距,确保手机一屏显示所有内容。
五、代码与使用
5.1 完整代码
代码仓库:https://gitee.com/vopo123/esp32-dev-kit
5.2 使用说明
1. 硬件接线(ESP32-S3)
|------------|-----------------|--------------|
| 模块 | ESP32-S3 引脚 | 备注 |
| DHT11 数据 | 13 | 需接上拉电阻(4.7K) |
| MQ2 模拟输出 | 7 | 模拟输入,无需额外电阻 |
| 无源蜂鸣器 | 20 | 需串 220Ω 限流电阻 |
| BH1750 SCL | 39 | I2C 时钟线 |
| BH1750 SDA | 40 | I2C 数据线 |
| WS2812 数据 | 48 | 需接 5V 供电 |
2. 环境准备
- 安装所需库(Arduino 库管理器中搜索):
ESPAsyncWebServer(需手动安装:https://github.com/me-no-dev/ESPAsyncWebServer)AsyncTCP(ESP32 内置,ESP8266 需手动安装)DHT sensor library(Adafruit 版本)Adafruit NeoPixelBH1750ArduinoJson(v7 版本)
- 修改代码中
ssid和password为你的 WiFi 名称 / 密码; - 选择开发板:
Tools → Board → ESP32 Arduino → ESP32-S3 Dev Module。
3. 功能操作
- 上传代码后,打开串口监视器,查看 ESP32-S3 分配的 IP 地址;
- 在浏览器中输入该 IP 地址,即可进入 Web 界面;
- 界面操作:
- 烟感阈值:拖动滑块设置报警值,开启 "自动报警" 后,超过阈值蜂鸣器间歇报警;
- 光照阈值:设置低 / 高阈值,开启 "LED 自动联动" 后,WS2812 自动按光照强度变蓝 / 绿 / 黄;
- 所有配置实时生效,无需重启开发板。