☰
MQ气体传感器ADC值到PPM浓度完整换算指南
2026/9/25 7:20:16 网站建设 项目流程

做气体检测项目的时候,MQ系列传感器几乎是入场券级别的存在:便宜、皮实、常见气体基本全覆盖。但很多人跟我抱怨过同一件事——明明照着网上的例程把ADC读出来了,也把数字换算成了电压,结果用标准公式一算,浓度还是对不上,有时候甚至差出一个数量级。问题基本都出在同一个地方:少了一条从ADC原始值到PPM浓度的完整换算链。

这篇就把这条链路彻底捋清楚,硬件分压怎么设计、ADC采样怎么采得准、电压怎么还原成传感器电阻、Rs/R0怎么算,最后怎么利用数据手册上的曲线得到PPM。文章会用MQ-2测甲烷/烟雾的完整计算作为实例,同时把ESP32、STM32、GD32等常见MCU在ADC采样上的差异也一并讲了。适合正在用MQ-2、MQ-5、MQ-7、MQ-135做环境监测、家庭安防、智能家居项目的开发者,也适合那些想搞明白“传感器输出到底怎么标定”的新手。你会拿到可以直接抄走用的C语言换算函数和排查清单,而不是一堆看似高深但落不了地的理论。

1. 换算链路整体拆解:从ADC整数到PPM的每一步

1.1 为什么很多人都卡在“最后一公里”

MQ系列传感器的核心是一个氧化锡半导体气敏电阻,它在还原性气体中电导率会升高,表现出来就是电阻Rs下降。这个Rs会随着被测气体浓度变化而改变,但它本身不是电信号,我们必须通过一个分压电路把电阻变化转成电压变化,再通过单片机的ADC把电压变成数字量。

问题在于,很多人拿到一个MQ模块,看到模块上有AO模拟输出引脚,就直接把这个电压接到MCU,然后想当然地套一个公式,试图让“ADC值”一秒变成“PPM值”。但完整的换算是一长串链条,任何一个环节和实际硬件不匹配,结果都会偏。

我见过非常经典的错误:模块用5V供电,模块内部的下拉电阻和传感器构成分压,空气里的输出电压最高能到接近5V;但MCU的ADC参考电压是3.3V,结果ADC一直被削顶,读数始终是4095,这时候再怎么拟合也白搭。还有人换了一个传感器模块,没有重新校准R0,直接用旧R0套新传感器的曲线,读数偏到天上去。你做任何软件算法前,先把这个链条在纸上理顺。

1.2 换算链路上的角色地图:ADC原始值、电压、Rs、R0、PPM

用文字把这个链路画清楚,大概是这样:

  • ADC原始值(ADC raw):MCU的ADC寄存器里读出来的整数,0~4095(12位)或0~1023(10位)。它只代表“输入引脚的电压相对于ADC参考电压的比例”,不代表任何气体浓度。
  • Vout_adc(采样电压):把ADC原始值按参考电压还原出来的引脚电压,没有经过任何传感器电路修正。
  • Vout_sensor(实际输出电压):如果分了压、加了运放、做了衰减放大,要把Vout_adc再还原到传感器实际输出电压。很多人漏掉这一步。
  • Rs(传感器内阻):通过分压电路反推出来的气敏电阻当前阻值。气体浓度越高,Rs越小。
  • R0(基准电阻):同一个传感器在标准洁净空气中的Rs值。它是个体特征,不同批次都不同。
  • Rs/R0:归一化相对电阻。数据手册上所有浓度曲线,画的都是“Rs/R0与PPM”的关系,不是“Rs与PPM”的直接关系。
  • PPM:最终浓度,体积浓度单位(parts per million,百万分之一体积比),也是大家最终要的结果。

很多教程把“ADC值”直接映射到“PPM”,实际上是默认了电压、分压、R0、曲线拟合都已经被某个成品模块替你做好了。而正经的工程环境,模块很可能只是裸传感器焊在自己画的板上,这时候必须自己走完整条链路。

