模块熟悉
第 12 课:热敏传感器——温度藏在哪里
跟光敏长得一样、接线一样、代码几乎一样——但读数不能直接用
我是吴老师。这节课里有个"陷阱",我先把话撂在这儿。
你把上一课光敏的程序一个字都不改,烧进板子,换上热敏模块——它照样跑,串口照样哗哗地刷数字。
看起来很顺,对吧?
但那个数字,已经不是你以为的那个意思了。
光敏那个数,你比大小就够了:比阈值大就是亮,比阈值小就是暗,"多少勒克斯"你根本不用管。热敏不行。 热敏那个数,跟"多少度"之间隔着一层换算。你不换算,它就只是个没头没脑的数字。
这节课就讲清楚两件事:那层换算是什么,以及为什么在我们这个套件上,你最好别去跟它较真。
一、看视频时注意的四件事
第一,注意它和光敏怎么区分。
这俩模块放在一起,你不仔细看根本分不出来——丝印一样,针脚一样,板子大小一样。
区别只在顶上那个元件:
| 模块 | 顶上是什么 |
|---|---|
| 光敏 | 一个带花纹的扁圆片(光敏电阻) |
| 热敏 | 一颗玻璃珠一样的小东西(NTC 热敏电阻) |
第二,注意数字是怎么变的。
视频里我用手指捏住那颗玻璃珠,数字是慢慢变的。注意这个"慢"字。
光敏你手一遮,数字"啪"就跳过去了。热敏不行——热量要从我的手指钻进那颗玻璃珠里,珠子自己的温度升上来,电阻才会变。这个过程要几秒到几十秒。
这不是模块坏了,也不是你程序写错了。热学这件事,天生就慢。
第三,注意变化的方向可能是反的。
热敏电阻的脾气是:温度越高,电阻越小(这叫 NTC,负温度系数)。
但它接到模块上之后,你读到的数是变大还是变小——取决于模块内部怎么接的线。理论上两种都可能。
所以别背"热 = 大"或者"热 = 小",跑一遍看实际方向。 这是第 5 课那句"先测,再猜"。
第四,注意视频里我最后是怎么用它的。
我没有去算"现在 26.3 度",我是让它判断"变热了没有"。这个区别,是这节课的重点,后面细说。
二、接线和代码:照抄上一节
真的,照抄就行。
接线表(跟光敏、麦克风完全一样):
| 热敏 | 接到 |
|---|---|
| VCC | 3.3V |
| GND | GND |
AO |
一个模拟引脚(GPIO0 ~ GPIO5) |
DO |
本课不用 |
为什么不用 DO? 跟光敏那节一样的理由:DO 那个门槛是靠板上一个小电位器拧出来的,拧完你自己都记不住定在哪。我们读 AO,判断写在代码里,看得见、改得动。
代码:
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println(analogRead(0)); // 跟光敏一模一样的代码
delay(300);
}看到了吧——一个字没改。
烧进去,打开串口监视器,你应该能看到一个几百到几千之间的数字在慢慢飘。
这里先给你打个预防针:飘是正常的。
环境温度本来就在微微变,ADC 自己也有点噪声。别指望它老老实实待在一个数上不动。
光敏那节你可能也见过这个小抖动,只是热敏更明显——因为它变化的幅度本来就小。
三、要命的地方:这个数不是温度
现在到这节课的核心了。
光敏的任务是"判断亮暗",比大小就完事。温度不一样——"现在多少度"是个具体的数,你得把读数换算过去。
麻烦在于,这个换算不是乘一个数那么简单。
看这张图。横轴是温度,纵轴是电阻。
- 如果它是一条直线(图上那条虚线),那换算就简单了:温度变 1 度,电阻固定变多少,乘一乘就出来了。
- 但它是条曲线——温度每升高 1 度,电阻下降的幅度是不一样的。低温和高温段,斜率完全不同。
这就好比什么?好比你的尺子刻度是乱的。 前 10 厘米一格一厘米,后 10 厘米一格半厘米——那你量出来的长度就没法直接读,得先换算。
NTC 的尺子,就是这么一根刻度不均匀的尺子。
四、三个层次的换算方法
那怎么办?三条路,看你想要多准、愿意费多大劲。
| 方法 | 精度 | 难度 | 说白了就是 |
|---|---|---|---|
| 查表法 | 高 | 中 | 提前测一堆点,做成表格,读到一个数就查表 |
| B 值公式 | 中 | 高 | 用厂家给的 B 值,套一个带指数的公式算 |
| 两点线性拟合 | 低 | 低 | 只测两个点,中间拿直线硬连 |
三条路我都说一句:
查表法——你拿个温度计放旁边,一边看温度一边记读数,记个二三十组。写代码的时候,读到一个数就去找最接近的那一行。笨,但是准。
B 值公式——长这样:1/T = 1/T0 + (1/B) × ln(R/R0)。你看到 ln(对数)就该知道,这事儿不简单了。 而且公式里的 B 值、R0 你得有厂家数据手册,我们套件里没有给。
两点线性拟合——最省事,也最不准:
// 假设你自己测出来:室温 25°C 附近读数约 1800,手心捂着约 33°C 读数约 1300
// 中间就用一条直线硬连起来(注意:这是在两个点之间凑合,别指望准)
float v = analogRead(0);
float temp = 25.0 + (1800 - v) * (33.0 - 25.0) / (1800 - 1300);
Serial.println(temp);上面那个 1800 和 1300 是编的,你必须自己测。 而且注意——我写的是"读数变小 = 温度升高",这个是方向假设,你得先跑一遍确认,见前面第三节。
说句实话:这套件里的热敏模块,本来就不是用来精确测温的。
那颗玻璃珠的个体差异、模块上分压电阻的误差、ADC 自己的偏差,三层误差叠在一起,能准到正负两三度就算你运气好。
想知道靠谱的温度?用 DHT11(第 16 课)。 那是个数字传感器,自己内部就换算好了,直接告诉你"26.5°C",误差正负 2 度,还不用你算。
五、那它到底适合干什么
这才是这节课真正想让你记住的。
既然算不准,那它还有什么用?
有用,而且很有用——它的价值是"事件",不是"数值"。
什么叫事件?就是"变热了"这个事本身。
- 热水器开始加热了没有?
- 电机是不是转久了发烫?
- 这杯水是刚才倒的,还是放了半小时的?
这些问题你根本不需要知道具体几度,你只需要知道:"比刚才热了" 还是 "没变"。
判断"事件",只需要一条阈值线。
跟光敏那节一模一样:阈值是你自己画的一条线。线的一边叫"还好",另一边叫"变热了"。
int v = analogRead(0);
// 阈值 1500 是举例,你得用自己测出来的数
if (v < 1500) { // 比室温明显"热",就报警
digitalWrite(3, HIGH); // 点亮 LED(换成蜂鸣器也行,见第 17 课)
} else {
digitalWrite(3, LOW);
}看,还是那个闭环:传感器(读热敏)→ 判断(比阈值)→ 执行器(亮灯/响蜂鸣器)。骨架跟第 9 课、第 11 课一模一样。
那个 1500 又是哪来的
这个问题我在第 11 课专门讲过,这里再来一遍,因为它是同一个道理。
同一块热敏模块,握在手里、放在桌上、放在窗台上、放在空调风口,读数范围完全不同。
而且热敏比光敏更麻烦——光敏你遮一下就有巨大的变化,热敏的变化幅度小得多。 你可能测出来"室温 1750 到 1800,手捂着掉到 1400",中间就隔着这么窄一段。
所以那个阈值:
- 定得太靠近室温(比如 1700)→ 一阵风吹过来就报警,天天误报
- 定得太远离室温(比如 800)→ 你手捂到发烫它都不响
正确流程还是那三步:
- 先跑一遍,在你的实际环境里读
- 记下"平时"是多少、"变热时"是多少
- 在这两个数中间取个阈值,偏"变热"那一侧一点,留点余量
这就是标定。第 11 课学的那个"先测,再定",换了个模块,一字不改地用。
六、动手:捏住那颗玻璃珠
第一步:先跑一遍,什么都别碰。
让它跑个一两分钟,盯着数字看它飘的范围。把你看到的"平时值"记下来,写纸上。
如果数字一直不动、或者一直是 0 或者 4095,那多半是线的问题——
AO接到了DO、接错脚、或者VCC/GND搞反了。先查线,再怀疑代码。
第二步:用手指捏住那颗玻璃珠。
捏住,别松手,看着串口。
你会看到数字慢慢、慢慢地变化——可能要十几秒才明显。
别急。这不是模块坏了,是热量还在路上。 你可以在心里数数,看它多少秒之后开始动。
第三步:确认方向。
记下来:是变大了,还是变小了?
这个方向决定了你代码里的判断符号是 < 还是 >。 想当然写反了,程序照样跑,就是永远不触发——这种错误最难查,因为它不报错。
第四步:松手,看它慢慢回去。
回去比升上去还慢,正常的。热起来容易,凉下去难——跟生活里一样。
第五步:写判断。
拿你刚才记的两个数,取个中间值当阈值,写个 if,让它"热了就亮灯"。
第六步(可选):拿万用表量 AO 脚的电压。
对着你串口上的读数算:电压 ≈ 读数 ÷ 4095 × 3.3。对得上,说明你真的搞懂了 ADC 那套东西。
自测
答案与解析
光敏的任务是判断亮暗,比大小就够了,"多少勒克斯"你根本不需要知道。温度不一样——"现在多少度"是个具体的数,你得把电阻的变化换算成温度。而这个换算是一条曲线(指数关系),不是乘一个常数。
答案与解析
热学过程天生就慢。 热量得从你的手指传进玻璃珠,珠子自己温度升上来,电阻才变。这个"慢"跟代码、跟模块质量都没关系。同理,松手之后也要等它慢慢降回去,而且降比升还慢。
答案与解析
NTC 本身的特性是温度越高电阻越小,这是确定的。但你读到的数是变大还是变小,取决于模块内部怎么把这个电阻变化变成电压。理论上两种接法都可能。写反了程序照样跑,只是永远不触发——不报错的错误最难查。
答题要点
答题要点应该包含:① 不准的原因是误差一层层叠加——热敏元件本身的个体差异、模块上分压电阻的误差、ADC 自己的偏差,加起来能差好几度;② 它适合做"事件判断"——只关心"变热了没有",比如电机发烫、水温升高,这时候你根本不需要知道具体几度;③ 要精确温度就用 DHT11(第 16 课),那是数字传感器,内部已经把换算做好了,直接给你一个摄氏温度值。
拓展既然两点线性拟合不准,为什么很多人还是这么干?
这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。
提示:搜"分段线性拟合 传感器"、"查表法 插值"。想一想:如果我每隔 5 度测一个点,然后在每两个点之间用直线连——这样是不是既不用套公式,又能比较准?
拓展同样都是"温度改变电阻",为什么有的材料电阻变大、有的变小?
这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。
提示:搜"PTC NTC 区别"、"热敏电阻 半导体 载流子"。想一想:NTC 是半导体做的,PTC 有些是陶瓷做的——材料不同,为什么表现会相反?
本节你要动手做的事
- [ ] 接好热敏:
VCC→3.3V,GND→GND,AO→ 一个模拟引脚(注意是AO不是DO) - [ ] 先空跑一分钟,记下"平时"的读数大概是多少、飘动的范围有多大
- [ ] 用手指捏住玻璃珠,看数字慢慢变化,并确认变化方向(变大还是变小)
- [ ] 记下"室温"和"手捏住"两个数,取中间值当阈值
- [ ] 做个"变热报警":用
if判断,热了就点亮 LED——记住,比的是事件,不是温度 - [ ] (可选)用万用表量
AO脚电压,跟读数 ÷ 4095 × 3.3 对一对
这节课表面上跟第 11 课很像——一样的模块、一样的线、几乎一样的代码。
但在"读数能不能直接用"这一步上,它们分道扬镳了。
我给你留一个习惯:拿到任何一个传感器,先问一句——它读出来的东西,是"能直接用的量",还是"还得换算的量"? 光敏是前者,热敏是后者。往后的红外、超声波,各有各的脾气,你都得先问这一句。
另外,"算不准"这件事不丢人,也不代表这模块没用。 工程师天天在做这种取舍:这个场景只需要知道"变热了没有",那我就用一个两块钱的元件;那个场景要精确到 0.5 度,那我就换 DHT11。选对的,不是选贵的——这是个本事。
下一节我们学麦克风模块——那个模块身上有个特别常见的误会:很多人以为它能录音。 它到底能干什么,我们下节课说。
快去看看你桌上那个玻璃珠,捏一下试试。