GD32F407VE天空星开发板的MQ135的空气质量检测
GD32F407VE天空星开发板的MQ135的空气质量检测
一、MQ135传感器深度解析
1.1 传感器概述与应用场景
MQ135是一款高性能的半导体气体传感器,专门设计用于检测空气中的多种污染气体。这款传感器采用二氧化锡(SnO₂)作为核心气敏材料,在清洁空气中具有较低的电导率,而当环境中存在污染气体时,其电导率会随着气体浓度的增加而显著增大。
典型应用场景包括:
- 家庭环境空气质量监测系统
- 工业现场有害气体泄漏报警装置
- 智能家居中的通风控制系统
- 实验室环境安全监测
- 公共场所空气质量评估
1.2 技术特性详解


MQ135传感器具备多项优秀的技术特性:
电气参数:
- 工作电压:5V DC,需稳定供电
- 加热电阻:29Ω±3Ω(室温条件下)
- 加热功耗:≤950mW,能效较高
- 负载电阻:1KΩ,可根据应用调整
环境适应性:
- 工作温度范围:-10℃~+50℃
- 预热时间:建议不少于5分钟
- 长期稳定性:在标准条件下表现良好
检测性能:
- 检测气体种类:氨气、硫化物、苯系蒸气等多种污染气体
- 检测浓度范围:10~1000ppm
- 灵敏度:对多种有害气体具有良好的响应特性
二、硬件系统设计与连接
2.1 模块硬件构成
MQ135空气检测模块是一个完整的检测解决方案,包含以下核心组件:
传感器本体:
- MQ-135气体传感器头
- 金属防护罩,确保气流畅通同时提供物理保护
信号处理电路:
- LM393ADR电压比较器,提供数字信号输出
- 10KΩ可调电位器,用于设定检测阈值
- 双LED状态指示系统
- LED1:DO输出状态指示
- LED2:电源状态指示
接口定义:
- VCC:5V电源输入,需稳定可靠
- GND:电源地线,确保良好接地
- DO:数字信号输出端,TTL电平 如果超出你设定的预警的数值,就会变成高电平
- AO:模拟信号输出端,0-3.3V电压范围
2.2 工作原理深度分析