1.3 为什么统一用Rs/R0,而不是直接用Rs

这点我多说两句,因为它是很多人换算失败的根源。MQ传感器的数据手册,比如MQ-2的手册里,会给出“Rs/R0 与 气体浓度”的双对数坐标曲线。注意横纵坐标都是对数刻度,为什么?因为这个传感器在几个数量级浓度范围内,Rs/R0和浓度近似满足幂律关系,取完对数就是一条直线。

为什么手册不直接给Rs与浓度的曲线?因为同一个型号的传感器,不同个体在洁净空气中的电阻R0离散性很大。同一批MQ-2,R0可能是5kΩ,也可能是20kΩ,直接给Rs没意义。先测出当前传感器的R0,再看Rs相对于R0的变化,才能在同一个坐标系下对照手册曲线。这就是“换算链”的核心思想:不是把ADC值变成PPM,而是把“当前电阻相对基准电阻的比值”变成PPM。所有校准、拟合、查表,都围绕Rs/R0展开。

2. 硬件先过关:分压电路、ADC参考与采样设计

2.1 经典分压电路与上下拉电阻选型

MQ传感器通常有6个引脚,其中H-H是加热极,A-A和B-B是测量极。测量极的A、B之间就是一个可变电阻,所以典型接法是把A接电源,B经过一个负载电阻RL接到GND,从A、B两端取电压。实际上就是把传感器电阻和RL构成一个分压器。

RL的选择很关键,直接影响ADC采样的有效范围。数据手册一般会给一个推荐RL值,比如MQ-2推荐5kΩ,MQ-135推荐10kΩ。这个值的意义在于,让传感器的电阻落在中间阻值时,分压点输出电压不至于贴近0V或者电源电压,保证曲线变化灵敏。

我自己做项目时有个经验:如果没有手册可以用,让RL等于传感器在典型浓度下的Rs附近,分压灵敏度最高。比如MQ-2在洁净空气里Rs大约是10kΩ到20kΩ,而目标气体浓度较高时Rs会降到2kΩ左右,这时候RL选5kΩ比较居中,输出电压变化范围能覆盖ADC量程相当大的一段。RL选得太大,输出经常饱和在接近电源电压;选得太小,输出又长期贴近0V,浓度变化引起的电压变化太小,分辨率不够。

这还没完,MQ传感器输出的等效内阻偏高,如果MCU的ADC输入阻抗不够高,直接连接会造成分压比例被拉偏。STM32系列的ADC输入阻抗大约是几十kΩ级别,单片机内部采样电容充电时会从外部吸取电流,如果源阻抗太高,采样值会偏低。稳妥做法是在ADC输入到地之间并联一个0.1uF电容,同时尽量把采样时间调长。后面软件滤波部分我再细说。

2.2 ADC参考电压与量程:为什么5V模块不能直接接3.3V ADC

实际接到MCU之前,你要算清楚“最大输出电压会不会超过ADC参考电压”。典型场景,模块用5V供电,内部RL接5V,那么洁净空气下输出可能接近5V,这直接超过3.3V单片机的耐压和ADC量程。

处理方法通常有三种:

  • 给模块单独用3.3V供电,输出范围整体压缩到0~3.3V以内,但传感器加热电压也随之降低,很多MQ传感器加热电压需要5V才能保持稳定温度,降低电压会导致基线漂移严重,不建议这么干。
  • 用电阻分压把0~5V衰减到0~3.3V,比如串一个10kΩ、并一个20kΩ,或者用运放跟随+分压。不过分压会压缩测量分辨率,需要计算好。
  • 使用ADC内部的增益或衰减配置。比如ESP32的ADC2有11dB衰减档,可以把输入范围扩大到约0~3.9V,但衰减也带来额外的非线性误差,后面要校准。

如果用的是GD32H7系列,它带了硬件过采样和模拟看门狗,还支持ADC的硬件滤波功能,能在硬件层面做抽取滤波,减少软件负担。这种硬件滤波器本质上就是多次采样取平均,关键是它不影响你用软件再做一次中值滤波,两层叠加也不会让响应变慢太多。硬件滤波省的是CPU时间,不是给你省掉“算一遍链路”的功夫。

