给机器人加一路温度感知,DS18B20 大概是成本最低、接线最省的方案之一:一根数据线就能通信,还能在同一个 GPIO 上并联多颗传感器。这篇把 DS18B20 接 ESP32 的完整流程理一遍——接线、上拉电阻、装库、读数,代码逐段说清楚,照着做就能出数。

认识DS18B20:一根数据线就能通信
DS18B20 是单总线(One-Wire)数字温度传感器,只需要一根数据线加地线就能和 ESP32 通信。它每颗都有出厂写死的 64 位唯一序列号,所以多个传感器可以并在同一根数据线上,靠序列号区分身份——这是它和 DS18B20 同类模拟传感器(比如 LM35)最大的区别:数字输出,不占 ADC 口,也不会因为引线长度引入模拟漂移。
关键规格按 Maxim 的 DS18B20 数据手册对一遍:供电范围 3.0V 到 5.5V,工作温度范围 -55°C 到 +125°C,在 -10°C 到 +85°C 区间内精度 ±0.5°C,分辨率 9 到 12 位可配(默认 12 位,对应 0.0625°C)。另外它还有寄生供电模式,可以从数据线上取电,省掉 VDD 引线。有防水不锈钢封装版本,测水温、埋土里都能用。
接线:4.7kΩ上拉电阻是关键
需要的材料:ESP32 开发板一块、DS18B20 传感器(普通或防水版)、4.7kΩ 电阻一只、面包板和杜邦线。传感器三个脚:GND 接地,DQ 是数据脚,VDD 接 3.3V。

最容易翻车的一步在这里:DQ 数据线必须通过一个 4.7kΩ 电阻上拉到 VDD。单总线是靠总线释放时被拉高来传输"1"的,没有上拉电阻,数据线悬空,读出来全是乱码或者 -127。接法是把 4.7kΩ 电阻一端接 DQ,另一端接 3.3V。
这篇教程把数据线接在 GPIO 4 上,接其他合适的 GPIO 也行,改代码里的引脚号即可。下图是正常供电模式的接线:传感器 VDD 独立接 3.3V,DQ 接 GPIO 4,上拉电阻接在 DQ 和 3.3V 之间。

如果想省一根电源线,可以用寄生供电模式:VDD 直接接地,传感器从数据线上取电。这种模式下转换温度时的瞬时电流比较大,上拉电阻更是不能省。

装库:OneWire和DallasTemperature
ESP32 走 Arduino IDE 开发,先确保装好 ESP32 板卡支持包。然后打开 Sketch 菜单下的库管理器,搜 onewire,装 Paul Stoffregen 的 OneWire 库。

再搜 dallas,装 Miles Burton 的 DallasTemperature 库。装完重启一次 IDE。

读温度:单传感器完整代码
下面是单颗 DS18B20 的完整代码,读出摄氏和华氏,每 5 秒刷新一次。有一点要说明:平台会把尖括号头文件写法剥掉,所以下面的 #include 用双引号形式写成 #include "OneWire.h",在 Arduino 工具链下两种写法编译等价,直接复制可用。
/*********
Rui Santos
Complete project details at https://RandomNerdTutorials.com
*********/
#include "OneWire.h"
#include "DallasTemperature.h"
// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
void setup() {
// Start the Serial Monitor
Serial.begin(115200);
// Start the DS18B20 sensor
sensors.begin();
}
void loop() {
sensors.requestTemperatures();
float temperatureC = sensors.getTempCByIndex(0);
float temperatureF = sensors.getTempFByIndex(0);
Serial.print(temperatureC);
Serial.println("ºC");
Serial.print(temperatureF);
Serial.println("ºF");
delay(5000);
}代码逻辑分三层:OneWire 实例负责单总线时序,绑定 GPIO 4;DallasTemperature 拿着 OneWire 的引用做上层封装;loop 里先 requestTemperatures() 触发一次温度转换,再用 getTempCByIndex(0) 读总线上第 0 颗传感器的值。只有一颗传感器时,getTempCByIndex(0) 是最省事的读法,不用关心序列号。
烧录后打开串口监视器,波特率要和代码里的 Serial.begin(115200) 一致——不少教程截图里监视器停在 9600,结果满屏乱码,还以为是传感器坏了。读数正常应该是这样:

多传感器与网页展示:一根总线挂多个点
想把机器人上多个位置的温度都测了,不用加引脚:把所有 DS18B20 的 DQ 并到同一个 GPIO,上拉电阻一只就够。先用 sensors.getDeviceCount() 拿到总线上的设备数,再逐颗用 getAddress() 取序列号,之后按序列号用 sensors.getTempC(地址) 定点读取。代码里如果某颗读出 -127 或打印 ghost device,基本是那颗供电或接触有问题,先查线。
更进一步,ESP32 可以开一个异步 Web 服务器,局域网里用浏览器访问板子的 IP,页面每 10 秒自动刷新温度。下图就是手机浏览器打开后的效果:

这部分要额外装 ESPAsyncWebServer 和 AsyncTCP 两个库,网页用占位符替换温度值的思路写,原教程里给了完整代码,篇幅关系不整段贴了,照着 GitHub 上的 ESP_DS18B20_Async_Web_Server.ino 搬即可。
踩坑提示
把新手最常撞的三个坑归拢一下:一是上拉电阻没接或阻值不合适,读数 -127 或者扫不到设备,4.7kΩ 是数据手册推荐值,别用 10kΩ 以上的凑合;二是串口监视器波特率没跟着代码改,乱码误判成硬件故障;三是防水版传感器三根线的颜色各家不统一,接之前用万用表确认 GND、DQ、VDD,别按颜色想当然。
总体来说,DS18B20 加 ESP32 是传感器入门里性价比极高的一课:接线只有一个电阻的讲究,库里两行代码出数,还能顺带把单总线和多设备寻址的概念学了。给桌面机械臂测环境温度、给小车测电机温度,这一套直接就能用上。


4.7k上拉真的不能省,血泪教训。
串口监视器波特率那个提醒太真实了,第一次玩十有八九栽在9600上,满屏乱码还怪传感器。
防水版接之前拿万用表确认三根线颜色这条很关键,不同厂家颜色真不一样,我上次就按红正黑负想当然接反过。
上拉电阻这个坑我印象太深了,去年第一次玩DS18B20就是没接4.7k,读出来全是-127,还以为买到假货,折腾一晚上才反应过来是总线悬空。这篇把寄生模式和正常模式两种接法都画出来了,比很多只给一张图的教程强。多传感器并同一根线那部分也实用,一个GPIO挂三四颗测多点温度,省引脚省得痛快。