DS18B20 防水温度传感器
| 器材 | 数量 | 参考 |
|---|---|---|
| DS18B20 防水探头 | 1 | — |
| 4.7kΩ 电阻 | 1 | — |
价格随渠道波动,以购买页实时为准。
要测一缸鱼的水温,或者堆肥箱里深浅三个点同时测温——这时候 DHT22 帮不上忙:它是裸露的塑料栅格,沾水就废,而且一颗只能测一个地方。DS18B20 正相反。它有一根金属探头用环氧或不锈钢封死,整根泡进液体里没问题;更妙的是一根数据线能串好几颗,每颗各报各的温度。水温、土温、3D 打印热床、锅炉管壁,这些场景几乎是它的主场。
工作原理
DS18B20 用的是 Dallas 的 1-Wire 单总线协议。名字里的"单"指的是:除了电源和地,真正传数据只用一根线。这一根线既负责主控(如 ESP32)发命令下去,也负责芯片把温度数据传上来,靠时序分时复用。
它能一根线挂多颗的关键,在于每颗芯片出厂时都烧死了一个全球唯一的 64 位 ROM 地址。这 64 位里前 8 位是家族码(DS18B20 固定是 0x28),中间 48 位是序列号,没有两颗重复,末尾 8 位是 CRC 校验。主控在总线上喊话时,先用"匹配 ROM"命令点名某个地址,只有地址对上的那颗芯片才会应答。所以哪怕十颗芯片并排挂在同一根线上,也能被一颗一颗精确点名、分别读温——这就是单线挂多点的全部秘密。
另一个省事的地方:它内部直接做好了温度到数字的转换,输出的就是数字量,不像热敏电阻那种模拟量还得接 ADC、写查表公式、做校准。数字进数字出,没有 ADC 误差这回事。模拟和数字传感器的区别,可以看 模数转换 这篇。
它还支持一种"寄生供电"模式,可以省掉 VDD 那根线、只用数据线取电,但接线讲究多、稳定性差,新手直接用三线正常供电即可,这里不展开。
接线
标准三线接法(以 ESP32 GPIO4 为例)。防水探头通常是三根色线:
| DS18B20 探头线 | 接到 | 说明 |
|---|---|---|
| VDD(红) | 3.3V | 也兼容 5V |
| DATA(黄/白) | GPIO4 | 数据线,需上拉 |
| GND(黑) | GND | 公共地 |
| —— | 4.7kΩ 电阻 | 跨接在 DATA 与 VDD 之间 |
关键就是那只 4.7kΩ 上拉电阻,一端接 DATA、一端接 VDD。单总线平时靠上拉保持高电平,没有它总线浮空,读出来全是乱码或 -127。上拉的道理见 上拉电阻,GPIO 本身怎么回事见 GPIO 是什么。有些现成的 DS18B20 模块板上已经焊了这只电阻,裸探头则一定要自己加。
完整代码
用 OneWire 和 DallasTemperature 两个库(Arduino 库管理器里都能搜到)。下面这段会先扫描总线上有几颗芯片,再逐颗读温:
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 4 // DATA 接 GPIO4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(115200);
sensors.begin();
int count = sensors.getDeviceCount(); // 扫描总线上的设备数
Serial.print("找到 ");
Serial.print(count);
Serial.println(" 颗 DS18B20");
}
void loop() {
sensors.requestTemperatures(); // 命令全部芯片开始转换
int count = sensors.getDeviceCount();
for (int i = 0; i < count; i++) {
float c = sensors.getTempCByIndex(i); // 按索引读第 i 颗
if (c == DEVICE_DISCONNECTED_C) { // 即 -127,没读到
Serial.print("芯片 ");
Serial.print(i);
Serial.println(" 断线");
} else {
Serial.print("芯片 ");
Serial.print(i);
Serial.print(": ");
Serial.print(c);
Serial.println(" °C");
}
}
delay(2000);
}
requestTemperatures() 是一条广播命令,让总线上所有芯片同时启动一次温度转换;12 位精度下这次转换最久要 750ms,所以读数前别催太急。
你应该看到什么
串口监视器(115200 波特率)正常会刷出:
找到 2 颗 DS18B20
芯片 0: 23.50 °C
芯片 1: 24.31 °C
芯片 0: 23.56 °C
芯片 1: 24.25 °C
如果看到 找到 0 颗 或者温度是 -127.00,先别怀疑代码,八成是上拉电阻或接线的问题(见下方故障表)。
多点测温与读数解读
上面的代码用 getTempCByIndex(i) 按索引读,简单,但索引顺序由扫描决定、换个芯片可能就乱。要稳定区分"哪根探头在哪个位置",应该按 64 位地址读:先用 sensors.getAddress(addr, i) 把每颗的地址抓出来记下,之后用 sensors.getTempC(addr) 指定地址读温。这样哪怕加减芯片,每个监测点对应哪颗都不会错位——这正是 1-Wire 唯一地址的用处。
几个该记住的数:
- 量程:-55 ~ +125°C。家用水温、土温、热床都在范围内。
- 精度:-10 ~ +85°C 区间内约 ±0.5°C,是个相当不错的数字温度传感器。
- 分辨率:可设 9 / 10 / 11 / 12 位,对应 0.5 / 0.25 / 0.125 / 0.0625°C。位数越高越细,但转换越慢(12 位约 750ms)。库默认通常是 12 位。
选型与避坑
什么时候用 DS18B20、什么时候用别的:
- 要防水、要远距离、要一根线测多个点 → DS18B20。探头泡水里、埋土里都行,多点阵列是它的强项。
- 只想测室内空气温度,还想顺带测湿度 → DHT22 或入门的 DHT11。它们能给湿度,但不防水、单点、精度一般。两者的上手可看 DHT11 入门实验。
- 要高精度温湿度:那是 SHT30/SHT40 一类 I²C 传感器的活,不在本页。
读到 -127 几乎一定是没连上:上拉电阻没接、线断了、GPIO 接错。读到固定 85 则多半是上电后还没完成第一次转换就去读了——85°C 是芯片寄存器的上电默认值,意味着"我还没测出来"。遇到 85,检查是不是 requestTemperatures() 没调用、或者读得太急没等够转换时间。
故障排查
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 找到 0 颗 / 读到 -127 | 没接 4.7kΩ 上拉、或接错位置 | 在 DATA 与 VDD 间补上 4.7kΩ |
| 读到固定 85 | 没等转换完成就读 | 确认调了 requestTemperatures(),读前留够延时 |
| 多颗只认出 1 颗 | 长线 + 多颗导致总线驱动不足 | 上拉换 3.3kΩ 或缩短总线、改星形为链形 |
| 温度乱跳 | 接触不良、电源不稳 | 检查焊点,电源就近加 0.1µF 退耦 |
| 完全无反应 | GPIO 引脚号写错 | 核对 ONE_WIRE_BUS 与实际接线一致 |
进阶与变体
把多颗 DS18B20 都并在同一根 DATA 线上(各自地址唯一),就组成了一条温度阵列:一个 GPIO 就能监测一长串点位,省引脚又省线。比如发酵罐从顶到底插三四颗看温度梯度、温室不同高度布点、地暖回路逐段测温,都是这种玩法。总线拉长(几米到十几米)时,把上拉从 4.7kΩ 适当减小(如 3.3kΩ)、走链形而非星形布线,能更稳。
更进一步,多点温度数据采上来后交给模型做异常检测或趋势预测,是常见的下一步,可参考 让 AI 帮你处理传感器数据。
典型应用
- 鱼缸 / 泳池 / 热水器水温监测
- 土壤、堆肥、发酵罐温度(探头直接插进去)
- 3D 打印机热床、挤出机温度
- 冰箱 / 冷链多点温度记录
- 沿管路布一串探头做温度阵列
小结 · 相关
DS18B20 = 数字输出 + 防水探头 + 一根线挂多颗(靠 64 位唯一地址点名)。记住两件事就能少踩坑:DATA 对 VDD 必须有 4.7kΩ 上拉;-127 是没连上、85 是还没测好。要测水/土/多点选它,只测室内空气湿度选 DHT 系列。
相关阅读:DHT22 · DHT11 · 上拉电阻 · 模数转换 · 回到 传感器总览 与 原理总览。
参数以 datasheet 为准;本页公开资料整理,接线与代码请结合实物验证。