- 基于单片机的硫化氢、氨气、甲烷、一氧化碳气体多种有害气体检测与声光报警系统设计
点击链接下载prrotues仿真设计资料:https://download.csdn.net/download/m0_51061483/91644950
- 系统总体方案设计
2.1 设计背景与现实意义
在污水处理厂、化工厂、油气站、煤矿、地下管廊、锅炉房、实验室以及各种有限空间环境中,经常会出现多种有害气体混合存在的情况。其中硫化氢(H₂S)、氨气(NH₃)、甲烷(CH₄)、一氧化碳(CO)是最常见且危险性极高的四类气体:
- 硫化氢(H₂S):具有强烈臭鸡蛋味,低浓度即可刺激眼鼻和呼吸道,高浓度会导致呼吸麻痹甚至瞬间致死,是典型的"高毒性气体"。
- 氨气(NH₃):具有刺激性气味,对黏膜腐蚀性强,高浓度会引起灼伤、支气管痉挛和肺水肿,且氨气泄漏往往伴随设备故障风险。
- 甲烷(CH₄):无色无味,可燃易爆,浓度达到爆炸极限范围时遇明火可发生爆炸,地下空间尤其危险。
- 一氧化碳(CO):无色无味,不易察觉,与血红蛋白结合导致人体缺氧,中毒隐蔽性强,事故案例频繁。
传统单一气体报警器通常只能检测一种气体,并且在混合气体环境下不具备综合判断能力,容易出现"漏检"或"现场需要携带多个检测仪"的问题。多气体检测系统能够同时监测多种有害气体并进行统一的阈值管理与报警输出,显著提高现场安全水平,减少中毒、窒息、爆炸等事故概率。
因此,本设计提出一套基于51单片机的多种有害气体检测与声光报警系统,利用多个气体传感器实时采集H₂S、NH₃、CH₄、CO浓度信息,通过LCD1602显示测量结果,并提供按键设置报警阈值功能。当任意气体浓度超过设定阈值时,系统立即启动声光报警,提醒人员撤离或采取通风、切断气源等措施,从而构建低成本、易部署、易维护的现场安全监测设备。
2.2 系统设计目标
本系统在功能、可靠性与可扩展性方面设定如下目标:
- 四种气体实时采集:使用51单片机对H₂S、NH₃、CH₄、CO四路气体传感器信号进行采样与处理。
- 实时显示:LCD1602实时显示四种气体的测量值,并能显示单位、报警状态、阈值信息或页面编号。
- 阈值可设置:通过按键设置每种气体的报警阈值,确保系统可适配不同现场环境与安全标准。
- 声光报警可靠:当任意气体浓度超限,蜂鸣器鸣叫、报警灯闪烁,并在LCD上显示报警气体类型。
- 抗干扰与稳定运行:具备滤波、消抖、超限确认、传感器异常检测等策略,降低误报概率,适合工业现场长时间工作。
- 扩展能力:可扩展EEPROM存储阈值、RS485上位机通信、无线传输等,提高工程应用价值。
2.3 系统总体结构与工作流程
系统主要由以下硬件模块组成:
- 51单片机最小系统模块(STC89C51/AT89C52等)
- 气体传感器采集模块(H₂S、NH₃、CH₄、CO)
- A/D转换模块(多通道ADC,将模拟电压转换为数字量)
- LCD1602显示模块
- 按键设置模块
- 声光报警模块(蜂鸣器+报警LED)
- 电源模块(5V稳压,必要时提供3.3V或加热供电)
- 可选存储模块(EEPROM保存阈值)
系统软件流程如下:
- 上电初始化 → 读取阈值参数 → 传感器预热/稳定 → ADC多通道采集 → 数据滤波与浓度换算 → LCD显示 → 按键设置阈值 → 超限判断 → 声光报警 → 循环运行。
- 功能设计与工作原理
3.1 气体采集功能
3.1.1 传感器阵列与多气体检测思想
本系统的核心是"四传感器阵列"。每个气体传感器对目标气体具有一定敏感性,其输出通常表现为电阻或电压变化。通过分别测量四路信号,可以实现多气体同时监测。
在实际环境中,气体传感器可能存在交叉敏感(例如某些半导体传感器对多种还原性气体都有响应),因此系统更适合用于"超限报警+趋势监测"。若需要更高精度,可以通过标定、补偿或更换为电化学传感器提高准确性。
3.1.2 采集信号类型与处理要求
常见气体传感器输出形式:
- 模拟电压输出模块:传感器模块内部已完成分压与放大,输出0~5V范围模拟电压,便于ADC采样。
- 电阻输出传感器:需要外部分压电路将电阻变化转换为电压。
- 电化学传感器 :输出微电流,需要跨阻放大电路得到电压信号。
为了便于51单片机实现,本设计推荐使用带模拟输出的传感器模块或经过信号调理后输出0~5V电压,以便A/D转换。
3.1.3 采样周期与实时性平衡
气体浓度变化通常不是毫秒级,因此系统无需高频采样。推荐:
- 采样周期:1秒/次
- 每次采样每路进行8~16次平均
- 显示刷新:1秒/次
- 报警判断:每次采样后进行并加入确认计数
这样能兼顾实时性、稳定性与单片机资源占用。
3.2 数据显示功能(LCD1602)
3.2.1 显示内容规划
LCD1602仅两行显示,为了显示四种气体浓度,可采用"页面轮换显示":
- 页面1:H₂S与NH₃
- 页面2:CH₄与CO
- 页面3(可选):阈值显示/设置界面
- 页面4(可选):报警状态与故障信息
例如: - 第1页:
H2S:012ppm/NH3:025ppm - 第2页:
CH4:08%LEL/CO :035ppm
同时可在右侧显示报警标志:ALM、OK、ERR等,提升可读性。
3.2.2 显示刷新策略与稳定性
LCD刷新过快会导致闪烁并占用CPU,建议:
- 1秒刷新一次数值
- 页面自动每2秒或3秒切换一次
- 报警发生时固定显示报警页面,不再轮换
这种策略有利于现场人员快速捕捉危险信息。
3.3 按键设置阈值功能
3.3.1 阈值设置的必要性
不同现场对报警浓度要求不同,例如污水厂、矿井、化工车间的允许浓度和报警等级各不相同。若阈值固定,会出现报警太敏感或不敏感的问题。因此必须提供按键设置能力,支持现场快速调整。
3.3.2 按键交互设计
建议采用3~5个按键实现完整设置:
- SET:进入设置/切换气体种类/确认
- UP:增加阈值
- DOWN:减少阈值
- OK(可选):保存
- ESC(可选):退出/取消
设置逻辑:
- 短按SET进入阈值设置模式;
- SET切换当前设置对象:H₂S→NH₃→CH₄→CO;
- UP/DOWN调整阈值;
- 长按SET或OK保存退出;
- 若使用EEPROM则保存后断电不丢失。
为了提高效率,应加入长按加速:按住UP/DOWN持续快速增减。
3.4 声光报警功能
3.4.1 报警触发机制
系统判断每种气体测量值是否超过阈值:
- 若任一气体超限 → 启动报警
- 若多个气体同时超限 → 仍报警,并在LCD轮流显示或显示最危险气体
报警输出包括: - 蜂鸣器鸣叫(有源蜂鸣器)
- 报警LED闪烁(红色高亮)
- LCD显示报警气体名称与浓度
同时可加入"报警确认次数":连续3次采样超限才触发报警,减少误报。
3.4.2 报警解除与保持
报警解除策略建议:
- 浓度恢复到阈值以下,并连续3次稳定 → 解除报警
- 或提供按键消音功能,但报警灯仍闪烁,直到浓度恢复安全范围
这种机制在现场非常实用,既避免持续噪声扰人,又不会掩盖危险状态。
- 电路设计(分模块详细说明)
4.1 51单片机最小系统模块
4.1.1 单片机选型与理由
可选STC89C51或AT89C52等8051兼容单片机。原因:
- 成本低、学习资料丰富
- IO资源充足,适合多传感器、多按键、多外设
- 定时器和串口资源满足显示、按键扫描和扩展通信需求
系统对单片机的主要需求为: - 读取ADC数据
- 数据处理、滤波、阈值判断
- LCD驱动
- 按键扫描
- 声光报警控制
4.1.2 时钟与复位设计
- 晶振:11.0592MHz或12MHz
- 复位:RC上电复位+按键复位
- 去耦:VCC旁0.1uF,电源入口加100uF电解电容
保证系统上电稳定、运行可靠。
4.1.3 抗干扰措施
工业现场干扰强,建议:
- 数字部分与模拟采样部分分区布线
- 传感器信号线尽量短并远离蜂鸣器、继电器线
- ADC参考电压稳定,电源加滤波
- 单片机地线采用单点接地或星形接地
这些细节能显著提升采集稳定性。
4.2 气体传感器采集模块
4.2.1 硫化氢传感器模块(H₂S)
H₂S常见于污水厌氧分解环境。模块输出电压会随浓度变化。电路设计要点:
- 输出接ADC输入通道
- 增加RC低通滤波,抑制噪声
- 传感器需防潮防腐蚀,可加透气防水膜
- 建议提供校准接口,便于零点与跨度校准
4.2.2 氨气传感器模块(NH₃)
NH₃对湿度影响较大,电路建议:
- 增加温湿度补偿模块(可选)
- 软件层面进行漂移补偿
- 模块应避免水汽直接侵入传感元件
4.2.3 甲烷传感器模块(CH₄)
CH₄检测重点在可燃风险。若使用半导体传感器,其加热功耗较大,电路需注意:
- 供电电流足够,避免5V掉压导致单片机复位
- 加热电源与逻辑电源分开滤波
- 输出用于计算%LEL,并设置合理报警阈值
甲烷传感器需预热较长时间,软件要有预热阶段管理。
4.2.4 一氧化碳传感器模块(CO)
CO无色无味,中毒风险极高。电路要点:
- 传感器输出需要稳定,供电需干净
- 增加滤波与零点校准逻辑
- 可设置两级报警阈值(扩展),提升安全性
4.3 A/D转换模块
4.3.1 模块作用与通道分配
51单片机一般不带多路ADC,因此需外接A/D转换芯片或模块。常用:
- ADC0809:8路8位,多通道适合本系统
- MCP3008:8路10位,SPI接口,精度更高
本系统需要至少4路ADC通道: - CH0:H₂S
- CH1:NH₃
- CH2:CH₄
- CH3:CO
如需温湿度补偿可扩展更多通道。
4.3.2 参考电压与采样精度
ADC精度取决于参考电压与分辨率:
- 8位ADC分辨率约5V/256≈19.5mV
- 10位ADC分辨率约5V/1024≈4.88mV
若传感器输出变化较小,建议使用10位ADC提升分辨率。
电路中应确保参考电压稳定,并对ADC输入端增加小电容滤波,减少波动。
4.4 LCD1602显示模块
4.4.1 接口模式与节省IO
LCD1602推荐使用4位模式:RS、E、D4~D7共6根线,RW接地固定写模式。这样节省IO并提高稳定性。
对比度调节用电位器,背光可直接供电或用三极管控制。
4.4.2 显示抗干扰设计
- LCD供电端加去耦电容
- 信号线不要与蜂鸣器线并行长走
- 程序中定期刷新或重置显示状态,避免强干扰导致乱码
4.5 按键模块
4.5.1 按键硬件结构
按键采用上拉输入,按下为低电平。可加10K电阻上拉,必要时加0.1uF电容形成硬件消抖或抗干扰滤波。
按键布局应清晰标注:SET/UP/DOWN,保证现场人员快速操作。
4.5.2 按键可靠性设计
- 软件消抖(20ms稳定判定)
- 长按加速
- 设置模式超时自动退出(例如10秒无操作退出并保存/不保存)
这些措施可增强系统易用性。
4.6 声光报警模块
4.6.1 蜂鸣器电路设计
推荐使用有源蜂鸣器,由单片机IO控制,通过NPN三极管驱动:
- IO输出高电平 → 三极管导通 → 蜂鸣器响
并可通过定时器控制蜂鸣器间歇鸣叫,实现不同报警节奏(轻度/重度报警)。
4.6.2 报警LED驱动
LED可由IO直接驱动(串联限流电阻),也可用三极管驱动更高亮度LED。
报警LED可采用闪烁方式,增强视觉提示效果。
4.7 电源模块
4.7.1 供电需求分析
系统主要供电为5V,但注意:
- 若使用MQ类传感器加热,电流较大
- 蜂鸣器与LED也会造成电流波动
因此电源模块需提供足够电流(建议1A以上),并加滤波电容抑制波动。
4.7.2 稳压与保护措施
可采用:
- DC-DC降压模块输出5V(效率高、发热小)
- 或7805线性稳压(简单但发热需散热片)
同时加入: - 反接保护
- 保险丝或自恢复保险丝
- TVS防浪涌(可选)
保证系统适合复杂现场环境长期运行。
- 程序设计(分模块详细说明)
5.1 软件总体架构
软件采用"定时器节拍 + 主循环任务调度 + 状态机"结构,主要模块包括:
- ADC采集模块(多通道轮询)
- 数据滤波模块(平均/低通/限幅)
- 浓度换算模块(ADC→电压→浓度)
- LCD显示模块(页面切换)
- 按键扫描模块(消抖、长按、菜单)
- 阈值设置模块(每气体阈值独立设置)
- 报警判断与输出控制模块(声光报警)
- 参数存储模块(EEPROM可选)
- 传感器预热与故障检测模块
主循环中按照周期执行:
- 每1秒采样
- 每1秒刷新显示
- 每10ms扫描按键
- 每100ms更新报警节奏
5.2 ADC采集模块
5.2.1 通道轮询采样
采样顺序固定:H₂S→NH₃→CH₄→CO。每路采样N次取平均,降低随机噪声。切换通道时可丢弃第一次采样避免残留电荷影响。
5.2.2 采样值有效性判断
若ADC值出现:
- 长期为0或满量程
- 变化异常巨大
可认为传感器故障或断线,系统应显示"ERR"并触发报警提示维护。
5.3 数据滤波模块
5.3.1 滑动平均滤波
对每路数据保存最近8次采样值,取平均作为输出:
- 平滑显示
- 降低误报警
- 对慢变化气体监测足够有效
5.3.2 限幅与报警确认机制
限幅滤波:限制单次变化不超过某个范围,避免瞬态噪声导致浓度跳变。
报警确认:连续3次超限才报警,连续3次恢复才解除,显著提高稳定性。
5.4 浓度换算模块
5.4.1 简化线性换算
由于课程设计多采用模块化传感器输出,本设计可用线性映射:
- ppm = k * adc + b
或者 - ppm = adc * Range / 255
甲烷可映射为%LEL。
为了更贴近实际,可提供校准系数k、b可设置,便于现场标定。
5.4.2 标定与误差说明
传感器的真实浓度换算通常需要查表或曲线拟合。本系统强调"安全报警"为主,通过阈值判断实现可靠预警,精度可通过标定提高。论文中应说明:
- 精度受温湿度、交叉敏感、老化影响
- 可通过温湿度补偿、校准与高精度传感器改进
5.5 LCD显示模块
5.5.1 页面轮换显示
由于1602显示有限,采用页面轮换:
- 2秒切换一页
- 报警时固定显示报警气体页面
显示格式应保持对齐,便于快速读取。
5.5.2 报警状态显示
当报警时显示:
ALM:H2S 25ppm- 或
ALM:CH4 18%LEL
同时闪烁ALM字样,强化提示。
5.6 按键扫描与阈值设置模块
5.6.1 按键消抖与事件生成
10ms扫描周期,连续稳定20ms确认按键动作,生成短按事件。
长按UP/DOWN每200ms自动加减,提高调节效率。
5.6.2 设置菜单状态机
设置状态可定义:
- RUN:正常监测
- SET_H2S:设置H₂S阈值
- SET_NH3:设置NH₃阈值
- SET_CH4:设置CH₄阈值
- SET_CO:设置CO阈值
SET键切换状态,UP/DOWN修改阈值,长按SET保存并退出。
设置过程中LCD显示当前阈值并闪烁提示,避免误操作。
5.7 报警控制模块
5.7.1 报警判断逻辑
对于每路气体:
- 若 gas[i] > th[i] → 超限计数++
- 若超限计数达到3 → 报警置位
解除:连续3次低于阈值 → 清除报警
报警输出:蜂鸣器+LED,并显示报警气体。
5.7.2 报警节奏控制
通过定时器节拍实现蜂鸣器间歇鸣叫与LED闪烁:
- 报警周期1秒:500ms响、500ms停
- 多气体报警时可加快节奏或轮流显示最危险气体
可进一步区分不同气体的报警优先级,例如H₂S和CO优先级更高。
- 核心程序代码示例(C语言,51单片机风格:多通道ADC采集 + LCD1602显示 + 按键阈值设置 + 声光报警)
c
#include <reg52.h>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
// ===================== 硬件定义(示例:ADC0809) =====================
sbit ADC_A = P1^0;
sbit ADC_B = P1^1;
sbit ADC_C = P1^2;
sbit ADC_ALE = P1^3;
sbit ADC_START = P1^4;
sbit ADC_EOC = P1^5;
sbit ADC_OE = P1^6;
#define ADC_DATA P0
// ===================== LCD1602(4位模式) =====================
sbit LCD_RS = P2^0;
sbit LCD_E = P2^1;
sbit LCD_D4 = P2^4;
sbit LCD_D5 = P2^5;
sbit LCD_D6 = P2^6;
sbit LCD_D7 = P2^7;
// ===================== Keys =====================
sbit KEY_SET = P3^2;
sbit KEY_UP = P3^3;
sbit KEY_DOWN = P3^4;
// ===================== Alarm =====================
sbit BUZZ = P3^6;
sbit LEDA = P3^7;
// ===================== 系统节拍 =====================
volatile u32 g_ms = 0;
// ===================== 气体通道索引 =====================
#define GAS_H2S 0
#define GAS_NH3 1
#define GAS_CH4 2
#define GAS_CO 3
#define GAS_NUM 4
// ===================== 采样与阈值 =====================
u16 gas_val[GAS_NUM]; // 显示用浓度值
u16 gas_th[GAS_NUM] = {10, 25, 10, 50}; // 默认阈值(ppm/%LEL)
// 超限确认计数
u8 over_cnt[GAS_NUM] = {0};
u8 safe_cnt[GAS_NUM] = {0};
// 报警状态
bit alarm_on = 0;
u8 alarm_gas = 0;
// 页面显示
u8 page = 0;
// ===================== 定时器0:1ms =====================
void Timer0_Init(void)
{
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = 0xFC; TL0 = 0x18; // 1ms@12MHz
ET0 = 1; EA = 1; TR0 = 1;
}
void Timer0_ISR(void) interrupt 1
{
TH0 = 0xFC; TL0 = 0x18;
g_ms++;
}
// ===================== 延时 =====================
void delay_us(u8 t){ while(t--) _nop_(); }
void delay_ms(u16 ms){ u16 i,j; for(i=0;i<ms;i++) for(j=0;j<120;j++); }
// ===================== ADC0809 =====================
void ADC_SetChannel(u8 ch)
{
ADC_A = ch & 0x01;
ADC_B = (ch >> 1) & 0x01;
ADC_C = (ch >> 2) & 0x01;
}
u8 ADC_Read(u8 ch)
{
u8 val;
ADC_SetChannel(ch);
ADC_ALE = 1;
ADC_START = 1;
_nop_();
ADC_ALE = 0;
ADC_START = 0;
while(ADC_EOC == 0);
ADC_OE = 1;
_nop_();
val = ADC_DATA;
ADC_OE = 0;
return val;
}
u8 ADC_ReadAvg(u8 ch, u8 n)
{
u16 sum = 0;
u8 i;
for(i=0;i<n;i++) sum += ADC_Read(ch);
return (u8)(sum / n);
}
// ===================== 浓度换算(示例:线性映射) =====================
// 仅为示例:实际应根据传感器标定曲线修正
u16 Convert_ToConc(u8 gas, u8 adc)
{
if(gas == GAS_CH4)
{
// CH4 映射为 0~100 %LEL
return (u16)adc * 100 / 255;
}
else
{
// 其他映射为 0~200 ppm
return (u16)adc * 200 / 255;
}
}
// ===================== LCD1602驱动 =====================
void LCD_Write4(u8 dat)
{
LCD_D4 = dat & 0x01;
LCD_D5 = (dat & 0x02) ? 1 : 0;
LCD_D6 = (dat & 0x04) ? 1 : 0;
LCD_D7 = (dat & 0x08) ? 1 : 0;
}
void LCD_Enable(void)
{
LCD_E = 1; delay_us(10);
LCD_E = 0; delay_us(10);
}
void LCD_Cmd(u8 cmd)
{
LCD_RS = 0;
LCD_Write4(cmd >> 4); LCD_Enable();
LCD_Write4(cmd & 0x0F); LCD_Enable();
delay_ms(2);
}
void LCD_Data(u8 dat)
{
LCD_RS = 1;
LCD_Write4(dat >> 4); LCD_Enable();
LCD_Write4(dat & 0x0F); LCD_Enable();
delay_us(50);
}
void LCD_SetPos(u8 row, u8 col)
{
u8 addr = (row==0)?0x80:0xC0;
LCD_Cmd(addr + col);
}
void LCD_Print(char *s)
{
while(*s) LCD_Data(*s++);
}
void LCD_Init(void)
{
delay_ms(20);
LCD_RS=0; LCD_E=0;
LCD_Write4(0x03); LCD_Enable(); delay_ms(5);
LCD_Write4(0x03); LCD_Enable(); delay_ms(1);
LCD_Write4(0x03); LCD_Enable(); delay_ms(1);
LCD_Write4(0x02); LCD_Enable();
LCD_Cmd(0x28);
LCD_Cmd(0x0C);
LCD_Cmd(0x06);
LCD_Cmd(0x01);
}
// ===================== 数值转3位字符串 =====================
void u16_to_3char(u16 v, char *out)
{
out[0] = (v/100)%10 + '0';
out[1] = (v/10)%10 + '0';
out[2] = (v%10) + '0';
out[3] = 0;
}
// ===================== 显示页面 =====================
void LCD_ShowPage0(void)
{
char b[4];
LCD_SetPos(0,0);
LCD_Print("H2S:");
u16_to_3char(gas_val[GAS_H2S], b); LCD_Print(b);
LCD_Print("ppm ");
LCD_SetPos(1,0);
LCD_Print("NH3:");
u16_to_3char(gas_val[GAS_NH3], b); LCD_Print(b);
LCD_Print("ppm ");
}
void LCD_ShowPage1(void)
{
char b[4];
LCD_SetPos(0,0);
LCD_Print("CH4:");
u16_to_3char(gas_val[GAS_CH4], b); LCD_Print(b);
LCD_Print("%LEL");
LCD_SetPos(1,0);
LCD_Print("CO :");
u16_to_3char(gas_val[GAS_CO], b); LCD_Print(b);
LCD_Print("ppm ");
}
void LCD_ShowAlarm(void)
{
char b[4];
LCD_SetPos(0,0);
LCD_Print("ALARM! GAS:");
LCD_SetPos(1,0);
if(alarm_gas==GAS_H2S) LCD_Print("H2S ");
else if(alarm_gas==GAS_NH3) LCD_Print("NH3 ");
else if(alarm_gas==GAS_CH4) LCD_Print("CH4 ");
else LCD_Print("CO ");
LCD_Print("V=");
u16_to_3char(gas_val[alarm_gas], b); LCD_Print(b);
}
// ===================== 按键扫描(简化) =====================
u8 Key_Scan(void)
{
static u8 last_set=1, last_up=1, last_down=1;
u8 now_set = KEY_SET;
u8 now_up = KEY_UP;
u8 now_down = KEY_DOWN;
if(last_set==1 && now_set==0){ last_set=0; return 1; }
if(last_up==1 && now_up==0 ){ last_up=0; return 2; }
if(last_down==1&& now_down==0){ last_down=0; return 3; }
last_set = now_set;
last_up = now_up;
last_down = now_down;
return 0;
}
// ===================== 设置模式状态机 =====================
typedef enum{
MODE_RUN=0,
MODE_SET_H2S,
MODE_SET_NH3,
MODE_SET_CH4,
MODE_SET_CO
} Mode_t;
Mode_t g_mode = MODE_RUN;
void Show_Setting(void)
{
char b[4];
LCD_SetPos(0,0);
LCD_Print("SET THRESHOLD ");
LCD_SetPos(1,0);
if(g_mode==MODE_SET_H2S){ LCD_Print("H2S:"); u16_to_3char(gas_th[GAS_H2S], b); LCD_Print(b); }
if(g_mode==MODE_SET_NH3){ LCD_Print("NH3:"); u16_to_3char(gas_th[GAS_NH3], b); LCD_Print(b); }
if(g_mode==MODE_SET_CH4){ LCD_Print("CH4:"); u16_to_3char(gas_th[GAS_CH4], b); LCD_Print(b); }
if(g_mode==MODE_SET_CO ){ LCD_Print("CO :"); u16_to_3char(gas_th[GAS_CO ], b); LCD_Print(b); }
LCD_Print(" ");
}
void Apply_SetKey(u8 ev)
{
if(ev==0) return;
if(ev==1) // SET
{
if(g_mode==MODE_RUN) g_mode = MODE_SET_H2S;
else if(g_mode==MODE_SET_H2S) g_mode = MODE_SET_NH3;
else if(g_mode==MODE_SET_NH3) g_mode = MODE_SET_CH4;
else if(g_mode==MODE_SET_CH4) g_mode = MODE_SET_CO;
else g_mode = MODE_RUN;
}
else if(ev==2) // UP
{
if(g_mode==MODE_SET_H2S && gas_th[GAS_H2S]<200) gas_th[GAS_H2S]++;
if(g_mode==MODE_SET_NH3 && gas_th[GAS_NH3]<200) gas_th[GAS_NH3]++;
if(g_mode==MODE_SET_CH4 && gas_th[GAS_CH4]<100) gas_th[GAS_CH4]++;
if(g_mode==MODE_SET_CO && gas_th[GAS_CO ]<200) gas_th[GAS_CO ]++;
}
else if(ev==3) // DOWN
{
if(g_mode==MODE_SET_H2S && gas_th[GAS_H2S]>0) gas_th[GAS_H2S]--;
if(g_mode==MODE_SET_NH3 && gas_th[GAS_NH3]>0) gas_th[GAS_NH3]--;
if(g_mode==MODE_SET_CH4 && gas_th[GAS_CH4]>0) gas_th[GAS_CH4]--;
if(g_mode==MODE_SET_CO && gas_th[GAS_CO ]>0) gas_th[GAS_CO ]--;
}
}
// ===================== 报警判断 =====================
void Alarm_Check(void)
{
u8 i;
alarm_on = 0;
for(i=0;i<GAS_NUM;i++)
{
if(gas_val[i] > gas_th[i])
{
if(over_cnt[i] < 10) over_cnt[i]++;
safe_cnt[i] = 0;
}
else
{
if(safe_cnt[i] < 10) safe_cnt[i]++;
if(over_cnt[i] > 0) over_cnt[i]--;
}
// 连续3次超限触发报警
if(over_cnt[i] >= 3)
{
alarm_on = 1;
alarm_gas = i;
}
}
if(alarm_on)
{
LEDA = 0;
BUZZ = 1;
}
else
{
LEDA = 1;
BUZZ = 0;
}
}
// ===================== 主函数 =====================
void main(void)
{
u32 last_sample=0, last_disp=0, last_key=0;
LEDA=1; BUZZ=0;
LCD_Init();
Timer0_Init();
while(1)
{
// 10ms按键扫描
if(g_ms - last_key >= 10)
{
u8 ev;
last_key = g_ms;
ev = Key_Scan();
Apply_SetKey(ev);
}
// 1秒采样
if(g_ms - last_sample >= 1000)
{
u8 a;
last_sample = g_ms;
a = ADC_ReadAvg(0, 8);
gas_val[GAS_H2S] = Convert_ToConc(GAS_H2S, a);
a = ADC_ReadAvg(1, 8);
gas_val[GAS_NH3] = Convert_ToConc(GAS_NH3, a);
a = ADC_ReadAvg(2, 8);
gas_val[GAS_CH4] = Convert_ToConc(GAS_CH4, a);
a = ADC_ReadAvg(3, 8);
gas_val[GAS_CO] = Convert_ToConc(GAS_CO, a);
Alarm_Check();
}
// 显示刷新
if(g_ms - last_disp >= 2000)
{
last_disp = g_ms;
if(alarm_on)
{
LCD_ShowAlarm();
}
else if(g_mode != MODE_RUN)
{
Show_Setting();
}
else
{
if(page==0){ LCD_ShowPage0(); page=1; }
else { LCD_ShowPage1(); page=0; }
}
}
}
}
- 关键模块深化说明与工程化优化建议
7.1 传感器预热与稳定期管理
半导体气体传感器(如MQ系列)通常需要预热时间,刚上电输出波动大。系统应加入预热阶段:
- 上电后显示"WARMUP"
- 预热期间不进行报警或阈值提高
- 预热结束后进入正常检测
预热时间可设置为30秒、60秒或更长,具体取决于传感器特性。该策略能显著降低误报警,提升系统可信度。
7.2 阈值与单位规范化设计
不同气体阈值的量纲不同:
- H₂S、NH₃、CO通常使用ppm
- CH₄通常以%LEL或%VOL表示
系统显示与设置应明确单位,避免操作人员误设。
为了更专业,可加入两级阈值(低报警、高报警),并设置不同报警节奏。
7.3 误报警抑制与安全优先级
建议加入:
- 采样平均与限幅滤波
- 超限确认次数
- 报警解除延迟
- 多气体优先级:H₂S与CO优先级更高(毒性强),CH₄优先级也高(爆炸风险)
当多气体同时超限时,LCD可轮流显示,或显示最高危险等级气体。
7.4 阈值掉电保存与校验机制(扩展)
外接EEPROM可保存阈值:
- 上电读取,保证参数不丢失
- 写入时加校验字节(如校验和),防止数据损坏
同时可支持恢复默认值功能,便于维护。
7.5 通信扩展与远程监控(扩展方向)
系统可扩展:
- RS485通信上传浓度数据到中控室
- 无线模块(LoRa/WiFi)实现远程报警推送
- 数据记录模块保存历史浓度曲线
这些扩展可以显著提升系统工程价值,并可作为论文创新点。
7.6 结构防护与现场适应性建议
由于污水厂、化工现场湿度大、腐蚀性强,整机结构建议:
- 外壳具备防水防尘(至少IP54)
- 传感器开孔使用透气防水膜
- PCB喷涂三防漆
- 供电端增加浪涌保护
这些措施能显著提高设备寿命与可靠性。
- 系统测试方案与验证要点
8.1 硬件功能测试
- 检查四路传感器输出是否正常变化
- ADC采样是否稳定,通道切换无异常
- LCD显示是否清晰、无乱码
- 蜂鸣器与LED报警是否可靠
8.2 阈值设置测试
- 进入设置模式并修改各气体阈值
- 检查阈值范围限制是否正确
- 设置完成退出后阈值是否生效
- 若有EEPROM,断电重启后阈值是否保持
8.3 报警测试
- 设置低阈值使报警易触发,验证超限确认次数与报警输出
- 测试解除报警逻辑:浓度恢复后是否按规则解除
- 多气体同时超限时显示与报警是否符合预期
- 传感器故障(断线/输出异常)是否能提示并报警
8.4 稳定性与抗干扰测试
- 长时间运行是否出现死机、显示异常
- 电源波动或干扰下采样是否稳定
- 预热阶段是否正确抑制误报警
- 实际现场环境下是否存在明显漂移,需要多频次校准
- 总结
本设计实现了一套基于51单片机的多种有害气体检测与声光报警系统,能够同时采集硫化氢、氨气、甲烷和一氧化碳四种气体浓度,并通过LCD1602实时显示测量结果。系统提供按键设置每种气体报警阈值的功能,使设备能够适配不同场景的安全要求。当任意气体浓度超过设定阈值时,系统立即启动蜂鸣器与报警LED进行声光报警,并在LCD上突出显示报警气体类型与测量值,帮助现场人员快速识别危险并采取措施。
在电路设计方面,系统采用模块化结构,包括单片机最小系统、传感器阵列、A/D转换、显示模块、按键模块、声光报警与电源模块,各模块连接清晰,便于调试与扩展;在程序设计方面,系统采用周期采样、滤波处理、阈值判断、菜单状态机与报警节奏控制等策略,提高测量稳定性并降低误报警概率。进一步通过加入预热管理、阈值掉电保存、通信上传与数据记录等扩展,可使系统具备更强的工程应用价值与可靠性。