气体检测机制:
当传感器暴露在污染气体环境中时,气体分子与二氧化锡材料发生化学反应,导致材料电导率发生变化。这种变化与气体浓度呈正相关关系,从而实现了气体浓度的检测。
信号输出原理:
- 数字输出(DO):通过电压比较器实现。当气体浓度超过设定阈值时,比较器输出低电平,触发LED1点亮
- 模拟输出(AO):直接反映传感器当前的电阻状态,通过ADC采集可以获得连续的浓度信息
阈值调节机制:
通过旋转可调电位器,可以改变比较器的参考电压,从而调整触发阈值。顺时针旋转提高阈值,逆时针旋转降低阈值。
三、软件系统设计与实现
3.1 系统初始化配置
bsp_gpio_mq135.c的代码
#include "bsp_gpio_mq135.h"//初始化的代码我AO的引脚写在adc里面就初始化了,
//DO的引脚可以接在任意的有个io口上,检测引脚的电平就可以触发一些代码void mq135_init(){printf("=mq135_init===");//可以在这初始化DO引脚
}
/*_BSP_GPIO_MQ135_H */
/*** @brief 检测空气检测传感器情况* @param GPIOx:x 可以是 A,B,C等* @param GPIO_Pin:待操作的pin脚号* @retval SET(污染气体浓度未超过阈值)、RESET(污染气体浓度超过阈值)*/
FlagStatus MQ135_Scan(){// GD32使用gpio_input_bit_get读取指定GPIO引脚的输入状态// 返回值为SET(1)或RESET(0),表示引脚的逻辑电平状态if(gpio_input_bit_get(MQ135_DO_PIN) == RESET){return RESET;}else{return SET;}// 或者简化为一行:// return gpio_input_bit_get(GPIOx, GPIO_Pin);
}
bsp_gpio_mq135.h代码:
#ifndef __BSP_GPIO_MQ135_H
#define __BSP_GPIO_MQ135_H
#include "gpio_cfg.h"//这个是我的初始化的函数,可以写下面的这个
#include "gd32f4xx.h"
//任意的io口引脚
#define MQ135_DO_RCU RCU_GPIOC
#define MQ135_DO_PIN GPIOC, GPIO_PIN_2
//adc采样的引脚
#define MQ135_AO_RCU RCU_GPIOC
#define MQ135_AO_PIN GPIOC, GPIO_PIN_1void mq135_init();
//判断do的引脚是否触发
FlagStatus MQ135_Scan();#endif /* __BSP_GPIO_MQ135_H */
3.2 数字信号处理模块
// DO状态监测函数
FlagStatus MQ135_Scan()
{if(gpio_input_bit_get(MQ135_DO_PIN) == SET){// 气体浓度超过阈值printf("⚠️ 警告:检测到空气质量超标!\r\n");printf("当前时间:%s\r\n", get_timestamp());return SET;}else {// 气体浓度在安全范围内printf("✅ 空气质量正常\r\n");return RESET;}
}
3.3 模拟信号采集与处理
app_mq135.c代码
#include "App.h"
#include "app_mq135.h"
#include "bsp_gpio_mq135.h"
#include <math.h>
#include "ADC0.h"/*** @brief MQ135_ADC 任务初始化* @param mq135_task_cycle: 任务轮询周期 单位ms(可修改系统节拍定时器)* @retval 无*/
void MQ135_TaskInit(){printf("==MQ135_TaskInit==");//GPIO_analog(MQ135_AO_RCU, MQ135_AO_PIN); // 模拟输入}/*** @brief 求ppm* @param adc_value : ADC读取的原始值(0~4095)* @retval ppm* @note* 根据手册提供的各污染气体灵敏度 拟合成幂函数* 需要根据Rs/R0推算ppm,所以拟合函数时,x轴为Rs/R0,y轴为ppm,推导出y=ax^b* 图表没有每个点对应具体数值只能大致估计,所以测量值存在误差,想要完全精确请根据环境做多次标定*/
float MQ135_Get_PPM(uint16_t adc_value)
{float vrl = 0; /* AO输出的模拟电压 */float Rs; /* 当前传感器电阻 */float ppm = 0; /* 污染物平均浓度 */ /* 读取AO输出电压 */vrl = (float)adc_value / 4095 * VC;/* 换算Rs电阻 */Rs = (float)(VC - vrl) * RL / vrl;//根据数据手册图表,Rs/R0的范围为0.1~1000,所以需要取log10(Rs/R0)来进行拟合float Rs0 = Rs/R0; /* Rs/R0 *//* y=ax^b x为Rs/R0,ab的取值根据数据手册图表自行拟合成幂函数 */ppm = A*pow(Rs/R0,B) ;return ppm;
}
/*** @brief MQ135_ADC 任务 */
void MQ135_Task(void)
{float adc_convertedvalue[20] = {0};//转化后的源始值的计算值//将ADC原始值转换为电压值uint16_t value = ADC0_get(1);adc_convertedvalue[0] = value * 3.3/4095;printf("adc_convertedvalue = %.2f",adc_convertedvalue[0]);printf("\r\n/*");//打印分割线for(uint32_t adc_task_i_temp = 0;adc_task_i_temp<80;adc_task_i_temp++){printf("*");}printf("*/");printf("\r\n 当前的值:");printf("\r\n 空气质量检测模块: %f V(0x%04X)",adc_convertedvalue[0],value);printf("\r\n");/* 拟合函数换算出ppm */float ppm = MQ135_Get_PPM(value);if(ppm<10){printf("综合污染气体平均浓度未达到检测范围\r\n");}else if(ppm>1000){printf("综合污染气体平均浓度超过检测范围\r\n");}else{printf("综合污染气体的平均浓度:%fppm\r\n",ppm);} printf("/*");for(uint32_t adc_task_i_temp = 0;adc_task_i_temp<80;adc_task_i_temp++){printf("*");}printf("*/");
}
app_mq135.h代码
#ifndef __APP_MQ135_H
#define __APP_MQ135_H#include "gpio_cfg.h"//或#include "stdint.h"#define RL 1 /* 根据硬件原理图可知:RL = 1k */
#define R0 2 /* MQ135在洁净空气中的阻值,官方数据手册没有给出,这是实验测试得出,想要准确请多次测试 */
#define VC 5.0 /* MQ135供电电压,根据实际供电修改,默认接5V */
#define A 4.17 /* y=ax^b 的 a */
#define B -2.28 /* y=ax^b 的 b */#define MQ135_DO_RCU RCU_GPIOC
#define MQ135_DO_PIN GPIOC, GPIO_PIN_2#define MQ135_AO_RCU RCU_GPIOC
#define MQ135_AO_PIN GPIOC, GPIO_PIN_1typedef struct
{uint32_t cycle;uint32_t timer;uint8_t flag;
}MQ135_TaskInfo;extern MQ135_TaskInfo mq135_task;float MQ135_Ge_PPM(uint16_t adc_value);void MQ135_TaskReset(void);
void MQ135_TaskInit();
void MQ135_Task(void);#endif /* __APP_MQ135_H */
四、浓度换算算法与校准
4.1 理论基础与算法实现
气体浓度换算基于传感器的灵敏度特性曲线,采用幂函数拟合的方法:
/*** @brief 求ppm* @param adc_value : ADC读取的原始值(0~4095)* @retval ppm* @note* 根据手册提供的各污染气体灵敏度 拟合成幂函数* 需要根据Rs/R0推算ppm,所以拟合函数时,x轴为Rs/R0,y轴为ppm,推导出y=ax^b* 图表没有每个点对应具体数值只能大致估计,所以测量值存在误差,想要完全精确请根据环境做多次标定*/
float MQ135_Get_PPM(uint16_t adc_value)
{float vrl = 0; /* AO输出的模拟电压 */float Rs; /* 当前传感器电阻 */float ppm = 0; /* 污染物平均浓度 */ /* 读取AO输出电压 */vrl = (float)adc_value / 4095 * VC;/* 换算Rs电阻 */Rs = (float)(VC - vrl) * RL / vrl;//根据数据手册图表,Rs/R0的范围为0.1~1000,所以需要取log10(Rs/R0)来进行拟合float Rs0 = Rs/R0; /* Rs/R0 *//* y=ax^b x为Rs/R0,ab的取值根据数据手册图表自行拟合成幂函数 */ppm = A*pow(Rs/R0,B) ;return ppm;
}
五、完整应用系统实现
5.1 主程序框架
// 系统状态结构体
typedef struct {float current_concentration;float concentration_threshold;bool alarm_status;uint32_t sample_count;char air_quality_level[20];
} AirQuality_Status_t;// 主监控循环
void AirQuality_Monitor_Loop(void)
{AirQuality_Status_t system_status = {0};system_status.concentration_threshold = 100.0f; // 设置默认阈值printf(" MQ135空气质量监测系统启动\r\n");printf("=================================\r\n");while (1) {// 读取当前气体浓度system_status.current_concentration = Get_Gas_Concentration();system_status.sample_count++;// 更新空气质量等级Update_Air_Quality_Level(&system_status);// 检查数字输出状态Monitor_DO_Output();// 显示当前状态信息Display_System_Status(&system_status);// 数据记录Log_Sensor_Data(&system_status);// 等待下一次采样HAL_Delay(2000); // 2秒采样间隔}
}// 空气质量等级评估
void Update_Air_Quality_Level(AirQuality_Status_t *status)
{float ppm = status->current_concentration;if (ppm < 50.0f) {strcpy(status->air_quality_level, "优");} else if (ppm < 100.0f) {strcpy(status->air_quality_level, "良");} else if (ppm < 200.0f) {strcpy(status->air_quality_level, "轻度污染");} else if (ppm < 300.0f) {strcpy(status->air_quality_level, "中度污染");} else {strcpy(status->air_quality_level, "重度污染");}
}
5.2 数据显示与记录
// 系统状态显示
void Display_System_Status(AirQuality_Status_t *status)
{printf("\r\n 空气质量监测报告\r\n");printf("----------------------------\r\n");printf("采样次数:%lu\r\n", status->sample_count);printf("当前浓度:%.2f ppm\r\n", status->current_concentration);printf("空气质量:%s\r\n", status->air_quality_level);printf("报警状态:%s\r\n", status->alarm_status ? "触发" : "正常");printf("----------------------------\r\n");
}// 数据记录功能
void Log_Sensor_Data(AirQuality_Status_t *status)
{// 在实际应用中,这里可以将数据保存到SD卡或发送到服务器FILE *log_file = fopen("air_quality_log.csv", "a");if (log_file != NULL) {fprintf(log_file, "%lu,%.2f,%s,%d\r\n", (unsigned long)time(NULL),status->current_concentration,status->air_quality_level,status->alarm_status);fclose(log_file);}
}
MQ135空气质量检测传感器为环境监测提供了一个成本效益高、可靠性好的解决方案。通过本文介绍的硬件连接方法、软件实现方案以及数据处理算法,开发者可以快速构建一个功能完整的空气质量监测系统。
