十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

MQ137氨气传感器详解:硬件接线、R0标定与Arduino/STM32浓度换算代码

MQ137氨气传感器详解:硬件接线、R0标定与Arduino/STM32浓度换算代码 简介MQ137氨气检测模块的完整学习与开发资料包面向使用STM32进行环境监测、安全防护类项目开发的嵌入式工程师与电子爱好者。资源围绕传感器从原理到落地的全流程展开涵盖金属氧化物半导体检测机理、模拟量与TTL双路输出接口适配、ADC采样及GPIO电平读取方法、浓度换算与校准思路可支撑氨气浓度监测节点从原型到量产的设计调试。资料包共37个文件压缩后2.05MB包含传感器说明书、ADC0809中文资料等PDF文档Keil工程源码与C语言主程序、hex固件、汇编启动文件及编译中间文件兼顾阅读、编译、烧录和二次修改。已有3757人学习下载。配套说明对MQ137电气特性、接口定义、预热及长期稳定性注意事项做了归纳两个参考程序分别走模拟量与TTL输出两种读取路径便于开发者快速验证模块功能并迁移到自己的STM32工程中。 最近好几个做智能畜牧、农业大棚和实验室安全监测的圈友都在问我同一个问题市面上氨气传感器模块那么多为什么我看上了 MQ137能不能直接给套能跑通的代码说实话MQ137 这块模块在国产气体传感器里算是被低估的一个。它属于半导体式气敏元件专门针对氨气做了敏感度优化对铵根离子那一路的响应比 MQ135 要突出得多。用在鸡舍、猪舍、蔬菜冷链仓库这种需要实时盯氨气浓度的场合性价比确实没得挑。而且模块通常已经集成了 LM393 比较器和电位器既能出模拟电压给单片机 ADC 读也能直接给 TTL 高低电平做阈值报警接线和调试都比裸敏感元件友好不少。这篇文章我就结合自己实际调这块模块的经验把选型逻辑、硬件接线、标定原理、Arduino/STM32 的实现代码以及常见坑位一次讲清楚。适合刚入手气体传感器的新手也能给正在做环境监测项目的工程师提供一个可以直接抄作业的参考方案。1. 模块整体设计与核心参数拆解1.1 敏感元件的真实工作方式MQ137 本质上是二氧化锡SnO₂半导体气敏电阻它在洁净空气中的电导率比较低一旦接触到还原性气体氨气就是典型的还原性气体敏感材料表面会发生吸附和电子迁移导致电导率上升。这个过程中敏感元件等效成一个随气体浓度变化而变化的可变电阻——Rs。浓度越高Rs 越小。需要特别注意的是这个电阻和浓度之间并不是线性关系而是在对数坐标系里近似线性。这也就意味着我们后面做浓度换算的时候不能简单套一个 y kx b而是要做指数运算或者用特征点插值逼近。很多新手第一次测发现电压变化了一大截但换算出来的 ppm 完全不靠谱大概率就是卡在这一步。模块板子上的电路分两块一块是加热回路给敏感元件提供 5V 左右的工作电压让 SnO₂ 保持在合适的反应温度另一块是信号采集回路Rs 和负载电阻 RL 串联分压把电阻变化转成电压变化。板子上的那个蓝色电位器就是用来调 RL 等效值的它直接影响输出信号幅度也决定了数字输出的比较阈值。1.2 关键电气参数与适用场景参数项典型值备注加热电压 VH5.0V ± 0.2V直流供电必须稳压回路电压 VC3.3V ~ 5.0V决定输出电压范围检测浓度范围5 ~ 500 ppm 氨气低浓度段响应更敏感负载电阻 RL可调常见 4.7k ~ 10k由蓝色电位器调节响应时间 T90约 60 秒以内受温湿度影响明显恢复时间约 2 ~ 20 分钟高浓度暴露后恢复较慢工作温度-20℃ ~ 50℃超过范围需做温漂补偿工作湿度20% ~ 90% RH高湿度下读数会明显走偏从这些参数能看出来MQ137 并不是为工业级 ppm 级高精度检测设计的它更适合做定性监测和趋势判断。我的使用经验是在鸡舍这种环境下10 ~ 150 ppm 的段位能给出比较明显的区分度正好覆盖了家禽长期暴露的安全上限。2. 硬件接线方案与信号读取设计2.1 模拟量与数字量的取舍MQ137 模块板上给了两个输出端。DO 口是数字输出当气体浓度超过电位器设定的比较阈值时输出电平发生翻转同时板载 LED 点亮AO 口是模拟输出随浓度变化实时输出一个 0 到工作电压之间的连续电平可以接到单片机的 ADC 引脚上量化。实际项目里如果只是做“浓度超标就报警”这种简单控制用 DO 口最省事不需要占用 ADC代码就只有几行读 GPIO 的逻辑。但如果你需要记录浓度变化曲线或者做联动通风设备的自动控制就必须读 AO 口。我在自己项目里是 AO 接 ADCDO 作为硬件备份报警——万一 MCU 死机至少还有一路纯硬件比较输出能触发风扇继电器。2.2 分压计算与 ADC 采样电路设计模块的信号输出本质上是 Rs 与 RL 的分压值。根据模块电路结构输出电压 Vout 满足以下关系Vout VC × RL / (Rs RL)反转过来传感器的内阻 Rs VC × RL / Vout - RL。这意味着同一个 Vout 在不同 VC 和 RL 下对应的 Rs 是不一样的。所以程序里计算浓度的时候必须把实际供电电压和负载电阻值作为已知参数带进去。我的建议是 VC 直接用模块的 VCC 引脚电压不要从 5V 那边偷电否则 ADC 基准和分压基准不一致采样值会整体漂移。ADC 采样电路这边如果用的是 STM32建议把 AO 输出接到连续采样模式下开启内部采样保持采样时间设置到 10μs 以上避免传感器内阻偏高时采样电容充电不足导致读数偏低。Arduino Uno 的 10 位 ADC 也能对付但要注意 AREF 引脚的噪声模块地线要和单片机共地并且尽量粗短。3. 校准方法如何得到可靠的 R0 基准值3.1 标准 R0 校准流程MQ137 的数据手册里给了灵敏特性曲线纵轴是 Rs/R0横轴是氨气浓度。R0 指的是传感器在洁净空气中的阻值。所以要得到准确的 pmm 数据第一步是在已知的清洁环境里测出传感器 Rs把它定为 R0。校准过程并不复杂但有几个容易忽略的前提。首先传感器必须先在 5V 供电下通电预热 12 到 24 小时让敏感层达到稳定状态。新模块拿到手直接标定数据基本是不能用的。其次校准环境的空气必须是新鲜的不能在密闭房间、厨房、刚喷过酒精消毒剂的房间里做——这些环境里的酒精、甲醛会严重干扰标定结果。预热完成后通过 ADC 读到的电压代入前面提到的 Rs 计算公式得出当前 Rs 值这就是你的 R0。我建议连续采集 50 次取平均值同时记录环境温度方便后期做温漂补偿。3.2 干扰气体与温湿度的影响处理MQ137 虽然对氨气有优化但半导体传感器的选择性从来都不是完美的。它遇到酒精、氢气、硫化氢时也会有不同程度的响应。尤其是酒精浓度稍微高一点读数能直接飙到几百 ppm非常具有迷惑性。湿度的影响同样明显。水蒸气本身也算还原性物质高湿环境下 Rs 会降低直接导致浓度读数偏高。我测过在 85% RH 和 40% RH 下同一浓度的氨气读数差距能超过 30%。所以如果项目对精度有一定要求建议加一个温湿度传感器做查表补偿。补偿公式可以自己拟合也可以采用经验系数修正具体思路是在基准温湿度下测出偏移量再对新环境的读数做线性调整。3.3 验证夹气实验校准之后最好做一次夹气验证。我的土办法是拿一个干净的密封袋把模块放进去用注射器注入一定体积的高浓度氨水挥发气体等读数稳定后记录下来对比理论浓度和实测浓度的偏差。整个过程要控制注气速度避免气流直接冲击模块导致读数突跳。如果偏差超过 20%优先检查 R0 标定环境和 RL 调节是否正确不要一上来就怀疑气体浓度计算代码。传感器这行出了问题八成是输入参数错了而不是公式错了。4. 从电压到浓度代码实现与公式推导4.1 关键换算公式与对数坐标插值MQ137 数据手册的灵敏特性曲线在对数坐标下是一组接近直线的曲线。氨气这组曲线的特征点大约在两个位置10 ppm 时 Rs/R0 约 0.9100 ppm 时 Rs/R0 约 0.5。利用这两个点可以推导出该段的近似斜率进而得到任意浓度的换算公式。公式推导过程可以直接采用“两点确定一条直线”的思路但在对数坐标系下进行设 x log10(浓度 ppm)y log10(Rs/R0)已知点 Ax1 1对应10 ppmy1 log10(0.9)已知点 Bx2 2对应100 ppmy2 log10(0.5)斜率 k (y2 - y1) / (x2 - x1)截距 b y1 - k × x1浓度 ppm 10 ^ ((log10(Rs/R0) - b) / k)把这个公式直接写进代码测量稳定性和重复性都比我之前用查表插值的效果要好。代码里注意用浮点数运算避免 pow 函数的精度损失。4.2 Arduino 完整参考代码下面这段代码我在 Uno 上实测过可以直接用。它包含了预热等待、ADC 采样平滑、Rs/R0 计算、浓度换算和串口打印。RL 的数值根据自己的模块实际焊接电阻来填市面上大多数模块是 4.7k 或 10k。#include math.h const int AO_PIN A0; const float VC 5.0; const float RL 4.7; // 单位 kΩ依模块实际电阻修改 const float R0_CALIBRATED 38.2; // 实测洁净空气中的 R0 值单位 kΩ float readAverage(int samples 50) { long sum 0; for (int i 0; i samples; i) { sum analogRead(AO_PIN); delay(20); } return sum / (float)samples; } float voltageToRs(float adcValue) { float vout adcValue * VC / 1023.0; return (VC - vout) * RL / vout; // 单位 kΩ } float rsToPpm(float rs) { float ratio rs / R0_CALIBRATED; float y log10(ratio); float x1 1.0, y1 log10(0.9); float x2 2.0, y2 log10(0.5); float k (y2 - y1) / (x2 - x1); float b y1 - k * x1; float logPpm (y - b) / k; if (logPpm 0) return 0; return pow(10, logPpm); } void setup() { Serial.begin(9600); Serial.println(MQ137 ammonia sensor warming up...); delay(30000); // 上电预热新模块建议外部预热更长时间 } void loop() { float adc readAverage(50); float rs voltageToRs(adc); float ppm rsToPpm(rs); Serial.print(Raw ADC: ); Serial.print(adc); Serial.print( | Rs: ); Serial.print(rs); Serial.print( kΩ | NH3: ); Serial.print(ppm); Serial.println( ppm); delay(2000); }这段代码的思路比较直观。readAverage 那句是重点气体传感器的输出本身就有抖动单次采样直接用很容易出现浓度值上下乱跳的情况尤其在低浓度段。做个移动平均或者中值滤波对长期监测的稳定性改善非常明显。4.3 STM32 与 FreeRTOS 集成要点在 STM32 上做多任务监测时我建议把传感器采样逻辑独立成一个任务优先级不设太高周期设为 500ms用 ADCDMA 循环采集的方式减少 CPU 占用。值得注意的是MQ137 上电瞬间的冲击电流比较大如果项目是电池供电建议加入软启动避免供电电压跌落导致单片机复位。另外STM32 的 ADC 引脚输入阻抗相对较低VREF 如果采用内部 3.3V务必在代码里做精确的电压标定否则电压每偏差 0.05V最终浓度结果就能差出几十 ppm。5. 常见问题排查与实操避坑指南5.1 读数一直偏高或偏低的原因如果读数明显偏高先排查是否最近在传感器附近使用过酒精喷雾、消毒液、油漆等挥发性物质。这些干扰气体残留会导致 Rs 降低浓度虚高。把模块放在通风良好的洁净环境通电 24 小时一般能恢复。读数偏低时大概率是 R0 标定值偏大或者 RL 设定值不对。可以重新做一次洁净空气校准把 R0 更新进代码不要用网上别人的固定值——每块传感器的个体差异比你想的大得多直接用默认值误差可能超过 60%。5.2 数值频繁跳动的处理策略浓度值跳动通常是两个原因一是供电不稳模块 VH 引脚对电压波动极其敏感建议供电端并联 10μF 电解电容和 0.1μF 瓷片电容二是采样处理太粗糙至少使用 5 点中值滤波后再做滑动平均。也可以适当降低采样频率将串口打印间隔提高到 3 ~ 5 秒人眼观察起来会更稳定。从系统设计角度讲环境监测本身是慢变量没必要追求 100ms 的实时刷新率。5.3 长时间使用后灵敏度下降的恢复操作MQ137 长时间在工厂或养殖环境运行敏感层会吸附颗粒物或发生中毒灵敏度逐渐下降。恢复操作并不复杂把传感器取下放在 5V 供电下持续加热 12 小时中间不要通任何其他信号让敏感层慢慢把吸附物解析掉。如果加热恢复效果不明显可以尝试调整 RL 阻值让分压点回到比较合适的区间。注意换 RL 之后一定要重新标定 R0否则换算出来的浓度全部偏掉。现象可能原因解决方案读数偏高 200%酒精/有机溶剂干扰洁净空气中加热老化 24h读数恒定不变AO 引脚接线异常万用表量 AO 对地电压数字输出一直报警电位器阈值过低逆时针调节蓝色电位器数值下降缓慢高浓度暴露后恢复期等待 2 小时 持续吹风高湿天气读数异常湿度干扰增加温湿度补偿逻辑上电后读数持续漂移预热时间不足预热至少 30 分钟以上5.4 接线与布局的实操细节最后说一个容易被忽略的点。MQ137 模块的加热回路电流不算小如果和单片机共用一根长 USB 供电线加热回路的电流波动会影响 ADC 基准电压。我在实际项目中是把传感器供电和 MCU 供电分开走线在传感器供电入口单独加了一颗 LDO 稳压到 5V采样稳定性提升非常明显。模块安装位置的通风设计也要注意。如果装在封闭壳子里敏感元件周围积聚的氨气永远排不掉读数就没法反映环境真实浓度。需要在传感器附近开透气孔或者使用防尘透气膜并且避免气流直接对着传感器吹否则读数会跟着风速剧烈波动。还有一点很重要就是千万别在模块通电的时候去拔插杜邦线。我之前有一次调试时手抖碰了一下引线瞬间的接触不良导致 VH 出现幅值很大的毛刺直接把一个新型号的敏感元件击穿了。这个教训值小一百块写在这里提醒大家接线务必在断电状态下操作。写在最后我做过几轮 MQ137 的应用迭代最大的心得是半导体气体传感器这东西先天精度有限但只要你把标定做扎实代码里再做合理的滤波处理它在物联网环境监测这种对绝对精度要求没那么严苛的场景里完全够用且非常可靠。对刚接触这类传感器的人来说先把 R0 校准确认清楚再动手写浓度换算代码顺序不能颠倒。接下来可以考虑扩展的方向是做多点标定拟合或者引入环境温湿度传感器做实时补偿甚至接上 ESP8266 或者 4G 模组把数据上传到云平台做远程预警这套方案就能从一个小模块长成一个完整的监测系统了。本文还有配套的精品资源点击获取
返回列表