2.3 采样噪声、采样时间与硬件滤波

ADC读数跳,是很多人第一个会遇到的坑。MQ传感器本身响应就慢,一波浓度变化要几秒到几十秒才能稳定,所以不建议用“单次采样”结果去做气体浓度判断。

常见软件策略有三种:多次采样取平均、中值滤波、滑动窗口。对于MQ来说,因为可能偶尔有尖峰干扰,单纯平均会被尖峰拉偏;单纯中值又会丢掉真实浓度变化的趋势。我惯用组合:先做限幅滤波,把超过上一次值的某个百分比变化视为野值丢掉,再做滑动平均。

GD32H7的硬件滤波则是在ADC触发后连续采样多次,内部累加再右移,输出一个均值。这种抽取滤波能有效抑制高频噪声,但要理解它会影响有效采样率。如果你后续还要做快速响应控制,滤波深度别开太大,否则气体已经变了,读数还赖在旧值上。

ESP32这边则是另一番光景。ESP32的ADC存在两个老毛病:第一是模块出厂时校准参数每片不同,低电量或低温情况下读数漂移明显;第二是无衰减时量程只有0~1.1V左右,衰减后量程变大,但低端非线性比较严重。要想把ADC值可靠映射成电压,建议用esp_adc_cal或者新的oneshot接口做校准,并且做多点标定,不要直接用线性比例。如果你的项目对气体浓度精度有要求,ESP32的板载ADC只能说“够用”,最好外挂一颗独立的12位ADC芯片,比如MCP3201,或者用I2C接口的ADS1115之类的,省心很多。

2.4 不同MCU的ADC采样策略差异

这块我把常见MCU的情况摆一起说:

MCU/平台ADC位数参考电压特点关键注意点
STM3212位默认VDDA,可用内部VREFINT校准采样时间要调到大于源阻抗充电时间,推荐开启内部基准通道做实时补偿
GD32H712/14位可选支持硬件过采样和模拟看门狗硬件滤波深度可调,能减轻CPU占用,注意抽取后有效采样率下降
ESP3212位衰减档不同,量程不同,校准参数存于片内需要调用校准API,温度飘移大,做气体检测建议用外部ADC
经典805110位参考电压一般是电源电压精度有限,尽量让RL分压落在中间段

STM32做气体采样,很多项目只开了单通道单次采样,其实浪费了它内置的多重采样功能。你可以用定时器触发ADC,比如100ms触发一次,每次连续采16次取平均,然后把结果通过DMA搬到内存,CPU完全不用干预。对于MQ这种慢响应传感器,100ms的采样周期已经非常足够,CPU还可以去处理显示、联网、报警逻辑。

还有一点,STM32的ADC会受供电噪声影响。如果LDO输出纹波大,ADC参考也会跟着抖,读数自然就跳。可以在VDDA和VREF+引脚多并几个去耦电容,最好用低ESR的陶瓷电容,布局尽量靠近引脚。这些小地方的改善,往往比在软件里反复滤波更有效。

3. 软件换算第一段:ADC读取、滤波与电压还原

3.1 ADC原始值到电压域的转换

ADC原始值与电压的关系,在理想情况下是一次线性关系:

V_out_adc = (ADC_raw / ADC_max) * V_ref

其中ADC_max与位数有关:10位ADC是1023,12位ADC是4095。V_ref是实际参考电压,不是名义值。很多开发板用3.3V稳压供电,但实际可能只有3.28V,如果直接按3.3V换算,会产生约0.6%的固定误差。对气体浓度来说这个误差不算大,但既然要搭完整换算链,建议实测一下V_ref,用万用表量出MCU的VREF引脚电压再代入计算,这样后面所有值才准确。

如果使用了分压衰减或运放电路,还要继续还原:

V_out_sensor = V_out_adc / K

K是衰减或放大系数。比如前端做了0.66的分压,那么K=0.66。这一步常常被忽略,一旦忽略,后续算出的Rs就会成比例地偏大。

