[i=s] 本帖最后由 WT_0213 于 2025-5-19 11:29 编辑 [/i]
背景
火灾与燃气泄漏的危害主要包括以下几方面:
- 爆炸风险
燃气(如天然气、液化气)泄漏后,若在空气中浓度达到5%-15%,遇明火、静电或微小电火花即可能引发剧烈爆炸。典型案例包括地下管道接头破损导致街头爆燃,以及密闭空间内燃气积聚引发的瞬间闪爆,爆炸冲击波可摧毁建筑物并造成伤亡。
- 火灾蔓延迅速
泄漏燃气即使未达到爆炸极限,遇火源仍会快速燃烧,火势随燃气扩散范围不断扩大,尤其在人员密集场所或通风不良区域更难控制。
- 一氧化碳中毒
燃气不完全燃烧会产生无色无味的一氧化碳,其与血红蛋白结合能力远超氧气,可导致人体缺氧昏迷甚至死亡。此类中毒常见于密闭环境中未及时通风的情况。
- 缺氧性窒息
燃气主要成分为甲烷等气体,大量泄漏会直接降低空气中氧气浓度,引发窒息风险。
面对火灾、燃气泄漏、爆炸等突发灾害,我们可以利用一些简单的传感器例如火焰传感器、MQ-2烟雾传感器和蜂鸣器等等,搭建一套较高可靠性的安全监测系统,让技术为生命筑起第一道防线。
核心组件
1. 火焰传感器
功能:通过红外光谱检测明火(波长760nm~1100nm),响应速度快(毫秒级)。
适用场景:厨房、客厅等明火易发区域。
2. MQ-2烟雾传感器
功能:检测烟雾、液化气、甲烷、丙烷等可燃气体,输出模拟信号(浓度越高电压越高)。
优势:成本低、灵敏度可调,适用于燃气泄漏监测。
3. 蜂鸣器
功能:蜂鸣器(声音报警)
4. 摄像头
功能:可以及时观看当前火势或是否误报
配合推送服务或MQTT协议进行风险提醒或者设备联动。
系统设计与实现步骤
硬件清单
- 火焰传感器 ×1
- MQ-2烟雾传感器 ×1
- BW21-CBV-Kit 开发板 ×1
- 蜂鸣器模块 ×1
- XH2.54段子
- 端子线若干
接线方式

