传感器 MQ-2型烟雾传感器
MQ-2型烟雾传感器原理图供电引脚,支持5V电压范围。接地引脚。输出一个高电平或低电平的数字信号,可以连接到微控制器的任何数字输入引脚。模块上有一个电位器RP4(可调电阻),可以旋转它来设定一个气体浓度的阈值。模块内部的比较器电路会持续将传感器信号与这个阈值进行比较。当气体浓度低于阈值时,DO输出高电平(例如5V或3.3V当气体浓度高于阈值时,DO输出低电平0V输出一个连续变化的模拟电压信号,必须
一、工作原理
核心原理是:其内部的金属氧化物半导体(SnO₂)在接触到可燃气体或烟雾时,其电导率会发生变化,通过测量这种变化来检测气体浓度。
1. 正常工作状态(在洁净空气中)
-
传感器通电后,其内部的加热丝会持续将SnO₂敏感材料加热到200-300℃的高温。
-
在高温和洁净空气中,氧气(O₂)会被吸附在SnO₂材料的表面。
-
这些吸附的氧分子会从SnO₂的晶格中“捕获”自由电子,形成带负电的氧离子(如 O₂⁻, O⁻)。
-
这个过程在SnO₂表面形成了一个“电子耗尽层”,使得其内部的自由电子更少,电阻值变得非常高。
2. 检测到目标气体时(如烟雾、液化气、氢气等)
-
当环境中存在可燃性气体或烟雾颗粒时,这些气体分子会扩散到传感器表面,并与之前吸附的氧离子发生氧化还原反应。
-
以丙烷(C₃H₈)为例:
C₃H₈ + 10O⁻ → 3CO₂ + 4H₂O + 10e⁻ -
注意反应式右边的 e⁻(电子)!这个反应将之前被氧“捕获”的电子释放回了SnO₂晶格中。
-
大量自由电子的回归,使得SnO₂材料的电导率急剧增加,宏观上就表现为其电阻值显著下降。
3. 信号输出
-
传感器通常以一个简单的电路(通常是分压电路)来将电阻的变化转换为电压信号的变化。
-
当电阻高时(洁净空气),输出电压低(或高,取决于电路设计)。
-
当电阻低时(有目标气体),输出电压高(或低)。
-
这个变化的电压信号就可以被单片机的模拟输入引脚读取,从而判断气体的浓度。
二、简单介绍

MQ-2型烟雾传感器原理图
<1>引脚介绍
VCC(1):供电引脚,支持5V电压范围。
GND(4):接地引脚。
DO(2) :输出一个高电平或低电平的数字信号,可以连接到微控制器的任何数字输入引脚。模块上有一个电位器RP4(可调电阻),可以旋转它来设定一个气体浓度的阈值。模块内部的比较器电路会持续将传感器信号与这个阈值进行比较。当气体浓度低于阈值时,DO 输出高电平(例如 5V 或 3.3V);当气体浓度高于阈值时,DO 输出低电平(0V)。
AO(3) :输出一个连续变化的模拟电压信号,必须连接到微控制器的模拟输入引脚。这个引脚直接来自于与传感器组成的分压电路。传感器的电阻变化会直接导致这个引脚的电压变化。在洁净空气中,输出电压较低(例如 0.1V - 0.3V);当气体浓度升高时,输出电压也会升高(可能接近 VCC)。
<2>电路分析
MQ-2型烟雾传感器属于二氧化锡(SnO2)半导体气敏材料,属于表面离子式N型半导体,当与烟雾接触时,就会引起表面导电率的变化。烟雾浓度越大导电率越大,输出电阻就会越低,则输出的模拟信号越大。电路中的比较器将模拟电压和参考电压进行比较,当模拟电压大于参考电压的时候输出低电平,指示灯亮起。
三、代码实现
实际上,MQ-2型烟雾传感器可以根据MQ-2传感器特性曲线参数来检测出不同的可燃气体,但这里只做简单使用,所以没将气体类型分出来。
<1>mq2.c
#include "mq2.h"
#include "adc.h"
#include "math.h"
#include "delay.h"
/**
* @brief MQ2传感器初始化
* @param None
* @retval None
*/
void MQ2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 初始化AO引脚(模拟输入)
RCC_APB2PeriphClockCmd(MQ2_AO_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = MQ2_AO_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(MQ2_AO_GPIO_PORT, &GPIO_InitStructure);
// 初始化DO引脚(数字输入)
RCC_APB2PeriphClockCmd(MQ2_DO_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = MQ2_DO_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(MQ2_DO_GPIO_PORT, &GPIO_InitStructure);
ADCx_Init();
}
/**
* @brief 读取MQ2 ADC值
* @param None
* @retval ADC转换值
*/
uint16_t MQ2_ADC_Read(void)
{
return ADC_GetValue(ADC_CHANNEL, ADC_SampleTime_55Cycles5);
}
/**
* @brief 读取MQ2数字输出状态
* @param None
* @retval 0:气体浓度低于阈值 1:气体浓度高于阈值
*/
uint8_t MQ2_ReadDigital(void)
{
return GPIO_ReadInputDataBit(MQ2_DO_GPIO_PORT, MQ2_DO_GPIO_PIN);
}
/**
* @brief 获取电压值
* @param None
* @retval 电压值(V)
*/
float MQ2_GetVoltage(void)
{
uint16_t adc_value = MQ2_ADC_Read();
return (adc_value * 3.3f / 4096.0f);
}
/**
* @brief 获取气体PPM浓度
* @param None
* @retval 估算的PPM值
*/
float MQ2_GetData_PPM(void)
{
float tempData = 0;
// 多次读取取平均值
for (uint8_t i = 0; i < MQ2_READ_TIMES; i++)
{
tempData += MQ2_ADC_Read();
delay_ms(5);
}
tempData /= MQ2_READ_TIMES;
// 计算电压值(这里使用5V参考电压,根据实际修改)
float Vol = (tempData * 5.0f / 4096.0f);
// 计算传感器电阻RS
// RL为负载电阻,为5KΩ,根据实际修改
float RS = (5.0f - Vol) / (Vol * 0.2f); // 0.2 = 1/RL = 1/5K
// R0为传感器在洁净空气中的电阻(需要校准)
float R0 = 6.64f; // 这个值需要通过校准获得
// 使用简化公式计算PPM
float ppm = pow(11.5428f * R0 / RS, 0.6549f);
return ppm;
}
<2>mq2.h
#ifndef __MQ2_H
#define __MQ2_H
#include "stm32f10x.h"
// MQ2引脚定义 根据实际连接修改
#define MQ2_AO_GPIO_CLK RCC_APB2Periph_GPIOA
#define MQ2_AO_GPIO_PORT GPIOA
#define MQ2_AO_GPIO_PIN GPIO_Pin_0
#define MQ2_DO_GPIO_CLK RCC_APB2Periph_GPIOA
#define MQ2_DO_GPIO_PORT GPIOA
#define MQ2_DO_GPIO_PIN GPIO_Pin_1
// ADC通道定义
#define ADC_CHANNEL ADC_Channel_0
// 读取次数
#define MQ2_READ_TIMES 10
// 函数声明
void MQ2_Init(void);
uint16_t MQ2_ADC_Read(void);
uint8_t MQ2_ReadDigital(void);
float MQ2_GetData_PPM(void);
float MQ2_GetVoltage(void);
#endif /* __MQ2_H */
<3>使用示例
#include "stm32f10x.h"
#include "mq2.h"
#include "stdio.h"
// 简单的延时函数
void Delay_ms(uint32_t nTime)
{
for(uint32_t i = 0; i < nTime; i++)
for(uint32_t j = 0; j < 8000; j++);
}
int main(void)
{
float ppm_value;
float voltage;
uint8_t digital_status;
// MQ2传感器初始化
MQ2_Init();
// 等待传感器预热(重要!)
Delay_ms(30000); // 预热30秒
while(1)
{
// 读取模拟值并计算PPM
ppm_value = MQ2_GetData_PPM();
// 读取电压值
voltage = MQ2_GetVoltage();
// 读取数字输出状态
digital_status = MQ2_ReadDigital();
// 简单的报警逻辑
if(digital_status == 0 || ppm_value > 100.0f) // 数字输出为0或PPM超过100
{
// 触发报警,例如点亮LED或启动蜂鸣器
}
else
{
// 关闭报警
}
Delay_ms(1000); // 每秒读取一次
}
}
更多推荐



所有评论(0)