3.2 滤波算法的选择与C语言实现

我直接给一份我自己项目里常用的小代码,限幅加滑动平均,非常适合MQ这类低频、有尖峰干扰的传感器信号。

#define FILTER_WINDOW_SIZE 8 #define LIMIT_PERCENT 20 // 限幅百分比 static float buf[FILTER_WINDOW_SIZE]; static uint8_t idx = 0; static float last_valid = 0; float gas_adc_filter(float new_value) { // 1. 限幅:变化幅度太大视为干扰,沿用上次有效值 if (last_valid > 0) { float delta = (new_value - last_valid) / last_valid * 100.0f; if (delta < -LIMIT_PERCENT || delta > LIMIT_PERCENT) { return last_valid; } } // 2. 滑动平均 buf[idx++] = new_value; if (idx >= FILTER_WINDOW_SIZE) idx = 0; float sum = 0; for (int i = 0; i < FILTER_WINDOW_SIZE; i++) { sum += buf[i]; } last_valid = sum / FILTER_WINDOW_SIZE; return last_valid; }

使用这套滤波时,采样周期要和窗口大小配合。MQ传感器响应时间一般是10秒到60秒,所以采样周期设在100ms到500ms都行,窗口取8到16个点完全够用。窗口开得过大,滤波平滑但响应滞后明显;窗口太小又压不住尖峰。实际调试时可以在串口打印未滤波和滤波后的值,边吹气体边观察,选一个目标浓度变化时能跟上、静止时跳动在2%以内的窗口参数。

3.3 从电压还原Rs

拿到V_out_sensor之后,就要根据分压电路反推传感器电阻Rs。

典型电路里,传感器一端与电源Vcc相连,另一端经RL接地,从两个电阻的连接点取电压。那么分压关系:

V_out_sensor = Vcc * RL / (Rs + RL)

反推:

Rs = RL * (Vcc - V_out_sensor) / V_out_sensor

注意这里的Vcc是传感器电路的实际供电电压,不是MCU的3.3V。如果传感器由5V供电,Vcc就是5V,V_out_sensor则是你实际采回来的电压(无论是否做了衰减,都要先还原)。

很多人在这一步会犯一个低级错误:直接把MCU的3.3V代入Vcc,导致Rs算出来偏小很多,后面的浓度自然就错了。所以写代码时一定把Vcc、RL作为配置项,并且在调试时用万用表实测一下Vcc和RL的真实值。

3.4 R0校准与零点判定

R0的定义是传感器在标准洁净空气中的Rs。校准方法很简单:把传感器放在洁净空气中(室外通风处,或打开门窗的房间,但要避开香水、酒精、油烟),按上面公式算出此时的Rs,作为R0记录下来。

实际项目里,我一般不是只采一次,而是连续采30到60秒,取平均值作为R0,可以消除传感器短时波动。如果项目有EEPROM或Flash,把R0存下来,下次开机直接读取,不用每次重新校准。但要注意,传感器老化后R0会缓慢漂移,建议隔几个月重新校准一次。

还有个细节:MQ传感器刚上电时阻值不稳定,前几分钟基线会漂移。有人上电后立刻测R0,测出来的值比稳定后差很多。所以校准和正式测量都应该在预热完成后进行。预热时间看手册,一般5分钟以上,保守一点预热10分钟。如果你在程序里做了自动校准功能,一定要加一个“预热倒计时”逻辑,倒计时结束才允许校准,否则就是自欺欺人。

4. 曲线拟合:从Rs/R0到PPM的数学内核

4.1 为什么手册曲线画在双对数坐标上

说到曲线拟合,先搞清楚为什么用对数坐标。MQ传感器的响应近似满足幂律关系:

Rs/R0 = a * (PPM)^(-b)

或反过来:

PPM = A * (Rs/R0)^B

这里的A、B是气体种类相关的常数。等号两边取对数之后就是直线:

log(PPM) = B * log(Rs/R0) + log(A)

