💡 划重点
- 本项目以 ESP32 为主控,结合 MQ-2 烟雾传感器与火焰传感器,构建一套面向厨房环境的双重报警终端。核心亮点在于利用 ESP32 原生 Wi-Fi 能力,通过 Server-Sent Events(SSE)将报警状态实时推送至手机或 PC,无需额外购买显示屏。系统在检测到烟雾浓度超标或火焰红外特征后,立即驱动有源蜂鸣器与状态指示 LED,并在 5 秒内
需求洞察
目标用户是家中常开火做饭的中青年群体,以及有老人独自在家做饭的家庭照料者。真实痛点是厨房存在“看不见的风险”:燃气小火被风吹灭、油炸冒烟过久、油锅瞬间起火,而这类隐患往往在几十秒内升级。传统烟雾报警器仅能感知颗粒物,无法识别明火;商用厨房报警主机则造价数千元,且需专业布线。值得做这件事的理由有四点:其一,ESP32 与 MQ-2 成本极低,一次采购不足 55 元;其二,火焰传感器利用红外频段探测明火,响应时间小于 1 秒,比烟雾扩散更快;其三,SSE 方案让用户不必装 App,打开浏览器即可看到实时状态;其四,本项目既可以作为智能家居中控的一个节点,也能独立运行,具备实用与教育双重价值。
方案设计
- 感知层:MQ-2 烟雾传感器(模拟量输出 A0)负责检测空气中可燃气体与烟雾浓度,其内部加热电阻保证对油烟与燃气有较高灵敏度;火焰传感器(数字量 DO 输出)内置 5mm 红外接收管,对准炉灶方向可识别 760nm-1100nm 火焰光谱。两者形成“先呛后火”“先火后烟”的互补逻辑。
- 控制层:ESP32 核心承担数据采集、阈值判断与状态机切换。程序采用主循环轮询方式,每 200ms 读取一次模拟量与数字量,经滑动滤波后与预设阈值比较。逻辑分三档:无异常(绿灯慢闪)、烟雾报警或火焰报警(红灯快闪 + 蜂鸣器间歇鸣叫)、双重报警(红灯常亮 + 蜂鸣器连续鸣叫)。
- 执行层:有源蜂鸣器(低电平触发)串接 NPN 三极管或直接由 GPIO 驱动,用于声报警;一颗 5mm 共阳 RGB LED 作为状态指示,常见故障(传感器掉线、Wi-Fi 断连)以黄灯进行区分。
- 日志/联网层:ESP32 开启 SoftAP 或连接家中路由器。通过 WiFiServer 实现轻量级 SSE,即浏览器向 /events 发起长连接,服务器在检测到状态变化时向所有客户端推送
event: alert\ndata: {"smoke":xx,"fire":xx}。同时使用 Preferences 库将最近 20 条事件时间戳写入 NVS,功耗与延迟均优于 HTTP 轮询。
物料清单
| 物料名称 | 数量 | 用途 | 估算单价(元) |
|---|---|---|---|
| ESP32 DevKitC V4 (Wi-Fi/BLE) | 1 | 主控/联网 | 16.00 |
| MQ-2 烟雾传感器模块 | 1 | 烟雾/可燃气体检测 | 8.00 |
| 火焰传感器模块(红外/数字量) | 1 | 明火探测 | 3.50 |
| 有源蜂鸣器(5V 低电平) | 1 | 声音报警 | 1.00 |
| 5mm 共阳 RGB LED | 1 | 状态指示 | 0.50 |
| 面包板 + 杜邦线若干 | 1 | 免焊连接 | 5.00 |
| 5V/1A USB 电源 | 1 | 供电 | 约 10.00(若有旧充电器可省) |
| 收纳盒/杜邦针座 | 若干 | 结构固定 | 2.00 |
| 合计 | - | - | 46.00(不含电源则 36.00) |
接线与结构
使用 Arduino 默认引脚定义,所有模块共地与 3.3V/5V 供电:
| ESP32 引脚 | 外设 | 说明 |
|---|---|---|
| GPIO 34(ADC1) | MQ-2 A0(模拟输出) | 仅输入模式,连接 10k 上拉至 3.3V 可选 |
| GPIO 35 | 火焰传感器 DO | 配 10k 下拉至 GND,数字量输入 |
| GPIO 27 | 蜂鸣器正极 | 负极接 GND,若使用 5V 蜂鸣器需三极管驱动 |
| GPIO 2 | RGB LED 的 G(或三色共阳控制端) | 板上自带蓝色 LED,可作为状态灯替代 |
| GND | 所有模块负极 | 共地,避免信号光耦浮动 |
| EN | 复位按键 | 长按 3s 重连 Wi-Fi |
说明:原建议 GPIO 2 为状态灯,但该引脚同时连接板载蓝色 LED,方便调试,故方案中直接复用板载 LED,可减少接线。若需红绿双色指示,则 GPIO 2 仍为板载灯,额外用 GPIO 4 与 GPIO 16 连接外接 LED。火焰传感器 DO 输出为数字信号(有火为高或低取决于模块),本方案假定“检测到火焰输出高电平”,若模块为低有效则代码内反转。
核心代码
以下为 PlatformIO + Arduino 框架的可编译骨架,仅保留核心双判据与 SSE 推送逻辑。完整工程含分区表。
#include <WiFi.h>
#include <Preferences.h>
#define SMOKE_PIN 34
#define FIRE_PIN 35
#define BUZZER_PIN 27
#define LED_PIN 2
#define ADC_THRESHOLD 1800 // 根据 MQ-2 上电稳定后 ADC 值调整(12位分辨率,0-4095)
#define POLL_INTERVAL 200
const char* ssid = "你的WiFi";
const char* password = "你的密码";
WiFiServer server(80);
Preferences prefs;
unsigned long lastPoll = 0;
bool lastAlert = false;
char msgBuffer[128];
void pushEvent(const char* jsonData) {
// SSE 简单广播:遍历所有连接的 WiFiClient
for (int i = 0; i < 10; i++) {
WiFiClient client = server.available();
if (client && client.connected()) {
client.println("id: " + String((uint32_t)esp_random()));
client.printf("data: %s\n\n", jsonData);
}
}
}
void setup() {
pinMode(SMOKE_PIN, INPUT);
pinMode(FIRE_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
Serial.begin(115200);
WiFi.begin(ssid, password);
prefs.begin("kitchen", false);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
server.begin();
// 配置 MQ-2 通电预热倒计时
for (int i = 30; i >= 0; i--) {
delay(1000);
}
}
void loop() {
if (millis() - lastPoll >= POLL_INTERVAL) {
lastPoll = millis();
int smokeValue = analogRead(SMOKE_PIN);
bool fireState = digitalRead(FIRE_PIN);
bool smokeAlert = (smokeValue > ADC_THRESHOLD);
bool fireAlert = fireState; // 若模块低电平表示有火则改为 !fireState
bool alertNow = smokeAlert || fireAlert;
// 蜂鸣器与LED动作
if (alertNow) {
if (smokeAlert && fireAlert) tone(BUZZER_PIN, 2000); // 双报警:连续声
else { for (int j=0;j<3;j++) { tone(BUZZER_PIN, 1000); delay(100); noTone(BUZZER_PIN); delay(100); } }
digitalWrite(LED_PIN, HIGH);
} else {
noTone(BUZZER_PIN);
// LED 慢闪表示正常
digitalWrite(LED_PIN, HIGH);
delay(50);
digitalWrite(LED_PIN, LOW);
}
// 状态变化时记录日志并通过 SSE 推送
if (alertNow != lastAlert) {
"{\"smoke\":%d,\"fire\":%d,\"smokeVal\":%d}",
pushEvent(msgBuffer);
lastAlert = alertNow;
}
}
}
代码中实现了四个核心行为:MQ-2 模拟量 ADC 阈值判断、火焰数字量读取、基于 millis 的非阻塞轮询(避免 delay 卡死网络)、SSE 广播函数。首次启用时需在串口监视器观察 MQ-2 上电 60 秒后的稳定 ADC,将其作为正常基准值。
调试步骤
- 上电自检:将代码烧录后打开串口监视器,观察 MQ-2 的 ADC 读数。预热前数值应在 200-500 之间,预热后油烟喷向传感器会快速上升至 3000+,松手后逐渐回落。若数值始终为 4095,检查 3.3V 与模块供电是否正常。
- 火焰功能验证:用打火机(不打火)靠近火焰传感器 30cm 内,确认 DO 引脚电平反转。若用手机闪光灯照射无反应,说明该模块滤光片要求红外频段,需改用蜡烛或打火机放气状态的火苗。
- 报警联动测试:先屏蔽火焰检测,仅保留烟雾阈值。将 MQ-2 靠近热水壶蒸汽喷口,模拟阈值触发。观察蜂鸣器是否发出有节奏的间歇声,板载 LED 亮起。此时浏览器输入 ESP32 IP(串口打印地址),访问 http://ip/events,应能看到实时 SSE 数据流。
- 阈值微调:若烹饪时正常炒菜也误报,将 ADC_THRESHOLD 从 1800 提高到 2500。灵敏度过高靠上电后串口读线性设置,建议做成 Web 配置页面(代码中预留 http 处理,可自行扩展)。
- 无线稳定性验证:将路由器与 ESP32 的距离拉远至 8 米隔一堵墙,观察 SSE 连接是否有间断现象。若间断,在 setup 中启用 WiFi.setSleep(false)。
- 异常排查:若火焰传感器与 MQ-2 同时模块灯亮但主控无反应,用万用表二极管档测 ESP32 3.3V 输出能力,蜂鸣器工作电流超过 20mA 时需换用低功耗型号或改用三极管驱动。
设计图
厨房烟雾+火焰双重报警结构flow
1
感知输入
→
2
控制处理
→
3
执行反馈
→
4
数据上报