文章目录
-
- 一、前言
-
- [1.1 技术背景](#1.1 技术背景)
- [1.2 应用场景](#1.2 应用场景)
- [1.3 本文目标](#1.3 本文目标)
- 二、环境准备
-
- [2.1 硬件清单](#2.1 硬件清单)
- [2.2 硬件连接图](#2.2 硬件连接图)
- 三、核心实现
-
- [3.1 STM32CubeMX配置](#3.1 STM32CubeMX配置)
- [3.2 主程序实现](#3.2 主程序实现)
- 四、测试验证
-
- [4.1 传感器测试](#4.1 传感器测试)
- [4.2 报警联动测试](#4.2 报警联动测试)
- 五、故障排查
-
- [5.1 常见问题](#5.1 常见问题)
- 六、总结
-
- [6.1 核心知识点](#6.1 核心知识点)
- [6.2 扩展方向](#6.2 扩展方向)
- [6.3 学习资源](#6.3 学习资源)
一、前言
1.1 技术背景
火灾是威胁人民生命财产安全的重大隐患,早期预警和快速响应是减少火灾损失的关键。智能消防报警联动系统通过多种传感器实时监测环境参数,在火灾初期及时发出警报并联动相关设备,为人员疏散和火灾扑救争取宝贵时间。
本项目基于STM32F103微控制器,集成烟雾传感器、温度传感器、火焰传感器等多种探测手段,实现火灾检测、声光报警、联动控制等功能,适用于家庭、办公室、仓库等场所。
1.2 应用场景
- 家庭住宅:厨房烟雾检测,卧室温度监测
- 办公场所:公共区域火灾预警
- 仓库厂房:大空间多点监测
- 学校医院:人员密集场所安全监控
1.3 本文目标
通过本教程,你将学会:
- MQ-2烟雾传感器数据采集与校准
- 多传感器数据融合算法
- 火灾检测算法与阈值判断
- GSM模块实现短信和电话报警
- 继电器控制联动设备(喷淋、排烟等)
- TFT显示屏实时显示监控画面
- 数据存储与历史记录查询
技术栈:
- 硬件平台:STM32F103C8T6
- 烟雾传感器:MQ-2(模拟输出)
- 温度传感器:DS18B20 + LM35
- 火焰传感器:红外火焰传感器
- 声光报警:蜂鸣器 + RGB LED
- 通信模块:SIM800L GSM模块
- 显示模块:2.4寸TFT触摸屏
- 存储:SD卡模块
- 联动控制:继电器模块
二、环境准备
2.1 硬件清单
| 器件名称 | 型号/规格 | 数量 | 说明 |
|---|---|---|---|
| 主控芯片 | STM32F103C8T6 | 1 | Blue Pill开发板 |
| 烟雾传感器 | MQ-2 | 2 | 烟雾/可燃气体 |
| 温度传感器 | DS18B20 | 2 | 防水型 |
| 火焰传感器 | 红外型 | 2 | 火焰检测 |
| GSM模块 | SIM800L | 1 | 短信/电话报警 |
| TFT显示屏 | 2.4寸 | 1 | ILI9341触摸屏 |
| SD卡模块 | SPI接口 | 1 | 数据存储 |
| 蜂鸣器 | 有源5V | 1 | 声音报警 |
| RGB LED | 共阴极 | 2 | 状态指示 |
| 继电器 | 5V四路 | 1 | 联动控制 |
| 电源 | 5V/3A | 1 | 系统供电 |
2.2 硬件连接图
PA0/PA1
PA2/PA3
PA4/PA5
PA9/PA10
PA5-PA7
PB12-PB15
PB0-PB3
STM32F103C8T6
MQ-2烟雾传感器
DS18B20温度
火焰传感器
SIM800L GSM
ILI9345 TFT
SD卡模块
继电器模块
引脚连接表:
| STM32引脚 | 连接设备 | 功能说明 |
|---|---|---|
| PA0 | MQ-2 #1 | ADC输入 |
| PA1 | MQ-2 #2 | ADC输入 |
| PA2 | DS18B20 #1 | 单总线 |
| PA3 | DS18B20 #2 | 单总线 |
| PA4 | 火焰传感器 #1 | 数字输入 |
| PA5 | 火焰传感器 #2 | 数字输入 |
| PA6 | 蜂鸣器 | PWM输出 |
| PA7 | RGB LED | PWM输出 |
| PA9 | SIM800L TX | UART1 RX |
| PA10 | SIM800L RX | UART1 TX |
| PB0-PB3 | 继电器 | 输出控制 |
| PB12 | SD CS | SPI片选 |
| PB13 | SD SCK | SPI时钟 |
| PB14 | SD MISO | SPI数据输入 |
| PB15 | SD MOSI | SPI数据输出 |
三、核心实现
3.1 STM32CubeMX配置
时钟配置:
- HSE Crystal/Ceramic Resonator
- System Clock: 72MHz
外设配置:
- ADC1:PA0, PA1,烟雾传感器
- USART1:PA9(TX), PA10(RX),GSM通信
- SPI2:PB13(SCK), PB14(MISO), PB15(MOSI),SD卡
- TIM2:1s定时器,传感器采样
- TIM3:PWM输出,蜂鸣器
- GPIO :
- PA2, PA3:开漏输出,DS18B20
- PA4, PA5:输入,火焰传感器
- PA6, PA7:PWM输出
- PB0-PB3:输出,继电器
- PB12:输出,SD卡片选
3.2 主程序实现
📄 创建文件:
Core/Src/main.c
c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Smart Fire Alarm Linkage System
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "usart.h"
#include "spi.h"
#include "tim.h"
#include "gpio.h"
#include "fatfs.h"
/* USER CODE BEGIN Includes */
#include "mq2_sensor.h"
#include "ds18b20.h"
#include "gsm_module.h"
#include "ili9341.h"
#include "sd_card.h"
#include "fire_detector.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* USER CODE END Includes */
/* Private defines -----------------------------------------------------------*/
#define SENSOR_READ_INTERVAL 1000 // 传感器读取间隔(ms)
#define ALARM_THRESHOLD_SMOKE 300 // 烟雾报警阈值
#define ALARM_THRESHOLD_TEMP 60 // 温度报警阈值(°C)
#define ALARM_CONFIRM_COUNT 3 // 报警确认次数
#define GSM_ALERT_INTERVAL 30000 // GSM报警间隔(ms)
#define DATA_LOG_INTERVAL 60000 // 数据记录间隔(ms)
/* Private typedef -----------------------------------------------------------*/
typedef enum {
STATUS_NORMAL = 0,
STATUS_WARNING,
STATUS_ALARM,
STATUS_FAULT
} SystemStatus;
typedef enum {
SENSOR_SMOKE_1 = 0,
SENSOR_SMOKE_2,
SENSOR_TEMP_1,
SENSOR_TEMP_2,
SENSOR_FLAME_1,
SENSOR_FLAME_2,
SENSOR_COUNT
} SensorType;
typedef struct {
uint8_t type;
uint16_t value;
uint8_t alarm;
uint32_t timestamp;
} SensorData;
/* Private variables ---------------------------------------------------------*/
volatile SystemStatus system_status = STATUS_NORMAL;
volatile SensorData sensors[SENSOR_COUNT];
volatile uint8_t alarm_confirmed = 0;
volatile uint8_t alarm_counter = 0;
volatile uint32_t last_sensor_read = 0;
volatile uint32_t last_gsm_alert = 0;
volatile uint32_t last_data_log = 0;
volatile uint8_t linkage_active = 0;
// 联动设备状态
volatile uint8_t sprinkler_on = 0;
volatile uint8_t exhaust_on = 0;
volatile uint8_t alarm_horn_on = 0;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void Read_All_Sensors(void);
static void Process_Fire_Detection(void);
static void Control_Linkage(void);
static void Send_Alert(void);
static void Log_Data(void);
static void Update_Display(void);
static void Set_Alarm_Level(uint8_t level);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/**
* @brief 主函数入口
*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
MX_SPI2_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_FATFS_Init();
/* USER CODE BEGIN 2 */
printf("\\r\\n===== Smart Fire Alarm System =====\\r\\n");
// 初始化TFT显示屏
printf("Initializing TFT...\\r\\n");
ILI9341_Init();
ILI9341_FillScreen(BLACK);
ILI9341_DrawString(20, 20, "Fire Alarm System", WHITE, BLACK, 2);
ILI9341_DrawString(20, 60, "Initializing...", WHITE, BLACK, 1);
HAL_Delay(1000);
// 初始化DS18B20
printf("Initializing DS18B20...\\r\\n");
DS18B20_Init();
// 初始化GSM模块
printf("Initializing GSM...\\r\\n");
if (GSM_Init() == HAL_OK)
{
printf("GSM ready\\r\\n");
ILI9341_DrawString(20, 80, "GSM: OK", GREEN, BLACK, 1);
}
else
{
printf("GSM init failed\\r\\n");
ILI9341_DrawString(20, 80, "GSM: FAIL", RED, BLACK, 1);
}
// 初始化SD卡
printf("Initializing SD card...\\r\\n");
if (SD_Init() == FR_OK)
{
printf("SD card ready\\r\\n");
ILI9341_DrawString(20, 100, "SD Card: OK", GREEN, BLACK, 1);
}
else
{
printf("SD card init failed\\r\\n");
ILI9341_DrawString(20, 100, "SD Card: FAIL", RED, BLACK, 1);
}
// 初始化传感器数据结构
for (int i = 0; i < SENSOR_COUNT; i++)
{
sensors[i].type = i;
sensors[i].value = 0;
sensors[i].alarm = 0;
sensors[i].timestamp = 0;
}
// 启动定时器
HAL_TIM_Base_Start_IT(&tim2);
printf("System ready\\r\\n");
ILI9341_FillScreen(BLACK);
/* USER CODE END 2 */
/* Infinite loop */
while (1)
{
/* USER CODE BEGIN 3 */
// 读取传感器
if (HAL_GetTick() - last_sensor_read >= SENSOR_READ_INTERVAL)
{
last_sensor_read = HAL_GetTick();
Read_All_Sensors();
}
// 火灾检测处理
Process_Fire_Detection();
// 联动控制
Control_Linkage();
// 发送报警
if (system_status == STATUS_ALARM)
{
Send_Alert();
}
// 数据记录
if (HAL_GetTick() - last_data_log >= DATA_LOG_INTERVAL)
{
last_data_log = HAL_GetTick();
Log_Data();
}
// 更新显示
Update_Display();
HAL_Delay(100);
}
/* USER CODE END 3 */
}
/**
* @brief 读取所有传感器数据
*/
static void Read_All_Sensors(void)
{
// 读取烟雾传感器
sensors[SENSOR_SMOKE_1].value = MQ2_Read(1);
sensors[SENSOR_SMOKE_2].value = MQ2_Read(2);
// 读取温度传感器
sensors[SENSOR_TEMP_1].value = (uint16_t)(DS18B20_ReadTemp(1) * 10);
sensors[SENSOR_TEMP_2].value = (uint16_t)(DS18B20_ReadTemp(2) * 10);
// 读取火焰传感器
sensors[SENSOR_FLAME_1].value = HAL_GPIO_ReadPin(FLAME1_GPIO_Port, FLAME1_Pin) == 0 ? 1 : 0;
sensors[SENSOR_FLAME_2].value = HAL_GPIO_ReadPin(FLAME2_GPIO_Port, FLAME2_Pin) == 0 ? 1 : 0;
// 更新时间戳
for (int i = 0; i < SENSOR_COUNT; i++)
{
sensors[i].timestamp = HAL_GetTick();
}
printf("Sensors - Smoke1:%d Smoke2:%d Temp1:%.1f Temp2:%.1f Flame1:%d Flame2:%d\\r\\n",
sensors[SENSOR_SMOKE_1].value,
sensors[SENSOR_SMOKE_2].value,
sensors[SENSOR_TEMP_1].value / 10.0,
sensors[SENSOR_TEMP_2].value / 10.0,
sensors[SENSOR_FLAME_1].value,
sensors[SENSOR_FLAME_2].value);
}
/**
* @brief 火灾检测处理
*/
static void Process_Fire_Detection(void)
{
uint8_t smoke_alarm = 0;
uint8_t temp_alarm = 0;
uint8_t flame_alarm = 0;
// 检查烟雾
if (sensors[SENSOR_SMOKE_1].value > ALARM_THRESHOLD_SMOKE ||
sensors[SENSOR_SMOKE_2].value > ALARM_THRESHOLD_SMOKE)
{
smoke_alarm = 1;
sensors[SENSOR_SMOKE_1].alarm = 1;
sensors[SENSOR_SMOKE_2].alarm = 1;
}
else
{
sensors[SENSOR_SMOKE_1].alarm = 0;
sensors[SENSOR_SMOKE_2].alarm = 0;
}
// 检查温度
if (sensors[SENSOR_TEMP_1].value > ALARM_THRESHOLD_TEMP * 10 ||
sensors[SENSOR_TEMP_2].value > ALARM_THRESHOLD_TEMP * 10)
{
temp_alarm = 1;
sensors[SENSOR_TEMP_1].alarm = 1;
sensors[SENSOR_TEMP_2].alarm = 1;
}
else
{
sensors[SENSOR_TEMP_1].alarm = 0;
sensors[SENSOR_TEMP_2].alarm = 0;
}
// 检查火焰
if (sensors[SENSOR_FLAME_1].value || sensors[SENSOR_FLAME_2].value)
{
flame_alarm = 1;
sensors[SENSOR_FLAME_1].alarm = 1;
sensors[SENSOR_FLAME_2].alarm = 1;
}
else
{
sensors[SENSOR_FLAME_1].alarm = 0;
sensors[SENSOR_FLAME_2].alarm = 0;
}
// 多传感器融合判断
uint8_t alarm_triggered = 0;
if (flame_alarm)
{
// 火焰检测直接报警
alarm_triggered = 1;
}
else if (smoke_alarm && temp_alarm)
{
// 烟雾+温度双重确认
alarm_triggered = 1;
}
else if (smoke_alarm || temp_alarm)
{
// 单一传感器触发,进入预警状态
if (system_status == STATUS_NORMAL)
{
system_status = STATUS_WARNING;
Set_Alarm_Level(1);
printf("WARNING: Potential fire detected\\r\\n");
}
}
// 报警确认计数
if (alarm_triggered)
{
alarm_counter++;
if (alarm_counter >= ALARM_CONFIRM_COUNT)
{
if (system_status != STATUS_ALARM)
{
system_status = STATUS_ALARM;
alarm_confirmed = 1;
linkage_active = 1;
Set_Alarm_Level(3);
printf("ALARM: Fire confirmed!\\r\\n");
}
}
}
else
{
alarm_counter = 0;
if (system_status == STATUS_WARNING && !smoke_alarm && !temp_alarm)
{
system_status = STATUS_NORMAL;
Set_Alarm_Level(0);
printf("Status: Back to normal\\r\\n");
}
}
}
/**
* @brief 联动控制
*/
static void Control_Linkage(void)
{
if (!linkage_active)
{
return;
}
// 启动喷淋系统
if (!sprinkler_on)
{
HAL_GPIO_WritePin(RELAY1_GPIO_Port, RELAY1_Pin, GPIO_PIN_SET);
sprinkler_on = 1;
printf("Linkage: Sprinkler ON\\r\\n");
}
// 启动排烟系统
if (!exhaust_on)
{
HAL_GPIO_WritePin(RELAY2_GPIO_Port, RELAY2_Pin, GPIO_PIN_SET);
exhaust_on = 1;
printf("Linkage: Exhaust ON\\r\\n");
}
// 启动警报器
if (!alarm_horn_on)
{
HAL_GPIO_WritePin(RELAY3_GPIO_Port, RELAY3_Pin, GPIO_PIN_SET);
alarm_horn_on = 1;
printf("Linkage: Alarm horn ON\\r\\n");
}
}
/**
* @brief 发送报警信息
*/
static void Send_Alert(void)
{
if (HAL_GetTick() - last_gsm_alert < GSM_ALERT_INTERVAL)
{
return;
}
last_gsm_alert = HAL_GetTick();
// 发送短信报警
char sms_buffer[256];
sprintf(sms_buffer,
"FIRE ALARM! Smoke1:%d Smoke2:%d Temp1:%.1fC Temp2:%.1fC Location:Building A",
sensors[SENSOR_SMOKE_1].value,
sensors[SENSOR_SMOKE_2].value,
sensors[SENSOR_TEMP_1].value / 10.0,
sensors[SENSOR_TEMP_2].value / 10.0);
GSM_SendSMS("+86138xxxxxxxx", sms_buffer);
GSM_SendSMS("+86139xxxxxxxx", sms_buffer);
// 拨打电话
GSM_MakeCall("+86138xxxxxxxx");
printf("Alert sent via GSM\\r\\n");
}
/**
* @brief 记录数据到SD卡
*/
static void Log_Data(void)
{
FIL file;
FRESULT res;
char buffer[256];
UINT bytes_written;
// 打开日志文件
res = f_open(&file, "fire_log.csv", FA_OPEN_APPEND | FA_WRITE);
if (res != FR_OK)
{
printf("Failed to open log file\\r\\n");
return;
}
// 写入数据
sprintf(buffer, "%lu,%d,%d,%.1f,%.1f,%d,%d,%d\\r\\n",
HAL_GetTick(),
sensors[SENSOR_SMOKE_1].value,
sensors[SENSOR_SMOKE_2].value,
sensors[SENSOR_TEMP_1].value / 10.0,
sensors[SENSOR_TEMP_2].value / 10.0,
sensors[SENSOR_FLAME_1].value,
sensors[SENSOR_FLAME_2].value,
system_status);
f_write(&file, buffer, strlen(buffer), &bytes_written);
f_close(&file);
printf("Data logged to SD card\\r\\n");
}
/**
* @brief 更新TFT显示
*/
static void Update_Display(void)
{
char buffer[32];
// 根据状态设置背景色
uint16_t bg_color = BLACK;
if (system_status == STATUS_ALARM)
{
bg_color = (HAL_GetTick() / 500) % 2 == 0 ? RED : BLACK;
}
else if (system_status == STATUS_WARNING)
{
bg_color = YELLOW;
}
ILI9341_FillScreen(bg_color);
// 标题
ILI9341_DrawString(40, 10, "FIRE MONITOR", WHITE, bg_color, 2);
// 状态
const char* status_str;
uint16_t status_color;
switch (system_status)
{
case STATUS_NORMAL:
status_str = "NORMAL";
status_color = GREEN;
break;
case STATUS_WARNING:
status_str = "WARNING";
status_color = YELLOW;
break;
case STATUS_ALARM:
status_str = "FIRE ALARM!";
status_color = RED;
break;
default:
status_str = "UNKNOWN";
status_color = WHITE;
}
ILI9341_DrawString(60, 40, status_str, status_color, bg_color, 2);
// 传感器数据
sprintf(buffer, "Smoke1: %d", sensors[SENSOR_SMOKE_1].value);
ILI9341_DrawString(20, 80, buffer, sensors[SENSOR_SMOKE_1].alarm ? RED : WHITE, bg_color, 1);
sprintf(buffer, "Smoke2: %d", sensors[SENSOR_SMOKE_2].value);
ILI9341_DrawString(20, 100, buffer, sensors[SENSOR_SMOKE_2].alarm ? RED : WHITE, bg_color, 1);
sprintf(buffer, "Temp1: %.1fC", sensors[SENSOR_TEMP_1].value / 10.0);
ILI9341_DrawString(20, 120, buffer, sensors[SENSOR_TEMP_1].alarm ? RED : WHITE, bg_color, 1);
sprintf(buffer, "Temp2: %.1fC", sensors[SENSOR_TEMP_2].value / 10.0);
ILI9341_DrawString(20, 140, buffer, sensors[SENSOR_TEMP_2].alarm ? RED : WHITE, bg_color, 1);
sprintf(buffer, "Flame1: %s", sensors[SENSOR_FLAME_1].value ? "YES" : "NO");
ILI9341_DrawString(140, 80, buffer, sensors[SENSOR_FLAME_1].alarm ? RED : WHITE, bg_color, 1);
sprintf(buffer, "Flame2: %s", sensors[SENSOR_FLAME_2].value ? "YES" : "NO");
ILI9341_DrawString(140, 100, buffer, sensors[SENSOR_FLAME_2].alarm ? RED : WHITE, bg_color, 1);
// 联动状态
sprintf(buffer, "Sprinkler: %s", sprinkler_on ? "ON" : "OFF");
ILI9341_DrawString(20, 180, buffer, sprinkler_on ? GREEN : WHITE, bg_color, 1);
sprintf(buffer, "Exhaust: %s", exhaust_on ? "ON" : "OFF");
ILI9341_DrawString(20, 200, buffer, exhaust_on ? GREEN : WHITE, bg_color, 1);
}
/**
* @brief 设置报警级别
* @param level: 0=关闭, 1=预警, 2=警告, 3=报警
*/
static void Set_Alarm_Level(uint8_t level)
{
switch (level)
{
case 0: // 关闭
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
break;
case 1: // 预警
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 200);
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
break;
case 2: // 警告
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 500);
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
break;
case 3: // 报警
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 800);
HAL_GPIO_WritePin(LED_R_GPIO_Port, LED_R_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
break;
}
}
/**
* @brief System Clock Configuration
*/
void SystemClock_Config(void)
{
// 系统时钟配置(由CubeMX生成)
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
HAL_Delay(100);
}
}
四、测试验证
4.1 传感器测试
测试1:烟雾传感器校准
c
void Calibrate_MQ2(void)
{
printf("MQ2 Calibration - Keep sensor in clean air\\r\\n");
HAL_Delay(5000);
uint32_t sum = 0;
for (int i = 0; i < 50; i++)
{
sum += MQ2_Read(1);
HAL_Delay(100);
}
uint16_t baseline = sum / 50;
printf("MQ2 Baseline: %d\\r\\n", baseline);
}
测试2:火焰传感器测试
- 使用打火机在传感器前测试
- 验证检测距离和响应时间
4.2 报警联动测试
- 模拟烟雾触发,验证报警流程
- 检查GSM短信和电话是否正常
- 验证联动设备是否正确启动
五、故障排查
5.1 常见问题
问题1:MQ-2传感器读数不稳定
解决方案:
- 预热传感器5-10分钟
- 添加软件滤波
- 检查电源稳定性
问题2:GSM模块无法发送短信
解决方案:
- 检查SIM卡是否欠费
- 检查信号强度
- 验证APN设置
六、总结
6.1 核心知识点
- 多传感器融合:烟雾+温度+火焰综合判断
- 火灾检测算法:阈值判断+确认机制
- 联动控制:继电器控制外部设备
- GSM通信:短信和电话报警
- 数据记录:SD卡存储历史数据
6.2 扩展方向
- 联网功能:接入物联网平台,远程监控
- 视频监控:添加摄像头记录现场
- 语音报警:语音播报疏散提示
- 消防联动:对接消防系统