这就是为什么数据手册的曲线在双对数坐标下接近直线。双对数纸上量两个点,就能算出斜率,得到一整套拟合参数。

这种方法最大的好处是单点校准就能用:测出R0,按目标气体的A、B系数直接算。缺点是它只能描述传感器在某个有限浓度区间内的行为,超出区间误差会明显增大。比如MQ-2对甲烷的曲线,手册给出的有效范围大约是200~10000ppm,你在50ppm下用拟合公式算,结果只能看趋势,不能当定量数据。

4.2 手动从手册曲线读取A和B

具体怎么把手册曲线变成可用的A、B?拿MQ-2手册的甲烷曲线举例。

在双对数坐标纸上找到这条直线,读出两个点的坐标(Rs/R0, PPM)。比如曲线通过(1, 1000ppm)和(0.2, 5000ppm)附近。用取对数的方法算斜率:

log(PPM2/PPM1) = B * log((Rs/R0)2 / (Rs/R0)1)

B = log(5000/1000) / log(0.2/1) = log(5) / log(0.2) ≈ 0.699 / (-0.699) ≈ -1

所以B约等于-1。再把任意一个点代入PPM = A * (Rs/R0)^B,就能反算出A。

这里如果嫌手动取点误差大,还有一个更实用的办法:去网上找这个型号对应的代码库或公开的校准值,很多开源项目已经把A、B算好了。但每个开源项目的Vcc、RL、R0定义可能不同,直接用之前一定要核对他们计算Rs/R0的方式跟你是否一致。

4.3 不同气体、不同型号的系数差异

我把常见几种气体在MQ系列上的曲线特点整理一下:

传感器型号主要气体典型A典型B(绝对值)说明
MQ-2甲烷、丙烷、烟雾约600~1000约-1.0~-1.3曲线斜率相近,多气体选择性差
MQ-4甲烷约1000~1800约-1.0对甲烷灵敏度高
MQ-7一氧化碳约100~300约-1.5需要高低压循环加热
MQ-135氨气、VOC、二氧化碳约90~200约-1.3交叉敏感非常强,定量困难

注意表格里的A、B只是一个参考范围,不是标准值。每个传感器个体、不同供电电压下,实测系数都会有偏差,所以商用产品都要用标气做多点标定,而不是裸用手册系数。

4.4 多气体交叉敏感怎么办

MQ传感器最大的局限是选择性差。MQ-2对甲烷、丙烷、丁烷、烟雾都有响应,你说不清它到底是闻到了哪种气体。这在家庭烟雾报警场景是优点,在“我想精确测出室内一氧化碳浓度”的场景就是灾难。

处理思路有几个:

  • 如果是做泄漏报警,就把所有会被传感器响应的可燃气体都当作“危险气体总量”来看待,不做具体成分区分,PPM值当作等效可燃气体浓度,正常使用没问题。
  • 如果要区分具体气体,就得组合多个传感器做模式识别,比如同时用MQ-2、MQ-7、MQ-135,通过不同传感器的响应比例来判断气体类型。这个方法能做基础的区分,但精度有限。
  • 最可靠还是换电化学传感器,比如一氧化碳电化学探头,选择性和精度都远超MQ,但价格也高出一大截。

所以,在使用MQ时,我建议在文档里明确写清楚“半定量检测”这几个字。对家庭安防类项目,它能告诉你“空气里可燃气体明显升高了”就够用;但如果你拿它去给实验室报数据,那肯定会挨批。

5. 完整案例:MQ-2测量甲烷/烟雾的ADC到PPM推算

5.1 硬件参数与校准数据设定

现在用一组实际数据把整条链路走一遍。为了方便说明,设定环境如下:

  • MCU:STM32,ADC为12位,V_ref实测3.30V
  • 传感器:MQ-2裸传感器,测量极供电Vcc=5.0V
  • 负载电阻RL=4.7kΩ(实测4.7kΩ)
  • 传感器R0:洁净空气中预热后多次采样平均,测出R0=18.0kΩ
  • 手册/拟合系数:甲烷气体A=1000,B=-1.1(用前面说到的方法从手册曲线取点拟合得到)

