基于STM32的有害气体检测系统设计(MQ-135传感器方案)

基于STM32的有害气体检测系统设计(MQ-135传感器方案)

一、系统概述

基于STM32F103C8T6(Cortex-M3,72MHz)和外围气体传感器,实现对空气中有害气体(如氨气、苯、甲醛、酒精等) 的检测。核心采用MQ-135传感器(广谱气体传感器),通过ADC采集模拟信号,结合软件标定算法转换为浓度值,支持超标报警和数据显示,适用于家庭空气质量监测、工业安全预警等场景。

二、硬件设计

2.1 核心组件

模块 型号/参数 功能说明
主控 STM32F103C8T6(64KB Flash,20KB RAM) ADC采集、数据处理、报警控制、显示驱动
气体传感器 MQ-135(广谱有害气体传感器) 检测NH₃、C₆H₆、CH₃OH、CO₂等,模拟输出(AO)+数字输出(DO)
温湿度补偿 DHT11(单总线,±2℃/±5%RH) 采集环境温湿度,修正气体浓度误差
显示模块 0.96寸OLED(I2C接口,SSD1306驱动) 显示气体浓度、温湿度、报警状态
报警模块 有源蜂鸣器(5V)+ LED(红色) 浓度超标时声光报警
电源 5V USB供电(LM7805稳压) 为传感器、STM32、外设供电

2.2 硬件连接

模块 引脚(STM32F103C8T6) 说明
MQ-135 AO → PA0(ADC1_IN0) 模拟输出(0~5V,需分压至3.3V)
  DO → PB0(GPIO输入) 数字输出(阈值报警,高电平有效)
  VCC → 5V 加热电源(需预热3~5分钟)
  GND → GND 共地
DHT11 DATA → PB1(单总线) 温湿度数据
OLED SCL → PB6(I2C1_SCL) I2C时钟
  SDA → PB7(I2C1_SDA) I2C数据
蜂鸣器 BUZZER → PB10(GPIO输出) 高电平触发
LED LED → PB11(GPIO输出) 高电平点亮

2.3 关键电路设计

2.3.1 MQ-135信号调理电路

MQ-135的AO输出为05V,STM32的ADC输入范围为03.3V,需通过分压电路降压:

2.3.2 传感器预热提示

MQ-135需预热3~5分钟才能稳定工作,可通过LED闪烁提示:预热期间LED以1Hz频率闪烁,稳定后常亮。

三、软件设计(STM32 HAL库)

3.1 开发环境

3.2 CubeMX配置(关键步骤)

  1. 时钟配置:HSE 8MHz,系统时钟72MHz,APB2时钟72MHz(ADC时钟≤14MHz,分频系数6→12MHz)。

  2. ADC配置

    • 使能ADC1,通道0(PA0),单次转换模式,12位分辨率,右对齐。
  3. I2C配置:I2C1(PB6-SCL,PB7-SDA),标准模式(100kHz)。

  4. GPIO配置

    • PB0(MQ-135 DO):输入模式(上拉);
    • PB1(DHT11 DATA):开漏输出(需外部上拉10kΩ);
    • PB10(蜂鸣器)、PB11(LED):推挽输出。
  5. 生成代码:选择“Generate peripheral initialization as a pair of .c/.h files per peripheral”。

3.3 核心代码实现

3.3.1 ADC采集与浓度计算

MQ-135的电阻值随气体浓度变化,通过分压电路计算电阻,再查表转换为浓度(以CO₂为例):

#include "adc.h"
#include "dht11.h"
#include "oled.h"
#include "gpio.h"

// MQ-135参数(需根据datasheet校准)
#define RL 10.0f       // 负载电阻(kΩ,模块上通常为10kΩ)
#define R0 6.0f        // 洁净空气中电阻(kΩ,需实际校准)
#define VCC 5.0f       // 传感器供电电压
#define ADC_REF 3.3f    // ADC参考电压
#define ADC_RES 4095.0f // 12位ADC分辨率

// 计算气体浓度(以CO₂为例,单位ppm)
float calculate_gas_concentration(uint16_t adc_value) {
    // 1. ADC值转电压(分压后)
    float v_out = (adc_value * ADC_REF) / ADC_RES;  // 0~3.3V
    // 2. 计算传感器电压(反向分压)
    float v_sensor = v_out * (1 + 2.2/1.0);  // 分压比1:2.2,反向计算
    // 3. 计算传感器电阻Rs
    float rs = (VCC - v_sensor) * RL / v_sensor;  // Rs=(VCC-Vo)*RL/Vo
    // 4. 计算Rs/R0比值(R0为洁净空气电阻,需校准)
    float ratio = rs / R0;
    // 5. 查表或公式计算CO₂浓度(经验公式:y=1000*(ratio)^-2.5)
    float ppm = 1000.0f * powf(ratio, -2.5f);  // 示例公式,需实际校准
    return ppm;
}