火焰传感器 → BW21-CBV-Kit引脚 20
MQ-2传感器 → BW21-CBV-Kit引脚 A0 /GPIO11
蜂鸣器 → BW21-CBV-Kit引脚 PWM/GPIO8
核心代码示例(Arduino)
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "RTSP.h"
#include "StreamIO.h"
#include "VideoStream.h"
#include "VideoStreamOverlay.h"
RTSP rtsp;
IPAddress ip;
int rtsp_portnum;
StreamIO videoStreamer(1, 1);
VideoSetting config(VIDEO_FHD, 30, VIDEO_H264, 0);
#define CHANNEL 0
// 定义红外模块引脚
const int infraredPin = 20;
// 定义MQ - 2烟雾模块引脚
const int mq2Pin = A0;
// 定义蜂鸣器引脚
const int buzzerPin = 8;
// 定义烟雾传感器阈值
const int smokeThreshold = 500;
char ssid[] = "SSID"; // your network SSID (name)
char pass[] = "PASSWORD"; // your network password
int status = WL_IDLE_STATUS; // Indicator of Wifi status
char mqttServer[] = "192.168.50.19"; // broker.mqttgo.io
char clientId[] = "alerm";
char publishTopicMsg[] = "homeassistant/alermMsg";
char publishTopicImg[] = "homeassistant/alermImg";
char publishPayload[] = "alarm device";
char subscribeTopic[] = "homeassistant/alermMsg";
void callback(char* topic, byte* payload, unsigned int length)
{
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (unsigned int i = 0; i < length; i++) {
Serial.print((char)(payload[i]));
}
Serial.println();
}
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void reconnect()
{
// Loop until we're reconnected
while (!(client.connected())) {
Serial.print("\r\nAttempting MQTT connection...");
// Attempt to connect
if (client.connect(clientId)) {
Serial.println("connected");
// Once connected, publish an announcement and resubscribe
client.publish(publishTopicMsg, publishPayload);
client.subscribe(subscribeTopic);
} else {
Serial.println("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void play()
{
for(int note = 0; note < 3; note++){
// 升调(200Hz→800Hz)
for(int i=600; i<=800; i++) {
tone(buzzerPin, i);
delay(5);
}
// 降调(800Hz→200Hz)
for(int i=800; i>=600; i--) {
tone(buzzerPin, i);
delay(5);
}
}
noTone(buzzerPin);
}
void setup() {
Serial.begin(115200);
// 将红外引脚设置为输入模式
pinMode(infraredPin, INPUT);
// 将蜂鸣器引脚设置为输出模式
// pinMode(buzzerPin, OUTPUT);
// 初始化蜂鸣器为关闭状态
digitalWrite(buzzerPin, LOW);
// wait for serial port to connect.
while (!Serial) {
;
}
// Attempt to connect to WiFi network
while (status != WL_CONNECTED) {
Serial.print("\r\nAttempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
ip = WiFi.localIP();
wifiClient.setNonBlockingMode();
client.setServer(mqttServer, 1883);
client.setCallback(callback);
// Allow Hardware to sort itself out
delay(1500);
if (!(client.connected())) {
reconnect();
}
// config.setBitrate(2 * 1024 * 1024); // Re
Camera.configVideoChannel(CHANNEL, config);
Camera.videoInit();
// Configure RTSP with corresponding video format information
rtsp.configVideo(config);
rtsp.begin();
rtsp_portnum = rtsp.getPort();
// Configure StreamIO object to stream data from video channel to RTSP
videoStreamer.registerInput(Camera.getStream(CHANNEL));
videoStreamer.registerOutput(rtsp);
if (videoStreamer.begin() != 0) {
Serial.println("StreamIO link start failed");
}
Camera.channelBegin(CHANNEL);
Camera.printInfo();
// Start OSD drawing on RTSP video channel
OSD.configVideo(CHANNEL, config);
OSD.begin();
delay(5000);
}
void loop() {
// 读取红外模块状态
int infraredValue = digitalRead(infraredPin);
// 读取MQ - 2烟雾模块模拟值
int mq2Value = analogRead(mq2Pin);
// 打印传感器数值
Serial.print("Infrared: ");
Serial.print(infraredValue);
Serial.print(", Smoke: ");
Serial.println(mq2Value);
JsonDocument doc;
doc["fire"] = infraredValue;
doc["mq2"] = mq2Value;
char json_string[256];
serializeJson(doc, json_string);
Serial.print("Publishing: ");
Serial.println(json_string);
client.publish(publishTopicMsg, json_string);
// 判断是否触发报警条件
if (infraredValue == LOW && mq2Value > smokeThreshold) {
// 触发报警,打开蜂鸣器
// digitalWrite(buzzerPin, HIGH);
Serial.println("Alarm triggered!");
// 短暂延迟,避免频繁读取
play();
delay(4500);
}
// client.loop();
// 短暂延迟,避免频繁读取
delay(500);
}
转JSON使用的是ArduinoJson这个库需要安装。
不同版本写法有些不同,以下是两种不同的写法,可以参考下。
JsonDocument doc;
DynamicJsonDocument doc(1024);
错的话会报错。
HA-MQTT配置
使用docker命令进入HA容器,修改配置文件configuration.yaml,修改前建议备份一下原文件,在configuration.yam文件中增加以下内容,注意以下缩进
sensor:
- name: "BW21/AlermFire"
state_topic: "homeassistant/alermMsg"
suggested_display_precision: 1
unit_of_measurement: ""
value_template: "{{ value_json.fire }}"
- name: "BW21/AlermMQ2"
state_topic: "homeassistant/alermMsg"
suggested_display_precision: 1
unit_of_measurement: "ppm"
value_template: "{{ value_json.mq2 }}"
重载一下YAML配置,如果这里报错说明配置有问题。

如下图表示重新加载成功

在概览种点击编辑,然后点击添加卡片

按实体

选择两个传感器模块继续

添加至仪表盘

点击完成

仪表盘上就可以看到这两个模块的数值了

设备接入HomeAssistant以后很多事情就比较好办了。使用HomeAssistant的自动化功能可以做很多有趣的事情。可以参考之前写的一个帖子。使用MQTT+自动化除配置外无任何代码即可控制任意HomeAssistant内的设备。
[智能家居]MQTT控制HomeAssistant设备
通过自动化做一些联动,比如当MQ-2传感器数值上升时,通过磁控阀门关闭天然气。有条件的自动打开窗通风等等。
关于摄像头
实时监控空间状态,参考了泽哥的帖子,去除了模型部分,保留了RTSP视频流,感觉延迟有点高。不过如果观察火情隐患的话不是很影响。
【智能家居】BW21-CBV-Kit接入HomeAssistant实时查看Ai摄像头画面
在HomeAssistant中查看当前空间是否有险情。
外壳3D图
外壳用的是FreeCAD画的,画的比较一般,菜鸟一个各位大牛将就看。

MQ-2传感器,做了小窗,方便气体流入。感觉进气量会受一些影响。
火焰传感器挖了孔,做了锥形。
蜂鸣器,找了半天找到个POS机拆了个,无源蜂鸣器,形状有点对不上就直接接线了。

侧面留了一个typeC的母口孔。

用的这种母座,V和5V(MQ-2VCC+火焰VCC)并联,G和GND并联,数据空着了。

后视图

后盖

外壳量的有些误差,导致有些孔位对不上,又加工了一下。
附件:fire.zip
外壳的模型文件,部分需要微调。
实物图
正视图,3D打印机打印出来效果差一点。悬空加支撑部分不够平整,圈圈也都变形了。

内部结构,感觉这种端子线用起来还挺舒服的。也不用焊接。(压线钳+端子)一压就OK还蛮牢固的。

侧视图,供电用的Typec

目前没留调试口,本来想着用蓝牙配网后来看了下代码,没看明白最终WIFI账号密码保存到哪里了。索性直接写到代码里面直接烧录。
感觉视频流畅度不如AiPi-Cam-D200,后面换成AiPi-Cam-D200再做一版。应该还会小一些。
用开发板做出来的东西大小,样子自己无法控制,想要做好产品还需要努力呀。
系统的学习一下还是很有必要的。
优化与扩展
- 双重验证机制
- 火焰与烟雾传感器同时触发时再报警,减少误报(如蜡烛火焰干扰)。
- 远程通知功能
- 联动灭火设备
- 接入继电器模块,触发自动灭火装置(如家电磁阀喷水系统)。
安全提醒
- 定期校准传感器:MQ-2需预热1分钟后使用,每月测试一次灵敏度。
- 避免高温高湿环境:传感器长期暴露可能影响寿命。
- 紧急逃生预案:报警触发后,优先撤离并联系消防部门。
科技的温度,在于将“无情”的灾害转化为“可控”的风险。通过简单的电子元件与开源硬件,为家庭安全添一份保障。
视频