这些参数放在代码的最前面,方便换传感器或换模块时修改。

5.2 分步计算结果

第一步:ADC原始值。假设读到的ADC_raw=2048,这是中间值,好算,现实中这个值可能差不少。

第二步:还原引脚电压。

V_out_adc = 2048 / 4095 * 3.30 ≈ 1.650V

如果这路ADC引脚没有前端衰减,这一步得到的V_out_adc就等于传感器输出V_out_sensor。

第三步:反推传感器电阻Rs。

Rs = RL * (Vcc - V_out_sensor) / V_out_sensor = 4.7kΩ * (5.0 - 1.650) / 1.650 ≈ 4.7 * 3.35 / 1.65 kΩ ≈ 9.54kΩ

第四步:算Rs/R0。

Rs/R0 = 9.54 / 18.0 ≈ 0.530

第五步:用拟合公式算PPM。

PPM = 1000 * (0.530)^(-1.1) = 1000 * (1/0.530)^1.1 ≈ 1000 * 2.02 ≈ 2020ppm

这个结果表示,在当前环境下,MQ-2对甲烷的等效响应约为2020ppm。看着好像挺高,其实也就是打火机气体泄漏范围,这个数量级在可燃气体报警器里属于需要留意的程度。

5.3 C语言换算函数封装

把上面这五步封装成一个独立函数,代码会更好维护。实际项目里,我会把“ADC原始值”和“最终PPM”分开,中间所有参数做成结构体,方便随时调试。

