1. 从零搭建烟雾报警系统

第一次接触MQ-2烟雾传感器时,我完全被这个小玩意儿的灵敏度震惊了。记得当时在厨房测试,刚打开燃气灶不到3秒,传感器的数值就蹭蹭往上涨。这种实时响应能力,正是智能家居安防系统最需要的特性。

ESP32作为主控芯片的优势很明显:双核处理器能同时处理传感器数据和网络通信,内置Wi-Fi/蓝牙模块省去了外接模块的麻烦,最关键的是它对OpenHarmony的支持越来越完善。我实测过,用ESP32跑OpenHarmony的标准外设驱动,稳定性完全不输专业开发板。

OpenHarmony的分布式能力是这个项目的灵魂所在。传统方案需要在ESP32上写死所有联动逻辑,而我们现在可以通过分布式软总线,让手机、智能插座、窗帘控制器等设备自动发现彼此。举个例子,当MQ-2检测到异常时,ESP32只需要发布一个"smoke_alert"事件,其他设备订阅这个事件后就会自主响应。

2. 硬件连接与驱动适配

先说说MQ-2传感器的接线要点。虽然模块支持数字和模拟输出,但我强烈建议使用模拟输出接ESP32的ADC引脚(比如GPIO34)。原因很简单:数字输出只能设置固定阈值,而模拟信号能让我们更灵活地定义不同浓度级别的预警策略。

这是我常用的接线方案:

  • VCC接5V(注意不是3.3V)
  • GND接地
  • AO接ESP32的ADC引脚
  • DO悬空(不使用数字输出)

在OpenHarmony的驱动层,需要重点关注HDF框架的ADC驱动适配。这里有个坑我踩过:ESP32的ADC2通道与Wi-Fi共用硬件资源,所以最好选择ADC1的通道(GPIO32-39)。下面是我修改过的BUILD.gn配置片段:

include_dirs = [
    "//drivers/hdf_core/framework/include/platform/",
    "//device/soc/esp/esp32/components/driver/include",
    "//device/soc/esp/esp32/components/esp_adc_cal/include"
]

3. 烟雾检测算法优化

直接使用ADC原始值判断烟雾浓度会有一个大问题:环境温湿度会影响传感器基线值。我的解决方案是采用动态基线校准——在系统启动时连续采样30秒取平均值作为基准,后续检测时用当前值减去基准值。

这里分享一个实用的阈值设置经验:

  • 基准值+50~100:轻微烟雾,触发通风
  • 基准值+200~300:明显烟雾,切断电源
  • 基准值+500以上:紧急状况,推送警报

对应的代码逻辑可以这样实现:

int current_value = adc_read();
int delta = current_value - baseline;
if(delta > 500) {
    event = EMERGENCY_ALERT;
} else if(delta > 200) {
    event = POWER_OFF;
} else if(delta > 50) {
    event = VENTILATION;
}

4. 分布式事件联动实战

OpenHarmony的分布式能力在这个环节大放异彩。我们不需要关心具体设备在哪,只要定义好统一的事件ID,所有设备都能通过分布式事件总线协同工作。

首先在config.json中声明事件类型:

"events": [
    {
        "name": "smoke_level_change",
        "value": 1,
        "type": "int"
    }
]

然后在ESP32端发布事件:

OH_EventData eventData = {
    .data = &smoke_level,
    .dataLen = sizeof(int)
};
OH_EventPublish("smoke_level_change", &eventData);

其他设备订阅事件的代码更简单:

OH_EventSubscribe("smoke_level_change", eventHandler);

实测中我发现一个性能优化点:事件广播最好设置QoS等级。对于烟雾警报这种关键信息,应该用最高优先级:

OH_EventPublishOpts options = {
    .qos = OH_QOS_HIGH
};

5. 多设备联动策略

当烟雾浓度达到不同阈值时,系统应该执行阶梯式响应。这是我的联动方案:

  1. 初级响应(50<delta<200)

    • 开启智能窗帘(通过HTTP API控制)
    • 启动排风扇(通过MQTT协议控制)
  2. 中级响应(200<delta<500)

    • 切断智能插座电源
    • 发送APP推送通知
    • 本地蜂鸣器报警
  3. 紧急响应(delta>500)

    • 拨打预设紧急电话
    • 激活全屋警报系统
    • 向物业管理系统发送告警

每个动作我都设置了互斥锁,避免重复触发。比如切断电源后,即使浓度继续升高也不会重复操作,除非浓度先下降到安全值再回升。

6. 功耗优化技巧

虽然MQ-2工作电流有150mA,但通过合理的采样间隔设置,整体功耗可以大幅降低。我的方案是:

  • 正常状态:每10秒采样一次
  • 预警状态:每秒采样一次
  • 警报状态:持续采样

对应的ESP32电源管理代码:

// 进入低功耗模式
esp_sleep_enable_timer_wakeup(10 * 1000000);
esp_deep_sleep_start();

实测下来,两节18650电池可以维持系统工作3个月以上。如果接入市电,建议给传感器单独增加一个MOSFET开关电路,需要采样时才通电。

7. 抗干扰设计心得

厨房环境有很多干扰源:油烟、水蒸气、电磁炉辐射等。这些都会导致误报警,我总结了几个有效的滤波方法:

  1. 硬件滤波

    • 在传感器输出端加104电容
    • 使用屏蔽线连接ADC
  2. 软件滤波

    • 滑动窗口平均算法(我常用窗口大小=5)
    • 中值滤波排除突发干扰
    • 持续3次超阈值才触发警报
  3. 环境补偿

    • 增加温湿度传感器数据作为修正系数
    • 根据历史数据自动调整基准值

这套组合拳用下来,误报率能从最初的30%降到不足1%。

8. 移动端告警实现

OpenHarmony的跨设备调用功能让手机端开发变得异常简单。不需要自己搭建推送服务器,直接用分布式能力就能实现实时告警。

在手机APP端主要做三件事:

  1. 注册烟雾事件监听
  2. 显示实时浓度曲线
  3. 提供应急处理按钮

关键代码片段:

// 订阅事件
EventSubscribeInfo subscribeInfo = new EventSubscribeInfo.Builder()
    .setEventName("smoke_level_change")
    .build();
EventManager.subscribe(subscribeInfo, event -> {
    int level = event.getIntValue();
    updateUI(level);
});

我特别加了个实用功能:当用户点击"误报"按钮时,系统会自动学习当前环境值,动态调整基准线。这个设计让系统越用越准。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