一、所选任务介绍
此次我选择的是方向一:智能家居中的家庭安全与异常行为智能监测。应用场景是灶台存在热源,但无人值守时的感知预警和远程处理。
二、项目介绍
基于xiao ESP32S3 SENSE微控制器构建,集成了温度检测、人员活动感知、远程控制、本地人机交互及自动报警等多种功能。采用模块化设计思想,结合FreeRTOS多任务处理与中断响应机制,实现了高实时性与可靠性的智能监控能力。
系统通过红外温度传感器监测燃气灶表面温度,利用微波雷达检测人员活动状态,当检测到高温且长时间无人值守时,自动触发蜂鸣器报警并通过MQTT协议向远程服务器发送警报信息。远程端可通过MQTT查看现场状态并进行必要的处理。
三、 所有使用到的硬件介绍
本次任务除了使用了在贸泽电子上购买的xiao ESP32S3 SENSE作为主控之外,主要借助了之前在电子森林上参加活动的人工智能硬件实验套件平台中的底板和一些传感器,具体如下:
1. ESP32-S3 Sense
基于 ESP32-S3 芯片,双核、高算力,支持 Wi‑Fi / BLE。自带摄像头接口、麦克风模块。在项目中用来作为主控,并通过自带摄像头捕获现场照片,通过WIFI及MQTT服务实现远程数据传输与控制。

2. 5.8G雷达感应模块
人体移动传感器,项目中通过GPIO读取输出引脚高低电平来确定是否有人。

3. 远距离数字红外热电堆传感器
可远距离读取目标温度,在项目中通过I2C接口获取目标温度,从而确定是否进入预警检测。

4. 旋转电位器
可通过改变旋转角度可改变电阻值,这里用来实现获取灶台开关位置状态。

5. 无源蜂鸣器
可通过改变频率发出不同音调,不能通过简单的高低电平控制。在项目中用来进行播放报警提示音。

6. ADC 按键
多个按键共用一个 ADC 输入引脚,通过不同分压电阻产生不同电压。在项目中用来通过ADC来读取按键的电压值,区分不同的按键输入,实现参数变更及取消报警灯功能。

7. OLED 屏幕
0.96寸OLED屏幕,使用SSD1306驱动使用I2C接口。在项目中用来显示交互信息。

8. SG90 180 度伺服电机
可根据PWM波形来改变输出角度,在项目中用来实现开闭燃气灶阀门。

9. 转接底板
转接地板提供了各个传感器模块与主控之间的连接接口,可以方便的进行连接和调换。

10.硬件全貌

四、方案框图和项目设计思路介绍
1. 通过红外线测温传感器远距离感知灶台温度,当温度高于限定值则通过雷达检测人员值守状态,超时则进行报警和远程通知。
2. 本地可通过ADC按键实现4个功能,这里主要是用来调整无人值守时长间隔参数,可取消报警,并可立即获取温度传感器温度,进行简单测温。
3. 远程可通过MQTT特定指令实现获取现场实时图片,获取现场参数(包括温度、灶台开关状态、是否),操作灶台关闭,和调整参数。
硬件框图如下:

五、软件流程图及关键代码介绍
开发环境使用Arduino IDE。根据检测需要初始化串口、I2C、OLED、温度传感器、WIFI、MQTT及ADC按键队列任务等,根据时间阈值等触发条件进行循环检测从而触发本地报警,远程通过MQTT发送特定指令实现特定功能。
1.模块与功能对应:
模块名称 | 类型 | 引脚/接口 | 功能描述 |
TRS55D 红外温度传感器 | 传感器 | I2C (SDA:5, SCL:6) | 测量物体表面温度,判断是否点火 |
微波雷达模块 | 传感器 | GPIO3(RADA_PIN) | 检测人员活动,上升沿触发中断 |
蜂鸣器(Buzzer) | 执行器 | GPIO9(BUZZER_PIN) | 发出警报音,支持多音符旋律播放 |
SG90舵机(Servo) | 执行器 | GPIO8(servoPin) | 控制燃气阀门开关角度(0°关,180°开) |
OLED显示屏(SSD1306) | 显示设备 | I2C (默认) | 实时显示温度、检测间隔、开关状态 |
摄像头模块 | 图像采集 | 未知(通过camerahandle.h封装) | 拍照并上传JPEG图像至MQTT服务器 |
ADC按键模块 | 输入设备 | 未知(通过adc_key.h封装) | 模拟按键输入,通过ADC读取电压区分键值 |
ADC旋钮模块 | 传感器 | 未知(通过adc_positon.h封装) | 检测燃气灶旋钮旋转角度,映射为0~359° |
2.MQTT命令说明:
本地微控制器根据订阅主题的相关指令进行相关操作,具体如下:
指令关键词 | 参数格式 | 功能描述 | 备注 |
FIRE_ON | 无 | 开启模拟火源 | 舵机转动至 180° |
FIRE_OFF | 无 | 关闭模拟火源 | 舵机转动至 0° |
TAKE_PHOTO | 无 | 触发拍照 | 设置拍照标志位,系统随后上传 JPEG |
SET_TIME:<数值> | 1 ~ 29 | 设置检测间隔 | 单位:分钟。例如 SET_TIME:5 |
GET_PARAMETER | 无 | 查询系统状态 | 触发系统上报当前参数 |
CANCEL_ALARM | 无 | 手动消音 | 停止蜂鸣器报警,重置播放标志位 |
3.远程通过收到的不同数据头来分别解析数据:
序号 | 类型 | 标识头 | 触发方式 | 数据格式 |
1 | 参数状态数据 | PARAMETER | 收到 GET_PARAMETER 指令后主动上报 | 文本字符串 |
2 | 警报数据 | ALARM | 当 over_temp 为真且超过设定时间未检测到人时自动触发 | 文本字符串 |
3 | 图像数据 | 0xFF, 0xD8 | 收到 TAKE_PHOTO 指令后发送 | 二进制流 |
4.软件流程图如下:

5.中断驱动的人员检测
雷达模块连接至GPIO3,配置为上拉输入。在上升沿触发中断处理函数handleInterrupt(),记录lastDetectTime = micros()。主循环通过比较当前时间与最后检测时间判断是否超时。
if(over_temp){
unsigned long now = millis();
if((now - lastDetectTime/1000)> para_time_min*60*1000){//超过设定时间未检测到人
startAlarmSound();//开始报警
if(millis()-last_mqtt_alarm>30000){//每30秒再次通过MQTT报警
client.publish(PUBTOPIC,"ALARM");
last_mqtt_alarm = millis();
}
}
}
6.队列驱动的按键通信
adcKeyTask任务读取ADC按键,识别后向keyEventQueue发送键ID。loop()中通过xQueueReceive()接收按键事件,执行对应操作:KEY0立即获取温度值,KEY1取消报警,KEY2增加检测时间,KEY3减少检测时间。
if (xQueueReceive(keyEventQueue, &key_id, 0) == pdTRUE) {
Serial.printf("Key %d pressed!\n", key_id);
switch(key_id){
case 0:
btn_check_now = true;//立即检查温度
break;
case 1:
if(isPlaying){
isPlaying = false;
noTone(BUZZER_PIN);
}
break;
case 2:
para_time_min++;
if(para_time_min>=30){
para_time_min = 30;
}
break;
case 3:
para_time_min--;
if(para_time_min<=1){
para_time_min = 1;
}
break;
}
}
7.非阻塞式蜂鸣器播放
使用tone()和noTone()实现音符播放。updateBuzzer()在loop()中被周期调用,根据当前音符索引和持续时间自动切换音符,支持暂停和呼吸间隙(末尾50ms静音)。
void updateBuzzer() {
if (!isPlaying) return;
unsigned long now = millis();
int freq = alarmMelody[currentNote];
int duration = alarmMelody[currentNote + 1];
if (now - noteStartTime >= duration) {
currentNote += 2; // 跳到下一个音符(频率+时长一对)
if (currentNote >= MELODY_LENGTH) {
currentNote = 0;
}
noteStartTime = now;
freq = alarmMelody[currentNote];
if (freq == 0) {
noTone(BUZZER_PIN); // 静音
} else {
tone(BUZZER_PIN, freq);
}
}
}
六、 功能展示图及说明
设备启动后会自动联网并将获取到的阀门状态、目标温度、MQTT状态、无人值守时间参数显示在OLED屏幕上,并根据目标温度、雷达反馈数据和时间参数自动触发本地和网络报警。远端也可主动通过MQTT命令获取现场状态参数及图像。
启动后显示状态及参数信息

获取参数

打开阀门

关闭阀门

获取图像

图像解析

七、项目中遇到的难题及解决方法
1. I2C冲突问题
虽然DVP摄像头的参数使用的是SCCB类似I2C,但是实际使用中如果调用了摄像头,再调用一个I2C接口用于OLED后ESP32S3就没有多余可用的I2C了。刚开始不知道,导致单独测试红外线测温模块时功能正常,整合进项目里面就失效。发现这个问题也考虑使用软件模拟I2C来使用,结果找了几个库测下来都不好使,最后就是红外线测温和OLED公用I2C总线了。
2. 摄像头画面不是最新
根据这个应用的使用场景,摄像头只有在使用时才会获取画面。按说只要获取一帧数据发送即可,但是在实际测试时发现发送的照片可能是之前的照片。也就是说即使不使用摄像头,他可能也获取了图像,但不是最新的。为了解决这个问题,我将程序改为发送前先扔掉几帧,确保数据最新。
3. 回调函数堵塞问题
在调试过程中,遇到了MQTT通信偶尔延迟导致数据不同步的问题。通过查阅资料和优化代码,我意识到在回调函数中应尽量避免长时间的阻塞操作(如发送图片和立即获取最新温度数据),最终通过调整代码逻辑解决了该问题。
八、心得体会
本次项目让我熟练掌握了ESP32的Wi-Fi、I2C、ADC等外设驱动开发,将传感器数据转化为安全策略,再通过网络实现万物互联,这种软硬结合的创造过程充满了乐趣与挑战。感谢电子森林和贸泽电子举办的这次2026 贸泽电子 M-Design 创意设计大赛(第二季)活动。