typedef struct { float adc_max; // 4095 for 12-bit, 1023 for 10-bit float vref; // actually measured reference voltage float divider_gain; // 1.0 if no front-end divider float vcc; // sensor power supply voltage float rl; // load resistor in ohms float r0; // calibrated baseline resistance in ohms float coef_a; // fitting coefficient A float coef_b; // fitting coefficient B, negative value } mq_config_t; float mq_adc_to_ppm(mq_config_t *cfg, uint16_t adc_raw) { float v_adc = (adc_raw / cfg->adc_max) * cfg->vref; float v_sensor = v_adc / cfg->divider_gain; if (v_sensor <= 0.0f) { return -1.0f; } float rs = cfg->rl * (cfg->vcc - v_sensor) / v_sensor; if (rs <= 0.0f) { return -1.0f; } float ratio = rs / cfg->r0; float ppm = cfg->coef_a * powf(ratio, cfg->coef_b); return ppm; }

这个函数里有几个需要强调的地方。

  • V_out_adc如果是0V,说明传感器电阻为0或者电路短路,数值上无法计算,直接返回错误码。
  • ratio小于等于0是非法值,不会出现,但防御性编程建议保留判断。
  • powf计算速度不慢,在Cortex-M4及以上的M核上没问题,但在老8051上会偏慢。如果你用老平台,可以把指数计算提前做成查找表,以Rs/R0作为索引,线性插值查表,速度会快很多。

5.4 代码之外:如何验证换算结果

算出来2020ppm,到底对不对?大多数人没有标准气体,怎么办?有一个土办法:用打火机的气体(丁烷)短暂喷向传感器,观察PPM值是否剧烈升高。丁烷是高浓度丙烷/丁烷,MQ-2对这类气体非常敏感,读数会瞬间冲到几千甚至上万ppm。注意喷气时要离传感器远一点,别直接对着,否则浓度过大可能把敏感材料冲坏了。

另一种验证方式是异丙醇或酒精蒸汽。棉签沾一点酒精放在传感器旁边,读数也应该明显上升。这种方法不能定量,但能验证整条链路是否通:如果本来读数一直在几十ppm徘徊,棉签一放上去立刻几百上千ppm,说明ADC采集、Rs计算、曲线拟合都是连贯的。

6. 常见问题与排查实录

6.1 ADC读数满量程或者一直乱跳

读数满量程(12位ADC稳定在4095附近),先查硬件,别查代码。大概率是传感器输出电压超过ADC参考电压,MCU引脚被钳位了。用万用表直接量传感器AO引脚电压,如果超过V_ref,就得加衰减。

读数乱跳,先排除接线问题,接触不良或者杜邦线太长会引入噪声。然后检查传感器供电是否稳定,MQ的加热丝需要稳定电压,电压抖动会影响敏感层温度,输出电压跟着抖。最后才考虑软件滤波,因为软件滤波只能改善表现出来的一部分,根子问题不解决换个滤波算法也只是表面平缓。

6.2 校准时R0总是偏大或偏小

R0偏大最常见的原因是校准环境不洁净,空气里有一些挥发性气体,哪怕是刚喷完空气清新剂的房间都不行。此外传感器还没有预热够,也容易导致R0偏大。R0偏小则可能是传感器周围有酒精喷雾、油烟或者人的呼吸,呼气里CO2和VOC浓度高,都会让Rs偏低。

还有一个容易被忽略的点:R0值跟RL取值有数学关系,如果你反推Rs用的是5.1kΩ,但板上实际焊的是4.7kΩ,算出来的R0也会有偏差。校准前最好用万用表量一下RL电阻,不要只信丝印。

6.3 更换传感器后读数不对

传感器老化后R0会漂移,更换传感器更是必须重新测R0。有次我在项目里直接沿用旧传感器存在Flash里的R0,新传感器上机后读数从几百ppm涨到一万多ppm,后来重新预热校准才恢复正常。

注意不同厂家的“MQ-2”虽然引脚兼容,但敏感层材料工艺可能不同,曲线系数也有差异。换品牌后,最好重新拟合A、B系数,至少也要用已知浓度验证一下,不然只能当定性判断用。

6.4 数据手册曲线读取误差与标气校正

手工从手册曲线读取A、B,误差来源主要是印刷扫描之后坐标不再是严格的数轴刻度,以及取点位置不够精确。如果项目真的需要定量测量,最靠谱的方法是买一瓶标准气体,配置几个浓度点,比如100ppm、500ppm、1000ppm的一氧化碳,然后逐个实测Rs/R0,做多点拟合。把拟合后的线性方程再代回代码,使用标定后的A、B。

标气校正是有门槛和成本的,所以我对大多数个人项目的建议是:用手册系数估算出一个数量级即可,真正报警判据不要只看精度,更该看趋势和阈值。

6.5 温度湿度的影响与补偿

MQ传感器另一个天然问题是对环境温度和湿度敏感。同样浓度的气体,在30℃高湿环境下和15℃干燥环境下,输出会差不少。如果要提高精度,可以在板子上加温湿度传感器,记录当前温湿度,再根据实验数据做补偿修正。不过这个补偿曲线很难从手册得到,一般得自己做实验标定。

如果没有精力做温湿度补偿,那就保证所有对比数据在相似温湿度下采集,比如在家里做长期监测,早起和夜间的温差对基线影响会很明显,宁可每天定时自动校准,也不要长期顶着同一个R0。这里说的自动校准并不是全自动闭环,而是你预先设定好每天凌晨通风时采一次洁净空气R0,别在有人在房间抽烟的时候校准就行。

我把这些坑都踩过一遍后,最大的体会是:MQ传感器不是精密仪器,而是低成本告警元件。完整换算链保证的是“转换逻辑自洽、读数可复现、趋势可信”,而不是“和实验室气相色谱一样准确”。在其位谋其政,把这条链搭好,家庭烟雾报警、可燃气体泄漏监测、空气质量趋势判断这些场景,它完全能扛得住。最后再分享一个小技巧:如果你同时用多个MQ传感器做不同位置的浓度对比,ADC通道之间会互相干扰,尤其是在STM32里用连续扫描模式时,建议每个通道触发之间加一点延时,或者用多路ADC独立采样,否则后一个通道会读到前一个通道的残留电荷,导致浓度曲线出现鬼影。这个细节调试起来极其隐蔽,排查了半天最后发现是通道串扰。希望你能绕开这个坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询