先说结论
测出温度简单,但测出准确的温度,确需要花大功夫。
实际项目举例
项目中使用 ESP32-S3 + 3950 NTC 的方案进行测温,测温电路描述如下:
VCC(3.3V)— 100K 电阻 — 电压测量点(接MCU 的 ADC 管脚)— NTC — 接地。
测出的温度,在室温及以上,比水银温度计测出的温度高 1°C-2°C。在室温及以下,高 2°C-4°C。
问题排查
- 多测试几个传感器,确认是否是单个传感器偏差的原因;
测试结果:换传感器测试,问题依旧。 - 多测试几块开发板,确认是否是单个开发板的问题;
测试结果:换开发板,温度仍然偏高,但仅高 0.3°C-0.5°C。
综合上述 2 点,测试不同开发板的测量电路供电电压,发现:
开发板1:3.278 V,开发板2:3.319 V,代码中使用的是标准值:3.3 V。
这就是温度偏高的因素(但只是其中一个因素)。
测量电路的供电电压已经经过稳压芯片稳压到 3.3 V ,但是还是有差异!
可能的原因(AI 总结)
当前项目外部 NTC 温度测量的误差来源,可以分为电路参数、ADC、传感器、热环境和软件算法五类。
| 因素 | 对结果的影响 | 当前项目情况 |
|---|---|---|
| 分压供电电压 | 实际电压低于软件设定,会使计算温度偏高 | 实际 3.278V、软件按 3.300V,约偏高 0.3°C |
| 100kΩ上拉电阻误差 | 实际阻值高于100kΩ会使温度偏高,反之偏低 | 1%误差约带来 0.2~0.3°C |
| NTC的R25公差 | 实际R25偏低会使温度偏高 | 普通1% NTC约产生 ±0.2~0.3°C |
| B3950误差 | 离25°C越远影响越明显 | 单一Beta公式不等同于厂家完整R-T表 |
| NTC自热 | NTC自身功耗会使温度偏高 | 100kΩ分压功耗约几十微瓦,通常较小 |
| ADC增益、偏移和非线性 | ADC电压读低会使温度偏高,读高则温度偏低 | 芯片自动校准已经生效,但仍有残余误差 |
| ADC采样电容 | 高源阻抗可能导致第一次转换不稳定 | 已确认 probe1 首值平均高约 10.57 counts |
| ADC通道切换 | 电池通道可能影响随后读取的probe1 | 存在轻微首转换残留;probe1到probe2不明显 |
| ADC随机噪声 | 导致温度短期跳动 | probe1单组最大波动44 counts,约对应 1.3°C 瞬时变化 |
| 供电纹波 | Wi-Fi、屏幕、充电电路工作时会改变分压电源和地电位 | 固定写死3.278V不能补偿实时波动 |
| 接地与布线 | 线阻、接插件、地线压降和数字干扰会改变ADC电压 | 长探头线尤其需要关注 |
| RC滤波 | 可以降低噪声,但电容过大也需要更长建立时间 | 需要结合实际滤波电容确定等待时间 |
| 热传导与安装 | 探头与被测物接触不充分会测到空气或外壳温度 | 常见的主要误差来源 |
| 热响应时间 | NTC和不锈钢探头达到热平衡需要时间 | 与参考温度计必须同时充分稳定 |
| 板内热源 | ESP32、AMOLED、充电芯片、BME690加热器会使附近温度偏高 | 环境NTC尤其容易受影响 |
| 参考温度计 | 参考仪表本身也有精度、位置和响应时间误差 | 比对时必须同位置、同介质、同稳定时间 |
| 软件换算与取整 | ADC平均、mV整数换算和Beta公式会引入小误差 | 8次平均可降噪,但当前仍包含第一次转换 |
温度校准
芯片级校准:ADC 校准
出厂 eFuse 曲线校准负责芯片非线性,整板两点校准修正剩余的增益和零点误差。
-
芯片出厂 eFuse 校准(芯片已做校准,不用再做)
ESP32-S3 模数转换器 (ADC) 校准驱动程序 -
整板两点校准(条件有限,做不了)
修正 PCB、电源、分压电阻和残余 ADC 误差,需要外部精密电压或电阻实测。 即使 eFuse 校准正常,也建议用精密电压源和高精度万用表做整板验证。
步骤:1. 暂时隔离 NTC 分压电路与 ADC 引脚。2. 电压源和 ESP32 共地。3. 分别输入约 500 mV、2500 mV。4. 每个点采集至少 64 次并取平均。5. 用万用表记录实际电压,用固件记录当前 mv=。6. 再用约 1500 mV 验证中间点。
例如得到:实际 V1 = 500 mV,固件 M1 = 480 mV实际 V2 = 2500 mV,固件 M2 = 2430 mV
运行时校正公式为:Vcorrected = V1 + (Vmeasured - M1) × (V2 - V1) / (M2 - M1)
可在代码中得到 millivolts 后、计算 NTC 电阻前应用:static int32_t ntc_adc_correct_mv(int32_t mv){ const int32_t m1 = 480; const int32_t v1 = 500; const int32_t m2 = 2430; const int32_t v2 = 2500;
return v1 + (int32_t)( (int64_t)(mv - m1) * (v2 - v1) / (m2 - m1));}两点法校准有效 R25 和 B值(实际可行的方法)
这种方法不需要知道100kΩ上拉电阻的精确阻值,因为同一通道的上拉电阻误差已经包含计算过程中。并且它可以同时修正:
- NTC实际R25误差
- NTC实际B值误差
- 100kΩ上拉电阻误差
- 板间固定比例误差
两个点的选择:一般选择 0 °C 和 25 °C。
但如何没有恒温环境,选择其它温度也是可以的。两个校准点不要求是整数温度,只要求准确、稳定且间隔足够大。
1. 如果选择 0 °C 和 25 °C============================================需要记录:V25:25°C时NTC分压Vs25:25°C时分压供电V0:0°C时NTC分压Vs0:0°C时分压供电
先计算无量纲分压比:q25 = V25 / (Vs25 - V25)q0 = V0 / (Vs0 - V0)
再计算实际 B 值:T25 = 298.15 KT0 = 273.15 KBcal = ln(q0 / q25) / (1/T0 - 1/T25)
运行时测得 V 和当时的分压供电 Vs:q = V / (Vs - V)T(K) = 1 / [1/298.15 + ln(q/q25)/Bcal]T(°C) = T(K) - 273.15
2. 如果选择其它温度,比如:0.5 °C 和 26.2 °C============================================使用:Tlow = 0.50 + 273.15 = 273.65 KThigh = 26.20 + 273.15 = 299.35 K
分别计算分压比:qlow = V0.5 / (Vs0.5 - V0.5)qhigh = V26.2 / (Vs26.2 - V26.2)
校准B值:Bcal = ln(qlow/qhigh) / (1/Tlow - 1/Thigh)
运行时可基于高温校准点计算:q = V / (Vs - V)T(K) = 1 / [1/Thigh + ln(q/qhigh)/Bcal]T(°C) = T(K) - 273.15在固件中,每个探头应保存:
- 测量电路实际供电电压:Vs
- 参考温度:Thigh
- 参考分压比:qhigh
- 校准B值:Bcal
计算实时温度时,上述保存参数,再加上测得的实时电压 V,即可计算出经过校正的温度值。
测量电路实际供电电压,是否可以共用一个值:
- 同一块板、同一供电节点、两路NTC:Vs可以共用
- 不同板:分别保存各自的Vs
- 两个校准温度点:如果Vs变化很小,可以使用该板的平均Vs;如果变化明显,应分别记录Vs_low和Vs_high
实际验证
使用两点法校准有效 R25 和 B值,以水银温度计的温度作为参考,修改代码后测试,测量温度与水银温度计的温度误差为 +0.2 °C。
这篇文章是否对你有帮助?
发现错误或想要改进这篇文章?
在 GitHub 上编辑此页