3.3.2 DHT11温湿度读取

// DHT11读取函数(单总线协议)
uint8_t DHT11_Read(float *temp, float *humi) {
    uint8_t data[5] = {0};
    // 1. 主机发送起始信号(拉低18ms,再拉高20~40us)
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_Delay(18);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
    delay_us(30);  // 需实现微秒延时函数
    
    // 2. 等待DHT11响应(拉低80us,再拉高80us)
    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) != GPIO_PIN_RESET) return 1;
    delay_us(80);
    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) != GPIO_PIN_SET) return 1;
    delay_us(80);
    
    // 3. 读取40位数据(5字节:湿度整数+小数+温度整数+小数+校验和)
    for (uint8_t i=0; i<40; i++) {
        while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_RESET);  // 等待高电平
        delay_us(30);
        if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_SET) {
            data[i/8] |= (1 << (7 - i%8));  // 高电平>30us为1
        }
        while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_SET);  // 等待低电平
    }
    
    // 4. 校验和验证
    if (data[4] != (data[0] + data[1] + data[2] + data[3])) return 1;
    *humi = data[0] + data[1]/10.0f;  // 湿度(整数部分+小数部分)
    *temp = data[2] + data[3]/10.0f;  // 温度(整数部分+小数部分)
    return 0;
}

3.3.3 主程序逻辑

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_ADC1_Init();
    MX_I2C1_Init();
    
    OLED_Init();  // OLED初始化
    OLED_Clear();
    OLED_ShowString(0, 0, "Gas Detector", 16);
    
    uint16_t adc_value;
    float gas_ppm, temp, humi;
    uint8_t dht11_ret;
    
    // 传感器预热(3分钟)
    for (uint8_t i=0; i<180; i++) {  // 3分钟=180秒
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_11);  // LED闪烁
        HAL_Delay(1000);
    }
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);  // 预热完成,LED常亮
    
    while (1) {
        // 1. 采集MQ-135模拟信号
        HAL_ADC_Start(&hadc1);
        HAL_ADC_PollForConversion(&hadc1, 10);
        adc_value = HAL_ADC_GetValue(&hadc1);
        HAL_ADC_Stop(&hadc1);
        gas_ppm = calculate_gas_concentration(adc_value);
        
        // 2. 采集DHT11温湿度
        dht11_ret = DHT11_Read(&temp, &humi);
        
        // 3. 显示数据
        OLED_ShowNum(0, 2, (uint16_t)gas_ppm, 4, 16);  // 显示浓度(ppm)
        OLED_ShowString(40, 2, "ppm", 16);
        if (dht11_ret == 0) {
            OLED_ShowNum(0, 4, (uint16_t)temp, 2, 16);  // 温度
            OLED_ShowString(20, 4, "C", 16);
            OLED_ShowNum(40, 4, (uint16_t)humi, 2, 16);  // 湿度
            OLED_ShowString(60, 4, "%", 16);
        }
        
        // 4. 超标报警(CO₂浓度>1000ppm触发)
        if (gas_ppm > 1000.0f) {
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);  // 蜂鸣器响
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);  // LED亮
        } else {
            HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
        }
        
        HAL_Delay(1000);  // 1秒刷新一次
    }
}

参考代码 基于STM32的外围电路开发检测空气中的有害气体 www.youwenfan.com/contentcss/56931.html

四、关键问题与解决方案

4.1 传感器校准

4.2 温湿度补偿

4.3 电源干扰

五、测试与验证

  1. 硬件连接:按2.2节连接各模块,确保传感器预热3分钟。

  2. 功能测试

    • 用酒精棉球靠近传感器,观察浓度值是否上升,超标时声光报警是否触发;
    • 用吹风机改变环境温湿度,验证DHT11数据是否正确。
  3. 精度验证:对比商用气体检测仪,调整校准参数(R0、公式系数)提高精度。

六、总结

本系统基于STM32和MQ-135传感器实现了有害气体检测,核心是ADC信号采集、浓度换算算法和温湿度补偿。通过模块化设计,可扩展支持其他气体传感器(如MQ-2检测可燃气体、MQ-7检测CO),适用于家庭、工业等场景的空气安全监测。

专注于matlab/simulink,电子电路,编程