温度测量 —— 看似简单的嵌入式产品功能,做起来不一定简单
嵌入式
2026-07-30
1840 字
9 分钟

先说结论#

测出温度简单,但测出准确的温度,确需要花大功夫。

实际项目举例#

项目中使用 ESP32-S3 + 3950 NTC 的方案进行测温,测温电路描述如下:
VCC(3.3V)— 100K 电阻 — 电压测量点(接MCU 的 ADC 管脚)— NTC — 接地。
测出的温度,在室温及以上,比水银温度计测出的温度高 1°C-2°C。在室温及以下,高 2°C-4°C。

问题排查#

  1. 多测试几个传感器,确认是否是单个传感器偏差的原因;
    测试结果:换传感器测试,问题依旧。
  2. 多测试几块开发板,确认是否是单个开发板的问题;
    测试结果:换开发板,温度仍然偏高,但仅高 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 曲线校准负责芯片非线性,整板两点校准修正剩余的增益和零点误差。

  1. 芯片出厂 eFuse 校准(芯片已做校准,不用再做)
    ESP32-S3 模数转换器 (ADC) 校准驱动程序

  2. 整板两点校准(条件有限,做不了)
    修正 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 K
T0 = 273.15 K
Bcal = 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 K
Thigh = 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 上编辑此页