目录
一、系统概述
本系统采用STM32F103C8T6单片机(最小系统板)和MQ系列气体传感器模块(如MQ-2、MQ-135等),实现可燃气体或有毒气体的检测与报警功能。系统通过标准外设库进行开发,具有高灵敏度、快速响应的特点。
二、MQ系列气体传感器简介
2.1 MQ传感器概述
MQ系列气体传感器是一系列半导体气敏元件,广泛应用于各类气体检测场景。这类传感器基于金属氧化物半导体(MOS)原理,当目标气体接触传感器表面时,电导率会随气体浓度变化而变化。
主要特点:
- 低成本:价格远低于电化学和红外传感器
- 宽检测范围:可检测多种可燃气体和有毒气体
- 简单驱动电路:只需基本的外围电路即可工作
- 加热元件:内置加热丝,需要预热时间
- 交叉敏感性:可能对多种气体有反应
MQ系列传感器图片:
2.2 常见MQ传感器型号及检测对象
型号 | 主要检测气体 | 典型应用场景 |
---|---|---|
MQ-2 | 可燃气体、烟雾 | 火灾报警、烟雾检测 |
MQ-3 | 酒精(乙醇) | 酒驾检测、酿酒厂监控 |
MQ-4 | 甲烷(CH₄)、天然气 | 燃气泄漏检测 |
MQ-5 | 液化气、天然气 | 厨房燃气监控 |
MQ-6 | 丙烷、LPG | 液化石油气检测 |
MQ-7 | 一氧化碳(CO) | 工业安全、家庭CO报警 |
MQ-8 | 氢气(H₂) | 实验室、氢能源设施 |
MQ-9 | CO和可燃气体 | 综合气体检测 |
MQ-135 | 空气质量、CO₂、NH₃等 | 空气净化系统、工业废气监测 |
2.3 工作原理
基本检测原理:
MQ传感器核心是一个SnO₂(氧化锡)基的半导体材料。在清洁空气中,半导体材料的电子被氧分子捕获,形成电子耗尽层,电阻较高。当遇到还原性气体时:
- 气体与表面吸附的氧反应
- 释放被捕获的电子
- 半导体电阻降低
- 电阻变化量与气体浓度相关
传感器结构:
- 传感层:SnO₂等金属氧化物材料
- 加热线圈:维持传感器工作温度(200-300℃)
- 电极:测量电阻变化
- 防爆网:部分型号具备
信号输出特性:
- 模拟输出(AOUT):随气体浓度变化的电压信号(通常0-5V)
- 数字输出(DOUT):比较器输出,超过阈值时触发
2.4 电气特性
工作参数:
参数 | 典型值 |
---|---|
工作电压 | 5V±0.1V |
加热电压(VH) | 5V±0.1V |
加热电阻(RH) | 33Ω±5% |
加热功耗 | 约750mW |
信号输出电压 | 0.1V-4V |
响应时间 | <10s |
恢复时间 | <30s |
加热电路要求:
- 必须保证稳定的5V供电
- 建议使用独立稳压电路
- 避免与其他电路共用地线
2.5 典型应用电路
电路原理图:
电路分析 :
(1)给模块供5V直流电(注意正负极别接反,否则容易烧毁芯片)。
(2)如果选择DOUT,TTL高低电平端,输出信号可以直接接单片机10口或者接一个NPN型三极管去驱动继电器,电位器RP在这里用于调节输出电平跳变的阀值,由原理图可以分析,当传感器检测到被测气体时,比较器LM393管脚2点的电压值,跟传感器检测到气体的浓度成正比,当浓度值超过电位器RP设定的阀值时,比较器2脚的点位高于3脚的点位,这个时候,比较器1脚输出低电平,LED灯亮,R3为LED灯限流电阻,C1为滤波电容。传感器输出低电平,反之,当没有信号的时候,传感器输出高电平,等于电源电压。第三步:如果选择AOUT,模拟量输出,那样就不用管电位器了,直接将AOUT脚接AD转换的输入端或者,带有AD功能的单片机,就可以了。根据我们的经验:在正常环境中,即:没有被测气体的环境,设定传感器输出电压值为参考电压,这时,AOUT端的电压在1V左右,当传感器检测到被测气体时,电压每升高0.1V,实际被测气体的浓度增加200ppm(简单的说:1ppm=1mg/kg=1mg/L=1x10-6 常用来表示气体浓度,或者溶液浓度。),根据这个参数就可以在单片机里面将测得的模拟量电压值转换为浓度值。
注意:该传感器存在误差,因为,输出浓度和电压关系的比值并非线性,而是趋于线性。特别提醒:传感器通电后,需要预热20S左右,测量的数据才稳定,传感器发热属于正常现象,因为内部有电热如果烫手就不正常了
模块引脚描述:
模块中蓝色的电位器是用于调节灵敏度,顺时针旋转,灵敏度越小,逆时针越大。
引脚名称 |
描述 |
VCC |
5V供电 |
GND |
地线 |
DOUT | 数字量输出(TTL电平) |
AOUT | 模拟量输出(0-5V) |
2.6 MQ传感器的优缺点
优点:
- 成本低廉,适合大批量应用
- 检测范围广,灵敏度较高
- 结构简单,易于集成
- 功耗相对较低
缺点:
- 选择性较差(交叉敏感)
- 受环境影响大(温湿度)
- 需要预热时间
- 寿命相对较短
- 需要定期校准
MQ系列传感器以其优异的性价比,成为入门级气体检测项目的首选。理解其工作原理和特性,可以更好地应用于实际项目中,发挥最大效能。
三、硬件设计
3.1 硬件组成
- STM32F103C8T6最小系统板
- MQ系列气体传感器模块(以MQ-2为例)
- 1602 LCD显示屏或OLED显示屏
- LED指示灯
- 有源蜂鸣器
- 电位器(10KΩ)
- 电阻、杜邦线等
STM32F103C8T6最小系统板示意图:
蜂鸣器模块示意图:
本次使用的是有源蜂鸣器模块,高电平触发的。只要单片机的IO口输出高电平,就可以驱动蜂鸣器发出声音了。
LED模块:
STM32F103C8T6最小系统板PCB13默认接到自带的LED灯,无需外接 。
3.2 硬件连接
STM32引脚 | 连接模块 | 说明 |
---|---|---|
PA0 | 传感器AOUT | ADC1通道0 |
PA1 | 传感器DOUT | 数字输入 |
PC13 | LED | 报警指示灯 |
PB8 | 蜂鸣器 | 报警发声 |
PB6 | I2C1_SCL | OLED显示屏 |
PB7 | I2C1_SDA | OLED显示屏 |
5V | 传感器VCC | 电源 |
GND | 传感器GND | 共地 |
四、软件设计
4.1 开发环境配置
- 开发工具:Keil MDK-ARM
- 库版本:STM32F10x标准外设库
- 调试工具:ST-Link V2
4.2 关键代码实现
4.2.1 初始化代码
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_i2c.h"
#include "oled.h" // OLED显示屏驱动
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
// 配置PA0为模拟输入(AOUT)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置PA1为浮空输入(DOUT)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置PC13为推挽输出(LED)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// 配置PB8为推挽输出(蜂鸣器)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
// 使能ADC1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// ADC配置
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// 配置ADC通道
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
// 使能ADC1
ADC_Cmd(ADC1, ENABLE);
// ADC校准
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
// 启动ADC转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void I2C_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// 使能I2C和GPIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// 配置I2C引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// I2C配置
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000; // 100kHz
I2C_Init(I2C1, &I2C_InitStructure);
// 使能I2C
I2C_Cmd(I2C1, ENABLE);
}
GPIO配置函数(GPIO_Configuration
)功能描述:
该函数用于初始化STM32的GPIO引脚,配置各引脚的工作模式,包括:
模拟输入引脚(PA0) - 连接传感器的模拟输出(AOUT)
数字输入引脚(PA1) - 连接传感器的数字输出(DOUT)
LED控制引脚(PC13) - 推挽输出模式
蜂鸣器控制引脚(PB8) - 推挽输出模式
ADC配置函数(ADC_Configuration
)功能描述:
配置ADC1的工作参数,包括:
独立模式
单次转换模式
右对齐数据
通道0(PA0)的采样时间
I2C配置函数(I2C_Configuration
)功能描述:
配置I2C1接口用于连接OLED显示屏,包括:
GPIO引脚模式配置(PB6-SCL, PB7-SDA)
I2C工作频率(100kHz)
4.2.2 主程序逻辑
#define GAS_THRESHOLD 1500 // 气体浓度阈值(根据实际情况调整)
uint16_t Get_ADC_Value(void)
{
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待转换完成
return ADC_GetConversionValue(ADC1);
}
void Alarm_Control(FunctionalState state)
{
if(state == ENABLE)
{
GPIO_SetBits(GPIOC, GPIO_Pin_13); // LED亮
GPIO_SetBits(GPIOB, GPIO_Pin_8); // 蜂鸣器响
}
else
{
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // LED灭
GPIO_ResetBits(GPIOB, GPIO_Pin_8); // 蜂鸣器停
}
}
void Display_Gas_Value(uint16_t value)
{
char buffer[16];
sprintf(buffer, "Gas: %4d", value);
OLED_ShowString(0, 2, (uint8_t *)buffer);
if(value > GAS_THRESHOLD)
{
OLED_ShowString(0, 4, (uint8_t *)"Status: DANGER!");
}
else
{
OLED_ShowString(0, 4, (uint8_t *)"Status: Normal ");
}
}
int main(void)
{
uint16_t adc_value = 0;
uint8_t digital_state = 0;
// 初始化系统时钟
SystemInit();
// 外设初始化
GPIO_Configuration();
ADC_Configuration();
I2C_Configuration();
OLED_Init();
OLED_Clear();
OLED_ShowString(0, 0, (uint8_t *)"Gas Detector");
while(1)
{
// 读取模拟量
adc_value = Get_ADC_Value();
// 读取数字量
digital_state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1);
// 显示气体浓度值
Display_Gas_Value(adc_value);
// 气体检测逻辑
if((adc_value > GAS_THRESHOLD) || (digital_state == 0))
{
Alarm_Control(ENABLE); // 触发报警
}
else
{
Alarm_Control(DISABLE); // 关闭报警
}
// 延时500ms
Delay_ms(500);
}
}
气体浓度读取函数(Get_ADC_Value
):
等待ADC转换完成(EOC标志)
返回12位ADC转换结果(0-4095)
报警控制函数(Alarm_Control
):
统一控制LED和蜂鸣器状态
使用FunctionalState类型(ENABLE/DISABLE)提高可读性
数据显示函数(Display_Gas_Value
):
使用sprintf格式化显示内容
根据浓度阈值显示不同状态信息
需要提前实现OLED_ShowString函数(参考OLED四针驱动原码)
主循环:
同时监测模拟和数字输出
采用"或"逻辑判断报警条件
固定500ms的采样周期
五、系统调试与校准
5.1 预热处理
- MQ传感器需要预热1分钟才能稳定工作
- 初次通电时读数可能不准确,属于正常现象
5.2 阈值校准
- 在清洁空气中记录ADC值作为基准
- 使用已知浓度的测试气体调整阈值
- 可通过电位器调节DOUT的触发点
5.3 温度补偿
- MQ传感器受温度影响较大
- 可添加温度传感器进行补偿算法
5.4 软件滤波
采用简单的算术平均滤波,采样5次后取平均值,每次采样间隔10ms,可有效抑制随机干扰。
#define SAMPLE_NUM 5
uint16_t Get_Filtered_ADC_Value(void)
{
uint32_t sum = 0;
for(uint8_t i=0; i<SAMPLE_NUM; i++)
{
sum += Get_ADC_Value();
Delay_ms(10);
}
return sum/SAMPLE_NUM;
}
六、注意事项
6.1 电源要求
- MQ传感器需要5V供电
- 工作电流约150mA,确保电源足够
6.2 环境适应性
- 避免在高湿度环境下使用
- 防止传感器被灰尘或油污覆盖
6.3 使用寿命
- MQ传感器寿命通常为1-2年
- 需要定期校准和更换
6.4 数据准确性
- 本系统仅用于初步检测
- 关键场所应使用专业级气体检测设备
七、总结
本系统实现了基于STM32F103C8T6的MQ气体传感器检测方案,通过标准库开发保证了代码的可靠性和可移植性,适用于各种气体检测应用场景。