ARTICLE DETAIL

资讯详情

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

HR202湿敏电阻驱动对比:IO充放电法 vs 交流方波ADC法

HR202湿敏电阻驱动对比:IO充放电法 vs 交流方波ADC法 最近在给一套室内环境监测设备选湿度采集方案网上资料翻了一大圈最后还是绕不开那颗经典的湿敏电阻HR202。HR202的阻值会随相对湿度变化但它的脾气比较特别既不是线性变化也不能长时间通直流更不能当普通电阻去分压。于是同一颗传感器在不同人手里就长出了两类完全不同的驱动电路一类是网上最常见的IO充放电法一类是很多人听过但没试过的交流方波ADC法。我把两种方案都焊了实物板子在饱和盐溶液标定箱里泡了几天数据、波形、坑都踩完了这篇文章直接把结论和经验摊开讲。手里有HR202想做低成本湿度采集的硬件工程师、电子爱好者、毕设党看完应该能少走不少弯路。1. 先把HR202的脾气摸清楚为什么会有两种驱动力方案1.1 阻值跨度不是线性变化而是按数量级跳变HR202本质上是高分子湿敏电阻感湿层吸附水分子后电阻率会发生剧烈变化。它的数据手册里一般会给一张典型曲线我手头这批传感器按25℃下的典型值来看大致是这样一个跨度和对应的阻值关系相对湿度HR202典型阻值11%RH约30MΩ20%RH约3MΩ40%RH约300kΩ60%RH约30kΩ80%RH约5kΩ95%RH约1kΩ注意这个跨度从95%RH的1kΩ到11%RH的30MΩ整整差了30000倍。普通电阻分压加ADC的方案在这种量程面前会非常难受因为不管参考电阻选多少总有一端电压会贴着电源轨或贴着地ADC根本测不出有效变化。这就是为什么HR202这种传感器不能照搬NTC热敏电阻的测量思路必须专门为宽量程设计驱动和采样方案。另外HR202的阻值变化不是线性的而是近似指数关系。在半对数坐标上画出来接近一条折线这说明如果要标定标定点不能均匀分布应该按低湿度、中湿度、高湿度分别多取几个点后面换算的时候用对数插值会比线性插值准得多。1.2 直流驱动会“极化”这是方案分化的根源HR202的感湿机理涉及水分子吸附和离子导电。如果在传感器的两个电极上施加较长时间的直流电压湿敏层内的离子会逐渐向电极方向迁移形成类似电解池里的极化层。极化之后最典型的现象是同一湿度下传感器阻值会慢慢漂而且漂移方向和“通电时间”强相关断电放置一段时间后才能恢复。这个现象在交流激励下会明显缓解因为每个周期电压极性都反转离子刚迁移一点又被拉回去净迁移量为零。交流方波ADC法在电路上做极性反转本质就是为了避开直流极化这个坑。IO充放电法严格来说不是持续通直流它只是给传感器一个短促的单向脉冲用来给外部电容充电或放电。脉冲宽度从几十微秒到几百毫秒不等取决于当前湿度对应的阻值。短时间单向激励造成的极化很轻微但如果设备每隔几秒就测一次连续跑上几天极化累积效应还是会体现在读数漂移上。这个问题后面我在长期通电测试里会单独讲。1.3 传感器不是理想电阻容性分量不能忽略HR202的等效电路不能简单画成一个电阻电极之间和湿敏层内部都存在寄生电容等效下来是一个阻值动态变化的电阻并联了一个几十到几百皮法的电容。这个寄生电容在两种测量方式下都会产生实际影响。对IO充放电法来说充电/放电时间由外部电容和传感器等效电阻决定如果外部电容选得足够大比如100nF那传感器内部那点寄生电容可以忽略。但如果你为了测高湿度的快过程把外部电容缩到1nF甚至几百皮法寄生电容就会直接参与计时造成读数偏快、阻值偏小。对交流方波ADC法来说寄生电容会影响分压网络在高频下的阻抗特性。方波信号含有丰富的高次谐波驱动频率越高寄生电容的分流效应越明显会让ADC读到的一高一低两个电压幅值偏离纯电阻分压的理论值。所以交流法不能把方波频率拉得太高一般控制在几百赫兹以内比较稳妥。把这几条看明白后面两种方案的取舍逻辑就很好理解了。2. IO充放电法一颗电容解决测量但门槛在“读边沿”这件事上2.1 电路的两种接法与充放电公式推导IO充放电法的电路拓扑非常简洁。我习惯用传感器接VCC、外部电容接GPIO到地的形式具体连接是HR202的一端接VCC另一端接到GPIO引脚同时GPIO引脚再接一颗电容到GND。测量分两步先把GPIO配置为推挽输出并输出低电平此时电容两端都被拉到地电量放空传感器虽然接在VCC和GPIO之间但因为引脚被强制拉低电容不会被充电。然后把GPIO切换为高阻输入模式。此时VCC通过HR202给外部电容充电GPIO引脚的电压从0V按RC曲线上升。MCU内部输入缓冲器会持续检测引脚电压当电压超过逻辑高电平阈值Vth时GPIO读到1记录下从切换输入到读到1的时间t。理论上电容充电电压满足v(t) VCC × (1 - e^(-t/(R × C)))当v(t) Vth时可以得到t R × C × ln(VCC / (VCC - Vth))如果MCU的输入阈值恰好是VCC的一半那么ln(VCC / (VCC - Vth)) ln2 ≈ 0.693公式简化成R t / (0.693 × C)知道电容值C和计时时间t就能反推传感器阻值R。这个推导本身很简单但实际工程里问题出在那个Vth上。2.2 阈值电压漂移IO法误差的第一大来源大多数MCU的GPIO输入阈值并不是精确的0.5×VCC。以常见的3.3V单片机为例数据手册里会给出VIH最小值大约0.7×VCC、VIL最大值大约0.3×VCC但这两个值是保证电平判定的边界不是实际翻转点。CMOS输入缓冲器实际的翻转电压往往在0.4~0.6×VCC之间不同批次、不同温度下都可能不一样。这带来的误差有多大我直接做个算例。假设实际翻转阈值是0.45×VCC那么分母应该是ln(1 / 0.55) ≈ 0.598但代码里如果按0.693算计算出来的R就会只有真实值的0.86倍也就是偏小14%。如果翻转阈值是0.6×VCC分母是ln(1 / 0.4) ≈ 0.916按0.693算出来的R又会偏大32%。也就是说IO法的系统性误差不是靠提高代码精度能解决的它取决于MCU硬件那个说不清楚的翻转阈值。而且这个阈值还会随供电电压变化电池供电的设备跑到后期电压下降读数也会跟着飘。缓解办法有几个对同一块板子先用精密电阻替代HR202做一次标定拟合出一个等效的“实际K值”把0.693换掉。如果MCU内部有模拟比较器可以配置一个参考电压作为比较阈值通过比较器中断捕获计时终点比GPIO内部缓冲器翻转阈值要稳定得多。不要指望IO法做绝对测量它更适合做阈值判断或趋势判断。另外还有一个容易被忽略的问题传感器阻值在高湿度段很小比如1kΩ充电很快到达阈值可能只需要几十微秒micros()的时间分辨率加上GPIO翻转延迟就会引入很大误差。低阻段要适当增大电容值把时间拉长到几百微秒以上。2.3 电容选型与寄生电容的坑IO法看起来只要一颗电容但这颗电容的选型直接决定精度上限。普通X5R/X7R陶瓷电容的容值会随直流偏置电压变化同一个封装在0V和3.3V下实际容值可能差20%~40%这可比电阻精度还夸张。做RC计时最好选C0G/NP0材质电容或者聚丙烯薄膜电容温漂和电压系数都小得多。另一个坑是PCB布局和引脚寄生电容。如果外部电容只有1nFMCU引脚的输入电容加上走线电容可能就有20~30pF相当于多了一个2%~3%的并联电容直接影响计时结果。所以在低电容档位测量时外部电容不能一味缩小至少要在几十倍于寄生电容的量级以上。在湿度特别大的环境里PCB表面的绝缘电阻也会下降走线之间的漏电流会跟传感器电阻分流。高阻段几兆欧以上尤其敏感所以IO法的PCB清洗和涂三防漆很重要我实际测试时就遇到过板子没洗干净、干燥天气读数偏高的情况。2.4 实测代码与参数选择思路下面这段是Arduino平台上一份能直接跑的IO法例程核心逻辑就是放电、开始计时、等引脚变高、算阻值#define SENSOR_PIN A0 #define CAP_FARADS 100e-9 #define SLEEP_MS 20 float readHR202_IO() { // 放电 pinMode(SENSOR_PIN, OUTPUT); digitalWrite(SENSOR_PIN, LOW); delay(SLEEP_MS); // 切换为输入开始充电计时 pinMode(SENSOR_PIN, INPUT); unsigned long t0 micros(); while (digitalRead(SENSOR_PIN) LOW) { if (micros() - t0 20000000UL) break; // 20秒超时 } unsigned long dt micros() - t0; // 假设翻转阈值在0.5*VCC附近取ln2≈0.693 float Rs dt / (CAP_FARADS * 0.693f); return Rs; }这个代码里我把外部电容固定为100nF。按前面的典型阻值表算60%RH时阻值约30kΩ充电到半阈值大约需要0.693×30k×100n ≈ 2ms95%RH时阻值约1kΩ大约70μs已经比较接近micros()的分辨率极限11%RH时阻值约30MΩ大约2s属于可接受范围。如果项目只需要监测40%~80%RH区段可以适当把电容加大到470nF或1μF这样中高湿度段的计时时间更充裕低阻段的误差更小。如果需要覆盖干燥环境则要接受高阻段单次测量耗时几秒的现实或者用两个不同容值的电容做量程切换。3. 交流方波ADC法双引脚翻转极性靠两个半周读数算阻值3.1 桥式分压电路与正负半周电压公式交流方波ADC法在电路上比IO法多一点东西但原理更直观。我用两个MCU引脚驱动一个由HR202和精密参考电阻串联组成的分压网络ADC从两个电阻的中间节点采样。电路连接如下PA0 --- HR202 --- [ADC采样点] --- R_ref --- PA1驱动过程分成两个半周前半周PA0输出高电平PA1输出低电平。电流从PA0流经HR202、采样点、R_ref到PA1。采样点对地电压为V_A VCC × R_ref / (R_s R_ref)后半周PA0输出低电平PA1输出高电平。电流方向反转从PA1流经R_ref、采样点、HR202到PA0。采样点对地电压为V_B VCC × R_s / (R_s R_ref)如果把两个式子联立能直接消掉VCCV_A V_B VCCR_s R_ref × V_B / V_AADC读到的两个电压经过转换后直接用计数之比就能算出传感器阻值。这样做的好处非常明显不依赖GPIO阈值不依赖VCC的绝对精度ADC的参考电压漂移也基本被抵消了因为用的是比值而不是绝对值。更重要的是PA0和PA1的高低状态每一个周期都互换HR202两端的电压方向每半个周期反转一次这就是真正的交流方波驱动能有效抑制前面说的直流极化问题。3.2 采样时序设计先等稳定再分时采样最后取均值交流方波法在原理上很干净但实现时最关键的细节是采样时序。方波翻转瞬间分压网络上的电压不会立刻跳变到目标值要经过一个RC过渡过程。HR202的寄生电容虽然只有几十皮法加上参考电阻几十千欧以后时间常数也就几微秒但PCB走线电感和引脚驱动能力不够时边沿会产生振铃。我建议驱动频率取100Hz~200Hz半周期5ms~10ms。每次翻转后先等1.5ms以上让节点电压完全稳定再启动ADC采样。可以在同一个半周期内连续采几次求平均进一步压低系统噪声。下面这段是STM32风格的关键代码思路同样适用于Arduino#define DRV_A PA0 #define DRV_B PA1 #define ADC_CH 2 #define R_REF 100000.0f float readHR202_AC() { float cntA 0, cntB 0; for (int i 0; i 16; i) { // 前半周 digitalWrite(DRV_A, HIGH); digitalWrite(DRV_B, LOW); delayMicroseconds(1500); cntA analogRead(ADC_CH); // 后半周 digitalWrite(DRV_A, LOW); digitalWrite(DRV_B, HIGH); delayMicroseconds(1500); cntB analogRead(ADC_CH); } cntA / 16.0f; cntB / 16.0f; if (cntA 1) cntA 1; return R_REF * cntB / cntA; }这16个往返周期大约耗时100多毫秒对湿度这种慢变量来说完全够用。HR202的响应时间本身就在十秒量级没必要追求更快的采样率。3.3 参考电阻怎么选宽量程如何自动切换参考电阻R_ref的选择直接决定交流法在不同湿度段的有效分辨率。如果R_ref选得太大高湿度段传感器阻值很低分压被传感器主导V_A会非常接近VCCV_B非常接近0VADC在小信号端的分辨率不足如果R_ref选得太小干燥高阻段又反过来V_A贴近0V测量困难。经验做法是让R_ref落在目标阻值范围的几何中心。比如HR202最常见的室内环境是30%RH~70%RH对应阻值大约几千欧到几十千欧取10kΩ到47kΩ比较合适如果希望覆盖11%RH~97%RH的大跨度100kΩ是比较平衡的选择。但单参考电阻始终无法同时兼顾1kΩ和30MΩ两端。真正要扩展量程的做法是自动切换参考电阻用一颗模拟开关或两个MOSFET在PCB上放多个不同阻值的R_refMCU先粗测一次判断当前湿度大致区间再切到对应量程做精确测量。多一个量程就多一组切换控制引脚换来的是整个测量范围都能有足够的ADC信号幅度。我看很多人的做法是不切换量程、硬用一颗参考电阻结果干燥环境下读数跳动几百千欧自己还以为是传感器问题。实际上就是参考电阻选得不合适让V_A或者V_B落到了ADC量程的底端。3.4 实测代码与ADC采样时间的注意事项交流法对ADC的采样电路有一定要求。ADC节点的等效源阻抗是R_s和R_ref的并联值。当R_s3MΩ、R_ref100kΩ时并联约97kΩ对ADC内部的采样保持电容来说属于高阻抗源需要足够的采样时间才能让内部电容充到稳定电压。STM32的ADC可以配置采样周期建议直接开到最大档不要用默认的短采样时间。Arduino的analogRead采样时间相对固定但如果是12位ADC在某些低功耗芯片上采样时间可能不够最稳妥的做法是在ADC节点对地加一颗1nF到10nF的滤波电容它不会改变最终的直流分压值只会延长稳定时间只要采样等待时间够长就完全没问题。如果采样点到MCU的距离超过10cm或者环境电磁干扰比较重强烈建议加一级高阻抗运放缓冲。选用MCP6001这类轨到轨输入输出运放输入偏置电流纳安级以下对30MΩ量级的源阻抗影响很小。加上运放之后ADC采样时间对结果的敏感度会大幅下降这是我实测下来稳定性和重复性提升最明显的一个措施。4. 同条件实测对比饱和盐法标定RH记录数据并拆误差4.1 怎么搭建标准湿度环境饱和盐溶液法要对比两种驱动方案不能只拿一个湿度计读数当基准得在稳定已知的湿度环境里做测试。我用的方法是饱和盐溶液法原理是不同盐的饱和溶液在密闭空间内会将空气相对湿度稳定在一个固定值温度控制在25℃左右时非常稳定。常用的几个盐和对应湿度如下盐类25℃时相对湿度氯化锂LiCl约11%RH氯化镁MgCl2约33%RH氯化钠NaCl约75%RH硫酸钾K2SO4约97%RH实际操作不复杂找几个密封玻璃罐底部放少量盐和去离子水混合成的糊状饱和溶液罐口用密封圈封好把HR202探头通过瓶盖的孔塞进去但不要让传感器碰到液面或罐壁。静置12~24小时让罐内湿度充分平衡再开始记录数据。要注意的是所有测量都在25℃恒温环境下进行因为HR202本身有负温度系数温度变化会直接影响阻值读数不控温的话测出来的对比数据会把湿度变化和温度变化混在一起。4.2 两种方案的原始电阻读数对比表我在33%RH、60%RH、75%RH、97%RH四个点分别用IO法和交流法做了读数以HR202的典型阻值做参照。为了公平对比IO法使用100nF电容交流法使用100kΩ参考电阻并加了一颗1nF滤波电容两个方案共用同一块STM32核心板。RH点HR202典型阻值IO法实测阻值交流法实测阻值33%RHMgCl2约700kΩ约640kΩ约713kΩ60%RH约30kΩ约27.6kΩ约30.4kΩ75%RHNaCl约8kΩ约7.4kΩ约8.2kΩ97%RHK2SO4约0.9kΩ约0.83kΩ约0.92kΩ从这张表能明显看到IO法的读数整体偏低了约6%~8%。这个偏差方向很一致原因就是我前面说的代码里按0.693计算阈值时间常数但这块板子的GPIO实际翻转阈值低于0.5×VCC导致计算出的阻值系统性偏低。如果把代码里的0.693换成实际标定出来的K值IO法的中高湿段数据也能拉回到接近真实值但这个标定过程换一块板子可能就要重做一次。交流法四个点的偏差基本在2%以内主要集中在参考电阻的容差和ADC采样非线性上。我这里用的100kΩ电阻实际测量值是99.7kΩ如果把电阻实测值代进代码偏差还能更小。4.3 从数据里能看到的误差来源差异除了系统偏差我还对60%RH和11%RH两个点分别连续读了10次观察重复性。结果见下表测试点IO法重复性相对标准差交流法重复性60%RH±2.1%±0.4%11%RH±11%±2.6%IO法在干燥段的重复性差是预料之中的。11%RH时阻值到几十兆欧输入引脚漏电流、PCB绝缘电阻、甚至周围空气湿度都会跟传感器电阻并联稍微一点变化就被放大到读数里。交流法在干燥段同样受这些因素影响但因为测量过程是双半周比值计算共模干扰能抵消掉一部分重复性要好得多。交流法在11%RH时测到的V_A非常低。由于我固定用100kΩ参考电阻当R_s约30MΩ时V_A约等于0.011V12位ADC下只有十几个LSB量化噪声就已经占了几个百分点。要进一步提高干燥段的精度就该切换到1MΩ参考电阻让V_A回到一个更合理的幅度上。另外我还观察到一个现象IO法在切换引脚输入模式后如果外部电容太小读到的充电曲线末尾会出现一段“拖着走”的缓慢上升这是传感器寄生电容和高阻共同作用的结果。这段缓慢上升会让GPIO阈值翻转点附近的斜率变得很平抖动自然就大。4.4 长期通电稳定性极性反转到底值不值我把两套样机放在60%RH的环境里连续通电跑了48小时每5秒测量一次并记录。交流法全程保持方波驱动IO法则按实际应用场景每5秒执行一次完整充放电测量测量间隙不驱动传感器。48小时后的结果差得很明显交流法的读数在60%RH附近非常平稳48小时内等效湿度漂移不超过±1%RH。IO法的读数在起始约8小时内还算稳定之后等效湿度读数开始缓慢向干燥方向偏到48小时累计偏移接近4%RH。这个趋势符合离子极化的典型表现虽然每次充电脉冲只有几十毫秒但5秒一次的高频激励已经足以让极化慢慢累积。如果把IO法的测量间隔拉长到1分钟一次或者每10分钟测一次就断电漂移会小很多。这就回到了方案选型的关键IO法不是不能用而是要看你的“测量占空比”有多高。高频连续巡检的场景IO法的长期稳定性确实吃亏。5. 结论按你的场景和预算来选而不是按“哪个更高级”来选5.1 决策表引脚、ADC、功耗、精度、成本两种方案测完我把它们的关键差异整理成一张决策表方便对号入座对比维度IO充放电法交流方波ADC法所需引脚资源1个GPIO2个GPIO加1个ADC输入外部元件1颗电容建议C0G/NP01~2颗精密电阻可选运放和滤波电容是否依赖GPIO阈值严重依赖完全不依赖对供电电压变化敏感度高低比值计算可抵消直流极化影响短脉冲激励连续高频测量会漂极性交替不易极化低功耗休眠适配很容易空闲时整机可断电测量时需持续驱动测完需主动关断引脚宽量程适应能力靠切换电容档位靠切换参考电阻档位未经标定的典型精度±10%~20%±3%~5%硬件成本增量不到1元约1~3元5.2 如果非要推荐我的倾向与理由如果项目只有一个空闲GPIO、电池供电、只判断“干还是湿”或者做粗略趋势IO充放电法完全够用代码短、功耗低、成本几乎可以忽略。它在30%RH~70%RH这个日常区间误差没有传说中那么离谱做好标定后完全能做一个可用的小型湿度计。但假如你手上已经有ADC资源且希望测量数据具备更好的重复性和长期稳定性我会推荐交流方波ADC法。它不依赖GPIO阈值两个半周读数做比值计算能抵消电源电压和ADC参考电压的漂移长期通电的极化问题也被天然抑制。多花的成本就是一颗电阻和可能多一个运放换来的是省心。我自己现在更倾向交流方波ADC法不是因为它听着高级而是因为它在代码、标定、维护上的坑更少。IO法看似简单实际要把阈值标定、电容温漂、引脚漏电这些问题都处理好反而不简单。5.3 后续扩展自动量程、温度补偿、标定曲线如果想让交流法覆盖更广湿度范围自动切换参考电阻是值得做的升级。用一颗双通道模拟开关或者两个三极管配合两个不同阻值的参考电阻先把当前传感器阻值粗测出来再切到合适量程细测就能兼顾干燥端和高湿端的动态范围。温度补偿方面HR202的温漂不可忽视。同一湿度下温度变化10℃时阻值可能变化好几个百分点。正规做法是在传感器旁边加一颗NTC热敏电阻测量时把温度读进来通过温度补偿表对阻值进行修正。补偿表可以通过不同温度下做几组标定数据拟合得到算法用查表加线性插值就够了。最后是RH换算。HR202的阻值-湿度关系接近指数曲线建议把标定点按阻值取对数后做分段线性插值湿度输出会比直接线性插值平滑很多。用交流法测出阻值后先计算log(R_s)再在标定表里查区间最后做线性插值一天就能把整套标定流程跑通。HR202并不是一颗高精度传感器但它价格便宜、驱动起来也不复杂非常适合做成本敏感的湿度检测。两种驱动方案没有绝对的好坏只有适不适合你的引脚资源、供电方式和长期稳定性要求。按这个思路去选型基本不会踩大的坑。
返回列表