Arduino玩转DS18B20群组:OneWire库+地址扫描,轻松搞定多点测温
2026/6/11 2:22:54 网站建设 项目流程

Arduino轻松实现DS18B20多点测温:OneWire库实战指南

在创客项目中,温度监测往往是不可或缺的一环。无论是DIY恒温箱、鱼缸水温监控系统,还是房间多点温度记录仪,DS18B20数字温度传感器因其高精度、单总线通信等特性,成为众多开发者的首选。然而,当需要在同一总线上连接多个传感器时,传统方法往往需要手动处理复杂的时序和地址管理,这对初学者来说门槛较高。

幸运的是,Arduino生态为我们提供了强大的OneWire和DallasTemperature库,只需几行代码就能轻松实现多点温度监测。本文将带你从零开始,掌握如何快速扫描总线上的所有DS18B20地址,并循环读取各点温度数据,让你的项目开发效率提升数倍。

1. 硬件准备与基础原理

DS18B20是Maxim Integrated(原Dallas Semiconductor)推出的数字温度传感器,采用独特的1-Wire单总线协议进行通信。每个DS18B20都有一个全球唯一的64位ROM编码,这使得在同一总线上挂载多个传感器成为可能。

典型硬件连接方式如下:

  • VDD:接3.3V或5V电源
  • GND:接地
  • DQ:数据线,通过4.7kΩ上拉电阻连接到Arduino任一数字引脚

当使用多个DS18B20时,所有传感器的DQ引脚都并联连接到Arduino的同一个数字引脚,形成真正的"单总线"结构。这种设计极大简化了布线,特别适合需要分布式测温的场景。

DS18B20的64位ROM编码结构:

位范围内容说明
0-70x28固定产品家族码
8-5548位唯一序列号
56-638位CRC校验码

2. 开发环境搭建

在开始编码前,我们需要准备Arduino开发环境并安装必要的库文件。

所需材料清单:

  • Arduino开发板(UNO、Nano等均可)
  • DS18B20温度传感器(至少两个)
  • 4.7kΩ电阻
  • 面包板和连接线

库安装步骤:

  1. 打开Arduino IDE,点击"工具"→"管理库..."
  2. 搜索"OneWire",安装最新版本的OneWire库
  3. 搜索"DallasTemperature",安装DallasTemperature库

这两个库将大幅简化我们与DS18B20的通信过程。OneWire库处理底层1-Wire协议,而DallasTemperature库则提供了更高层的温度读取接口。

提示:如果无法通过库管理器安装,也可以从GitHub下载这两个库的ZIP文件,然后通过"项目"→"加载库"→"添加.ZIP库"手动安装。

3. 单总线设备地址扫描

识别总线上所有DS18B20的地址是实现多点测温的关键一步。下面我们通过代码实现自动扫描功能。

#include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 2 // 数据线连接的数字引脚 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); void setup() { Serial.begin(9600); sensors.begin(); Serial.println("开始扫描1-Wire总线设备..."); // 搜索总线上的设备 byte addr[8]; while(oneWire.search(addr)) { Serial.print("发现设备,ROM地址: "); for(int i = 0; i < 8; i++) { if(addr[i] < 16) Serial.print('0'); Serial.print(addr[i], HEX); if(i < 7) Serial.print(" "); } if(OneWire::crc8(addr, 7) != addr[7]) { Serial.println(" CRC校验失败!"); continue; } Serial.println(); } oneWire.reset_search(); Serial.println("扫描完成"); } void loop() { // 空循环 }

代码解析:

  1. oneWire.search(addr)函数会依次返回总线上每个设备的64位地址
  2. 我们通过串口打印出每个设备的完整ROM地址
  3. OneWire::crc8()用于验证地址的CRC校验码是否正确
  4. 扫描完成后调用reset_search()重置搜索状态

运行这段代码后,你将在串口监视器中看到类似这样的输出:

发现设备,ROM地址: 28 FF 64 1E 81 16 03 8A 发现设备,ROM地址: 28 FF 5A 2D 81 16 04 CB 扫描完成

将这些地址记录下来,后续读取特定传感器时会用到。如果总线上有多个DS18B20,建议在传感器上贴上标签并标注对应的ROM地址,便于物理识别。

4. 多点温度读取实现

掌握了设备地址扫描方法后,我们可以进一步实现多点温度的同时读取。DallasTemperature库为我们提供了简洁的API来完成这一任务。

完整示例代码:

#include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 2 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); // 存储已知的传感器地址 DeviceAddress sensor1 = { 0x28, 0xFF, 0x64, 0x1E, 0x81, 0x16, 0x03, 0x8A }; DeviceAddress sensor2 = { 0x28, 0xFF, 0x5A, 0x2D, 0x81, 0x16, 0x04, 0xCB }; void setup() { Serial.begin(9600); sensors.begin(); // 设置温度转换分辨率(9-12位) sensors.setResolution(sensor1, 12); sensors.setResolution(sensor2, 12); } void loop() { Serial.println("请求温度转换..."); sensors.requestTemperatures(); // 发送转换命令 Serial.print("传感器1温度: "); printTemperature(sensor1); Serial.print("传感器2温度: "); printTemperature(sensor2); delay(5000); // 每5秒读取一次 } void printTemperature(DeviceAddress deviceAddress) { float tempC = sensors.getTempC(deviceAddress); if(tempC == DEVICE_DISCONNECTED_C) { Serial.println("设备未连接"); return; } Serial.print(tempC); Serial.println("°C"); }

关键函数说明:

  • sensors.begin():初始化总线通信
  • sensors.setResolution():设置温度转换分辨率(9-12位,分辨率越高转换时间越长)
  • sensors.requestTemperatures():向所有设备发送温度转换命令
  • sensors.getTempC(addr):获取指定地址传感器的温度值(摄氏度)

注意:DS18B20的温度转换需要一定时间,12位分辨率时约需750ms。如果在转换完成前读取温度,将得到前一次的转换结果。

5. 高级应用与优化技巧

掌握了基础的多点测温方法后,我们可以进一步优化系统性能并实现更复杂的功能。

5.1 动态设备管理

在实际项目中,传感器可能会被随时添加或移除。我们可以定期扫描总线,动态更新设备列表。

void checkDevices() { byte addr[8]; int deviceCount = 0; oneWire.reset_search(); while(oneWire.search(addr)) { deviceCount++; Serial.print("设备 "); Serial.print(deviceCount); Serial.print(": "); printAddress(addr); } Serial.print("总设备数: "); Serial.println(deviceCount); } void printAddress(byte addr[8]) { for(int i = 0; i < 8; i++) { if(addr[i] < 16) Serial.print('0'); Serial.print(addr[i], HEX); if(i < 7) Serial.print(" "); } Serial.println(); }

5.2 温度报警功能

DS18B20支持设置温度报警阈值,当温度超出设定范围时会触发报警搜索。

// 设置报警温度 sensors.setHighAlarmTemp(sensor1, 30.0); // 高温报警阈值30°C sensors.setLowAlarmTemp(sensor1, 10.0); // 低温报警阈值10°C // 检查报警状态 if(sensors.hasAlarm(sensor1)) { Serial.println("温度超出设定范围!"); }

5.3 电源模式选择

DS18B20支持寄生电源模式(通过数据线供电),但这种方式在长距离布线时可能不稳定。如果使用外部电源,需要在初始化时告知库:

sensors.setWaitForConversion(false); // 不等待转换完成(外部电源模式)

5.4 温度数据平滑处理

为了消除读数波动,可以对连续多次测量结果进行平均:

