💡 划重点

  • 双重感知:MQ-2烟雾传感器 + 火焰传感器同采,防止单点漏报。
  • 本地蜂鸣告警:高分贝蜂鸣器直接警示,不受WiFi断连影响。
  • Server-Sent Events (SSE):ESP32作为HTTP服务器推送实时状态,手机/PC无需刷新即可看到报警信息。
  • 硬件成本严控:总物料开销≤55元,内置状态灯,不需要额外网关。

需求洞察

目标用户:老旧小区厨房、小餐饮后厨、独居老人及厨房临时离人家庭。

真实痛点:厨房火灾多数源于油锅过热起火或燃气泄漏,但很多人炒菜时临时接电话、拿快递而离开灶台,回来时火已窜起。传统烟雾报警器安装在客厅,距离厨房远,且无法区分油烟与火灾烟雾,误报率高,极易被断电丢弃。

为什么值得做:直接用ESP32搭建近火源报警节点,双传感器互相校验:火焰传感器先于烟雾检测到骤亮与红外变化,MQ-2再验证可燃气体或浓烟浓度,只有两者同时触发才鸣响蜂鸣器,大幅降低炒菜油烟误报。同时以SSE推送到家人手机,即便在卧室也能立即得知险情,真正实现“灶台级”防护,用极低成本弥补市场产品短板。

方案设计

感知层

控制层

ESP32主控运行FreeRTOS双任务:采样任务读取两个ADC,进行阈值比较;通信任务维持WiFi连接并运行SSE服务器。当火焰传感器读数超过阈值(例如<1.5V)且MQ-2超过阈值(>2.0V),判定为真实火情,触发报警标志。报警标志自锁,只有通过板载按钮清零或重新上电。

执行层

日志/联网层

ESP32工作在AP+STA或纯STA模式,连接家中路由器。建立一个HTTP服务器,提供/events路由,每次有状态变化(正常→报警)时推送JSON事件。手机浏览器访问ESP32 IP即可看到实时报警页面,无需安装APP。事件格式:data: {"smoke": 2.8, "flame": 0.9, "alarm": true}\n\n。同时可通过串口打印日志,用于调试。

物料清单

名称 数量 用途 估算单价(元)
ESP32-WROOM-32D开发板 1 主控+WiFi 18
MQ-2烟雾传感器模块 1 烟雾/可燃气体检测 8
火焰传感器模块(红外) 1 明火探测 5
有源蜂鸣器模块(5V) 1 报警音 3
红色LED(5mm) + 220Ω电阻 1 状态指示 0.5
NPN三极管S8050 + 1kΩ基极电阻 1 蜂鸣器驱动 0.5
面包板 + 公母杜邦线 1套 免焊接线 10
Micro USB数据线+5V充电头 1 供电 8
合计 53

剩余预算2元可用于外壳或热缩管,满足55元内要求。

接线与结构

使用给定IO完全可行,无需修改。

结构上,传感器模块尽量贴近烟源,可用铜柱固定面包板,阻燃外壳开窗,保证气流与红外穿透。

核心代码

以下给出简化但可编译的PlatformIO骨架,使用Arduino框架。滤除了SSE细部路由以突出重点逻辑,完整代码可在绑定异步TCP库后补充。


#include <Arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>

const int SMOKE_PIN = 34;
const int FLAME_PIN = 35;
const int BUZZER_PIN = 27;
const int LED_PIN = 2;

const float SMOKE_THRESH = 2.0;   // 电压阈值(V)
const float FLAME_THRESH = 1.5;   // 电压低于此表示有火

AsyncWebServer server(80);
AsyncEventSource events("/events");

bool alarmActive = false;
unsigned long lastSample = 0;

void setup() {
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);
  digitalWrite(LED_PIN, LOW);
  Serial.begin(115200);
  
  WiFi.begin("SSID", "PASS");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // 连接中快闪
  }
  digitalWrite(LED_PIN, LOW);
  
  events.onConnect([](AsyncEventSourceClient *client){
    client->send("{\"status\":\"connected\"}",NULL,millis());
  });
  server.addHandler(&events);
  server.begin();
}

void loop() {
  if (millis() - lastSample > 200) {
    lastSample = millis();
    float smokeV = analogRead(SMOKE_PIN) * 3.3 / 4095.0;
    float flameV = analogRead(FLAME_PIN) * 3.3 / 4095.0;
    
    bool fireDetected = (smokeV > SMOKE_THRESH) && (flameV < FLAME_THRESH);
    if (fireDetected && !alarmActive) {
      alarmActive = true;
      String json = "{\"smoke\":" + String(smokeV,2) + 
                    ",\"flame\":" + String(flameV,2) + 
                    ",\"alarm\":true}";
    }
    
    if (alarmActive) {
      digitalWrite(LED_PIN, millis() % 200 < 100 ? HIGH : LOW); // 快闪
    } else {
      digitalWrite(LED_PIN, millis() % 1000 < 500 ? HIGH : LOW); // 慢闪
    }
  }
  delay(1);
}

注:实际部署需将SSID/PASS填入,并安装ESPAsyncWebServer与AsyncTCP库。events.send保证浏览器SSE客户端实时展示报警数据。

调试步骤

  1. 供电检查:用USB线供电,测量面包板上5V与3.3V,确保无短路。MQ-2模块加热灯渐亮至稳定。
  2. ADC零值校准:上电后打开串口监视,观察未点火时烟雾电压常值(通常0.3~1V),火焰传感器电压在3.0V左右。若MQ-2读数高于1.5V,传感器需要预热3分钟。
  3. 模拟报警:用打火机火焰靠近火焰传感器2cm,火焰电压应快速降至1V以下;同时用灭烟产生的烟雾接近MQ-2,烟雾电压升高至2.5V以上。两者同时满足时蜂鸣器必须响,串口打印ALARM TRIGGERED。
  4. SSE连通性:手机连接同一WiFi,浏览器访问http://esp32_ip/,需看到初始连接数据。触发报警时页面应自动更新JSON并变红提示。
  5. 阈值微调:根据实测数据修改SMOKE_THRESH与FLAME_THRESH,保留一定裕度,避免油烟触发烟雾阈值。建议烟雾阈值设为平常值的2.5倍。

设计图

厨房烟雾+火焰双重报警结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报