3、热敏电阻与Steinhart-Hart方程
说到温度测量,热敏电阻是3D打印中最常用的传感器。它便宜、可靠,精度也够用。但有个问题——它的阻值和温度不是线性关系。这就引出了我们今天要聊的核心:Steinhart-Hart方程。
我个人习惯把热敏电阻看作一个「会说话的电阻」。它不说话,但阻值的变化就是它的语言。我们需要一套翻译规则,把阻值变成温度。Steinhart-Hart方程就是这套规则的数学表达。
Steinhart-Hart方程推导
先看标准形式:
1/T = A + B·ln(R) + C·(ln(R))³
其中T是开尔文温度,R是热敏电阻当前阻值。A、B、C是三个系数,由热敏电阻的型号决定。
你可能会问:为什么是三次方,不是二次方?
嗯,这里有个故事。Steinhart和Hart两位老兄在研究海洋温度测量时发现,热敏电阻的电阻-温度关系用三次对数多项式拟合,误差最小。二次方不够准,四次方又过拟合。三次方刚刚好。
实际推导中,我们通常用三个已知温度点来解方程组。比如0℃、25℃、100℃下的阻值。代入方程,三个未知数,三个方程,解出A、B、C。
关键点:Steinhart-Hart方程在-40℃到150℃范围内,精度可达±0.01℃。但超出这个范围,误差会急剧增大。我在项目中遇到过用它在200℃以上测温,结果偏差超过5℃的情况。
Marlin中的查表法实现
Steinhart-Hart方程虽然精确,但计算量太大。单片机每次测温都算一次对数,还要算三次方,太慢了。所以Marlin用了查表法。
说白了,就是提前算好一批温度对应的ADC值,存成表格。运行时直接查表,线性插值得到温度。
Marlin的查表代码在thermistortables.h中。每个热敏电阻型号对应一个表格:
// 典型的热敏电阻表格片段
const short temptable_1[][2] PROGMEM = {
{ 23, 300 }, // ADC值23对应300℃
{ 28, 290 },
{ 34, 280 },
// ... 中间省略
{ 920, 25 }, // ADC值920对应25℃
{ 980, 0 }
};
表格的生成过程是这样的:
- 选定一个温度范围,比如0℃到300℃
- 用Steinhart-Hart方程算出每个温度对应的阻值
- 根据分压电路算出ADC读数
- 把ADC值和温度一一对应存入表格
我的经验:表格的密度不是越密越好。温度变化平缓的区域可以稀疏些,变化剧烈的区域要加密。我曾经用均匀间隔的表格,结果在低温区误差很大。后来改成非均匀间隔,效果好多了。
温度-电阻曲线拟合
实际工作中,我们拿到的热敏电阻往往没有精确的A、B、C系数。这时候就需要自己拟合曲线。
拟合方法有两种:
- 三点法:测三个温度点的阻值,解出A、B、C。简单快速,但精度一般。
- 最小二乘法:测十几个点,用最小二乘拟合。精度高,但计算复杂。
我建议初学者用三点法。选低温、中温、高温三个点,比如0℃、50℃、100℃。用恒温槽或冰水混合物来标定。
避坑指南:我曾经用万用表直接测热敏电阻阻值,结果发现读数一直在跳。后来才意识到,万用表的测量电流会加热热敏电阻,导致自热效应。正确的做法是用低电流测量,或者等读数稳定后再记录。
下面这张图展示了热敏电阻的典型温度-电阻曲线:
看到没?温度低时阻值很大,温度高时阻值急剧下降。这就是NTC(负温度系数)热敏电阻的特性。Marlin默认支持的就是NTC类型。
实际项目中,我建议你准备一个表格生成工具。我自己写了个Python脚本,输入A、B、C系数,自动生成Marlin格式的表格。省时省力,还不会出错。
最后说一句:热敏电阻的选型很重要。打印PLA用100k的就行,打印ABS或PC建议用更高温度范围的型号。别问我怎么知道的——我曾经用100k的测300℃喷嘴,结果热敏电阻直接烧了。