#define SAMPLE_SIZE 5 float getSmoothedTemperature(DeviceAddress addr) { float sum = 0; for(int i = 0; i < SAMPLE_SIZE; i++) { sum += sensors.getTempC(addr); delay(100); } return sum / SAMPLE_SIZE; }

6. 常见问题排查

在实际使用中,你可能会遇到一些问题。以下是常见问题的解决方法:

问题1:扫描不到任何设备

  • 检查接线是否正确,特别是4.7kΩ上拉电阻
  • 确保电源电压稳定(3.3V或5V)
  • 尝试更换数据线连接的Arduino引脚
  • 检查传感器方向是否正确(平面朝向自己,引脚顺序为左GND、中DQ、右VDD)

问题2:温度读数不稳定或为85°C/0°C

  • 85°C是上电默认值,确保在读取前调用了requestTemperatures()
  • 0°C通常表示通信失败,检查总线是否有干扰
  • 尝试降低分辨率(setResolution(10))
  • 确保转换完成后才读取温度(12位分辨率需等待至少750ms)

问题3:CRC校验失败

  • 可能是总线过长或受到干扰,尝试缩短线缆长度
  • 检查电源是否稳定,寄生电源模式下负载能力有限
  • 确保上拉电阻值在4.7kΩ左右

问题4:同时使用多个库导致冲突

  • 某些库可能会占用与OneWire相同的定时器资源
  • 尝试使用其他数字引脚
  • 检查库的兼容性,更新到最新版本

7. 项目实战:多点温度监控系统

将所学知识综合应用,我们可以构建一个完整的温度监控系统。以下是一个记录多个点温度并显示在串口绘图仪中的示例:

#include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 2 #define MAX_SENSORS 8 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress sensorAddresses[MAX_SENSORS]; int sensorCount = 0; void setup() { Serial.begin(115200); sensors.begin(); // 发现并存储所有传感器地址 discoverSensors(); // 设置所有传感器为12位分辨率 for(int i = 0; i < sensorCount; i++) { sensors.setResolution(sensorAddresses[i], 12); } } void loop() { static unsigned long lastUpdate = 0; // 每2秒更新一次 if(millis() - lastUpdate >= 2000) { lastUpdate = millis(); sensors.requestTemperatures(); // 打印时间戳 Serial.print(millis() / 1000); Serial.print(","); // 读取并打印所有传感器温度 for(int i = 0; i < sensorCount; i++) { float temp = sensors.getTempC(sensorAddresses[i]); Serial.print(temp); if(i < sensorCount - 1) Serial.print(","); } Serial.println(); } } void discoverSensors() { byte addr[8]; oneWire.reset_search(); while(oneWire.search(addr) && sensorCount < MAX_SENSORS) { if(OneWire::crc8(addr, 7) == addr[7]) { memcpy(sensorAddresses[sensorCount], addr, 8); sensorCount++; Serial.print("发现传感器 "); Serial.print(sensorCount); Serial.print(": "); printAddress(addr); } } Serial.print("共发现 "); Serial.print(sensorCount); Serial.println(" 个温度传感器"); } void printAddress(byte addr[8]) { for(int i = 0; i < 8; i++) { if(addr[i] < 16) Serial.print('0'); Serial.print(addr[i], HEX); if(i < 7) Serial.print(" "); } Serial.println(); }

这个示例会以CSV格式输出时间戳和各传感器温度,可以直接在Arduino IDE的串口绘图仪中可视化。对于更复杂的项目,你还可以:

  1. 添加LCD或OLED显示屏实时显示温度
  2. 实现温度超过阈值时触发继电器或报警
  3. 将数据记录到SD卡或上传到物联网平台
  4. 设计Web界面远程监控温度变化

在实际部署中,我发现使用Cat5e网线作为传感器总线非常方便,8芯线可以同时部署多个传感器,且传输距离可达20-30米。每个传感器用三根线(VDD、DQ、GND)连接,网线剩余的线可以作为备用或用于其他信号传输。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询