当前位置: 首页 > news >正文

Arduino与DS18B20数字温度计制作:从单总线原理到多点测温实践

1. 项目概述与核心思路大家好今天想和大家分享一个我最近在家里捣鼓的小玩意儿——用Arduino和DS18B20温度传感器做一个数字温度计。这项目虽然不大但麻雀虽小五脏俱全从硬件连接到软件编程再到最后的显示完整地走了一遍。对于刚接触单片机或者传感器的新手朋友来说这是一个绝佳的入门项目能帮你快速理解传感器数据采集、单片机控制和信息显示的基本流程。而对于有经验的朋友或许也能从中看到一些关于DS18B20这个经典传感器的使用细节和避坑技巧。为什么选择DS18B20市面上温度传感器不少像LM35、DHT11这些我也都用过。LM35是模拟输出需要接ADC引脚精度和抗干扰能力在复杂环境下会打折扣DHT11是数字输出但它是温湿度一体传感器响应速度相对慢一些而且精度是±2°C。DS18B20的优势就很明显了它是单总线数字传感器只用一根数据线外加电源和地就能通信抗干扰能力强精度高达±0.5°C分辨率还能编程设置最高到0.0625°C。更重要的是它支持“一线多机”理论上一条数据线上可以挂很多个DS18B20通过唯一的64位ROM地址来区分这在需要多点测温的场合非常有用。所以无论是做简单的环境监测还是更复杂的分布式测温系统DS18B20都是一个非常可靠和灵活的选择。这个项目的目标很明确读取DS18B20测量的环境温度并实时显示在一块LCD屏幕上做成一个独立的、可读性好的数字温度计。整个系统以Arduino UNO作为大脑负责与传感器通信、处理数据并驱动LCD。下面我就把从元器件选型、电路连接、代码编写到调试优化的全过程以及我踩过的一些坑和总结的经验毫无保留地分享给大家。2. 核心组件选型与电路设计解析2.1 核心组件深度剖析要复现这个项目首先得搞清楚手头每个元器件的角色和选型理由。1. 主控Arduino UNO选择Arduino UNO的原因很简单普及率高、资源丰富、上手容易。它基于ATmega328P微控制器有14个数字I/O口和6个模拟输入口对于驱动一个传感器和一块LCD屏绰绰有余。其5V的工作电压也正好与DS18B20和LCD屏兼容。对于初学者UNO的Bootloader和丰富的库支持能极大降低开发门槛。当然如果你手头是Nano、Mega或者其他兼容板只要引脚资源够也完全没问题。2. 温度传感器DS18B20这是项目的核心。DS18B20有三种封装TO-92像三极管、SO-8贴片和防水探头型。我选用的是最常见的TO-92封装方便在面包板上搭建。它有三个引脚VDD电源引脚工作电压范围3.0V~5.5V本项目接5V。DQ单总线数据输入/输出引脚。这是通信的关键需要接一个上拉电阻。GND电源地。这里需要特别强调上拉电阻。DS18B20的单总线协议是开漏输出这意味着其DQ引脚在输出高电平时实际上是高阻态无法主动将总线拉高。因此必须在DQ和VCC5V之间连接一个4.7kΩ的电阻为总线提供一个稳定的高电平。这是电路能否正常工作的关键很多新手遇到的问题都源于此电阻的遗漏或阻值不当。3. 显示模块20x4字符LCD屏我选择了一块20列4行的字符型LCD型号通常是基于HD44780或兼容芯片的。相比16x2的屏它能显示更多信息比如可以同时显示温度值、单位、项目标题甚至简单的图形标识。它通过并行接口与Arduino连接需要占用多个I/O口。如果为了节省引脚也可以选择I2C接口的LCD模块那样只需要两根信号线SDA, SCL但需要额外的转换板。本项目为了清晰展示底层操作使用了直接并口驱动的方式。4. 电源管理LM7805线性稳压器虽然Arduino UNO的板载USB口或Vin引脚可以提供5V电源但为了构建一个更独立、稳定的系统我额外使用了LM7805三端稳压器。它的作用是将外部输入的较高直流电压如7V~12V的适配器或电池组稳定地输出为5V为整个系统Arduino、传感器、LCD背光供电。这能避免因USB供电电流不足导致LCD背光暗淡或传感器工作不稳定的情况。使用7805时输入端和输出端需要各接一个滤波电容通常为0.33μF和0.1μF以抑制电压纹波。5. 其他无源器件电阻除了上述关键的4.7kΩ上拉电阻可能还需要一个限流电阻用于LCD的背光LED如果屏上没有集成通常220Ω左右。电容除了配合7805的电容在Arduino的电源入口处加一个100μF的电解电容可以进一步平滑电源应对LCD背光开启时的瞬时电流冲击。2.2 电路连接原理与实操要点理解了元器件接下来就是把它们正确地连接起来。电路图的核心思想是“星型连接”所有器件的电源和地都汇聚到Arduino或7805的输出端信号线则按功能连接。具体连接步骤与意图搭建电源电路如果使用外部供电将外部电源正极如9V电池正极接LM7805的输入端第1脚负极接7805的接地脚第2脚。在7805输入脚与地之间并联一个0.33μF的瓷片电容输出脚第3脚与地之间并联一个0.1μF的瓷片电容。7805的输出脚5V连接到面包板的电源正极总线其接地脚连接到面包板的电源地总线。将Arduino UNO的5V和GND引脚分别连接到面包板的电源正极和地总线。连接DS18B20传感器将DS18B20的VDD引脚连接到面包板的5V总线。将DS18B20的GND引脚连接到面包板的地总线。将DS18B20的DQ引脚连接到Arduino的数字引脚2代码中定义为ONE_WIRE_BUS。关键一步在DQ引脚和5V总线之间连接一个4.7kΩ的电阻。这个电阻通常称为“上拉电阻”。连接20x4 LCD屏 字符LCD通常有16个引脚我们需要连接其中主要的几个电源LCD的VCC第2脚接5V总线VSS第1脚接地总线。VO第3脚对比度调节通过一个10kΩ的可调电阻中间抽头连接电阻两端分别接5V和地通过旋转来调节屏幕对比度。控制线RS寄存器选择第4脚 - Arduino 引脚12RW读写第5脚 - 直接接地因为我们只写不读E使能第6脚 - Arduino 引脚11数据线我们使用4位数据模式高4位以节省引脚。D4第11脚 - Arduino 引脚7D5第12脚 - Arduino 引脚6D6第13脚 - Arduino 引脚5D7第14脚 - Arduino 引脚4背光A第15脚背光阳极通过一个220Ω限流电阻接5VK第16脚背光阴极接地。注意引脚编号可能因LCD屏厂商而异务必以你手头屏幕的标注或数据手册为准。连接控制线和数据线时建议使用不同颜色的杜邦线便于后续检查和调试。电路搭建心得 在面包板上搭建时先布局再接线。我习惯把Arduino放在一侧电源总线在上下两侧核心器件传感器、LCD在中间。连接DS18B20的上拉电阻要尽量靠近传感器端。给LCD屏接上可调电阻调节对比度非常重要否则你可能什么都看不到误以为屏坏了。第一次上电前务必再三检查电源正负极是否接反尤其是LM7805和LCD屏接反极易烧毁。3. 软件代码实现与核心逻辑解读硬件搭好了接下来就是让系统“活”起来的软件部分。代码的核心任务是初始化传感器和LCD然后在一个循环中不断读取温度并刷新显示。3.1 库文件管理与代码结构Arduino生态的强大之处在于丰富的库。本项目需要两个库OneWire用于处理单总线通信协议是DS18B20通信的基础。DallasTemperature基于OneWire库专门为Dallas半导体现Maxim Integrated的温度传感器如DS18B20提供了更高层、更易用的API。LiquidCrystalArduino IDE自带的库用于驱动基于HD44780的字符LCD。安装库在Arduino IDE中点击“工具” - “管理库...”搜索“OneWire”和“DallasTemperature”并安装。LiquidCrystal库通常是内置的。下面结合代码逐部分解析其作用和编写逻辑// 1. 引入必要的库 #include OneWire.h #include DallasTemperature.h #include LiquidCrystal.h代码开头引入三个库。OneWire.h和DallasTemperature.h需要额外安装LiquidCrystal.h是内置的。注意#include后面没有分号。// 2. 定义引脚与对象初始化 #define ONE_WIRE_BUS 2 // 定义DS18B20数据线连接的Arduino引脚 OneWire oneWire(ONE_WIRE_BUS); // 初始化OneWire对象并指定通信引脚 DallasTemperature sensors(oneWire); // 将OneWire对象传递给DallasTemperature库 // 初始化LCD对象参数对应RS, E, D4, D5, D6, D7引脚 LiquidCrystal lcd(12, 11, 7, 6, 5, 4);这里定义了硬件连接关系。ONE_WIRE_BUS宏定义为2意味着传感器数据线接在Arduino的D2引脚。随后用这个引脚号实例化一个OneWire对象oneWire。再用这个oneWire对象实例化DallasTemperature对象sensors。最后根据之前的硬件连接初始化LCD对象引脚顺序是RS12,E11,D47,D56,D65,D74。// 3. setup()函数一次性初始化设置 void setup(void) { Serial.begin(9600); // 初始化串口通信用于调试输出 sensors.begin(); // 初始化温度传感器库 lcd.begin(20, 4); // 初始化LCD指定列数和行数20列4行 // 在LCD上显示启动信息 lcd.setCursor(5, 0); // 光标移动到第0行第5列从0开始计数 lcd.print(Welcome to:); lcd.setCursor(1, 2); lcd.print(www.TheEngineering); lcd.setCursor(4, 3); lcd.print(Projects.com); delay(5000); // 显示5秒欢迎信息 lcd.clear(); // 清屏准备显示温度 }setup()函数在设备上电或复位后只运行一次。Serial.begin(9600)开启了串口监视器波特率9600。这是一个非常重要的调试手段你可以在电脑上通过“工具”-“串口监视器”查看传感器输出的原始温度数据以判断传感器是否工作正常。sensors.begin()启动温度传感器库。lcd.begin(20,4)告诉LCD库我们连接的是一块20列4行的屏幕。随后几行lcd.setCursor()和lcd.print()用于在屏幕指定位置显示欢迎信息。setCursor(列, 行)中行列索引都是从0开始。delay(5000)让欢迎信息停留5秒然后lcd.clear()清屏。// 4. loop()函数主循环重复执行 void loop(void) { sensors.requestTemperatures(); // 向总线上所有传感器发送温度转换命令 // 从总线上的第一个索引0传感器获取摄氏温度值 float tempC sensors.getTempCByIndex(0); // 将温度输出到串口监视器 Serial.print(Temperature : ); Serial.println(tempC); // 在LCD上显示温度 lcd.setCursor(0, 0); // 将光标移动到左上角 lcd.print(Temperature: ); lcd.print(tempC); // 打印温度值 lcd.print( C); // 打印单位 delay(1000); // 等待1秒后再次读取 }loop()函数会不断循环执行这是程序的核心。sensors.requestTemperatures()这条命令至关重要。它通过单总线向所有DS18B20发送一个“开始温度转换”的指令。传感器收到指令后会启动内部温度测量这个过程需要一定时间对于12位分辨率最多750ms。sensors.getTempCByIndex(0)这条命令用于读取温度值。参数0表示总线上第一个索引为0的传感器。如果你连接了多个DS18B20可以通过改变索引来读取不同的传感器。这里有一个常见的坑在requestTemperatures()之后立即调用getTempCByIndex()可能会读到上一次的转换结果或者因为转换未完成而得到-127或85这样的错误值。DallasTemperature库的getTempCByIndex()函数内部通常会等待足够的时间通过delay()以确保转换完成但为了更可靠可以在两条语句之间加一个短暂的延时例如delay(750)尤其是当你把传感器分辨率设置得更高时。随后程序将读取到的温度值tempC同时发送到串口监视器和LCD屏幕。lcd.print(tempC)会打印浮点数。LCD库默认打印两位小数。最后的delay(1000)控制采样频率这里设置为每秒读取一次。对于环境温度监测这个频率足够了。如果用于快速变化的温度场可以适当减小延时。3.2 代码优化与功能扩展建议基础的代码已经能工作了但我们可以让它更健壮、更实用。1. 增加错误处理DS18B20通信失败时getTempCByIndex()可能返回-127或85上电复位值。我们可以增加判断void loop(void) { sensors.requestTemperatures(); float tempC sensors.getTempCByIndex(0); // 检查读数是否有效 if(tempC ! DEVICE_DISCONNECTED_C) { // DEVICE_DISCONNECTED_C 是库定义的常量通常为-127 Serial.print(Temperature : ); Serial.println(tempC); lcd.setCursor(0, 0); lcd.print(Temperature: ); lcd.print(tempC); lcd.print( C); } else { Serial.println(Error: Could not read temperature data); lcd.setCursor(0, 0); lcd.print(Sensor Error! ); } delay(1000); }2. 显示华氏温度或交替显示DS18B20库也提供了getTempFByIndex()函数来直接获取华氏温度。你可以在LCD上多显示一行或者通过一个按钮切换显示单位。3. 设置传感器分辨率DS18B20的精度分辨率可以编程设置从9位到12位默认。分辨率越高转换时间越长。可以在setup()中加入void setup(void) { // ... 其他初始化代码 sensors.begin(); sensors.setResolution(12); // 设置为12位分辨率转换时间最长精度最高 // ... }4. 使用I2C LCD以节省引脚如果觉得占用引脚太多可以换用I2C接口的LCD模块。代码需要引入Wire.h和LiquidCrystal_I2C.h库初始化会变得更简单#include Wire.h #include LiquidCrystal_I2C.h LiquidCrystal_I2C lcd(0x27, 20, 4); // 地址通常是0x27或0x3F20列4行 void setup() { lcd.init(); // 初始化LCD lcd.backlight(); // 打开背光 // ... 其余代码 }这样只需要连接SDAA4、SCLA5、VCC、GND四根线即可。4. 系统调试、问题排查与实测优化硬件连接和代码上传后第一次通电往往不会一帆风顺。下面是我在调试过程中遇到的一些典型问题及解决方法希望能帮你快速排雷。4.1 常见问题与解决方案速查表问题现象可能原因排查步骤与解决方案LCD屏幕无任何显示1. 电源未接通或接反。2. 对比度调节不当。3. 背光未亮。1. 检查VCC和GND连接确保电压为5V。2.重点调节连接在VO引脚上的可调电阻缓慢旋转直到字符出现。3. 检查背光引脚A, K是否接通限流电阻是否合适。LCD显示乱码或黑色方块1. 初始化代码不正确行列数不对。2. 数据线接触不良或接错顺序。3. 时序问题在初始化完成前就尝试写数据。1. 检查lcd.begin(20,4)中的参数是否与你的屏幕匹配。2. 逐一检查D4-D7引脚连接是否正确、牢固。3. 确保在setup()中完成lcd.begin()后再进行其他操作。串口监视器显示“Error”或“-127.00”1. DS18B20数据线DQ未接上拉电阻。2. 传感器引脚接错VCC, DQ, GND。3. 传感器损坏。4. 代码中指定的数据引脚与实际不符。1.最常见原因检查4.7kΩ上拉电阻是否连接在DQ和5V之间。2. 对照数据手册确认传感器三个引脚的顺序弧形面朝自己从左到右通常是VCC, DQ, GND。3. 更换一个DS18B20测试。4. 检查代码#define ONE_WIRE_BUS 2和实际连线。温度读数固定为85°C或跳跃很大1. 上拉电阻阻值过大或过小导致信号质量差。2. 总线受到干扰导线过长、靠近电源线。3. 电源不稳定。4. 多个传感器地址冲突如果挂载了多个。1. 确保使用4.7kΩ电阻并尽量靠近传感器端连接。2. 缩短数据线长度远离电机、继电器等干扰源。3. 在Arduino的5V和GND之间并联一个100μF的电解电容。4. 使用sensors.getDeviceCount()检查总线设备数用示例代码扫描并记录每个传感器的地址。温度更新非常慢1. 传感器分辨率设置过高如12位且delay()时间不足。2. 循环中有其他耗时操作。1. 在sensors.requestTemperatures()后增加足够的延时12位分辨率需至少delay(750)。2. 优化代码将非必要的显示或计算移出主循环。Arduino或LCD发热严重1. 电源短路。2. LCD背光电流过大未加限流电阻。1. 立即断电用万用表蜂鸣档检查5V和GND之间是否短路。2. 检查LCD背光引脚是否直接接5V必须串联一个220Ω左右的限流电阻。4.2 调试流程与实操心得我的调试习惯是“分模块调试逐步集成”先调通LCD只连接Arduino和LCD上传一个简单的显示固定字符的程序如Hello World例程。确保屏幕能正常点亮并显示。这一步能排除LCD硬件和基础连接的问题。再调通传感器断开LCD只连接DS18B20。上传一个只通过串口打印温度的程序。打开串口监视器观察是否有数据输出。如果输出-127首先怀疑上拉电阻如果输出85检查接线和传感器好坏。这一步能验证传感器和单总线通信是否正常。最后系统集成将两者结合上传完整的代码。此时如果出现问题就比较容易定位是电源负载问题还是代码逻辑冲突。几个实测下来的小技巧上拉电阻是关键我试过用10kΩ电阻在导线稍长50cm时通信就变得不稳定时好时坏。换回4.7kΩ后立刻稳定。如果通信距离需要更长比如1-2米可以尝试将上拉电阻减小到2.2kΩ但要注意Arduino引脚的电流承受能力。电源要干净当LCD背光点亮时电流消耗会有个瞬间峰值。如果只用USB供电有时会导致Arduino板载稳压器输出不稳进而影响传感器读数。使用外部稳压电源如7805或品质较好的USB适配器能有效改善。代码中的延时在sensors.requestTemperatures()和sensors.getTempCByIndex(0)之间我习惯性加一个delay(750)。虽然库函数内部可能有等待但显式地等待转换完成是最保险的做法特别是当你修改了传感器分辨率后。传感器的防水与封装如果你用的是TO-92封装的DS18B20并且想测量液体或潮湿环境温度可以用热缩管或者灌胶的方式做好防水绝缘处理。市面上也有现成的防水探头型号可选直接密封好了用起来更方便。5. 项目扩展与应用场景探讨一个基础的数字温度计做成了但这仅仅是DS18B20应用的起点。它的单总线特性和高精度为更多有趣的应用打开了大门。5.1 单总线挂载多个传感器这是DS18B20最强大的功能之一。每个DS18B20都有一个全球唯一的64位ROM地址。你可以将多个传感器的DQ引脚都连接到Arduino的同一个数字引脚当然都需要各自独立的4.7kΩ上拉电阻或者共用一个但计算好总线上拉强度。在代码上你需要先扫描总线上所有设备的地址然后分别读取。DallasTemperature库提供了相应的函数#include OneWire.h #include DallasTemperature.h #define ONE_WIRE_BUS 2 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(oneWire); DeviceAddress insideThermometer, outsideThermometer; // 用于存储传感器地址 void setup(void) { Serial.begin(9600); sensors.begin(); // 发现总线上有多少个设备 Serial.print(Found ); Serial.print(sensors.getDeviceCount(), DEC); Serial.println( devices.); // 搜索并分配地址 if (!sensors.getAddress(insideThermometer, 0)) Serial.println(Unable to find address for Device 0); if (!sensors.getAddress(outsideThermometer, 1)) Serial.println(Unable to find address for Device 1); // 设置传感器分辨率可选 sensors.setResolution(insideThermometer, 12); sensors.setResolution(outsideThermometer, 12); } void loop(void) { sensors.requestTemperatures(); // 发送转换命令给所有传感器 // 通过地址读取特定传感器的温度 float tempInside sensors.getTempC(insideThermometer); float tempOutside sensors.getTempC(outsideThermometer); Serial.print(Inside: ); Serial.print(tempInside); Serial.print( C, Outside: ); Serial.print(tempOutside); Serial.println( C); delay(1000); }这样你就可以用一套系统同时监测室内、室外、水箱、土壤等多个点的温度了。5.2 结合其他传感器与执行器温度数据只有和其他系统联动才能发挥更大价值温控风扇/加热器将读取的温度值与设定阈值比较。如果温度超过28°C就通过继电器模块启动一个小风扇如果低于18°C则开启一个加热片。实现一个简单的自动恒温系统。数据记录仪给Arduino加上一个SD卡模块将温度数据连同时间戳需要RTC时钟模块定期写入SD卡生成CSV文件用于长期的环境温度变化分析。物联网节点结合ESP8266或ESP32这类带Wi-Fi的模块将温度数据上传到云平台如Blynk、ThingsBoard、自建MQTT服务器实现手机APP远程监控和历史数据查看。高温报警器当温度超过安全阈值时不仅LCD显示警告还可以让蜂鸣器鸣叫或LED闪烁用于机房、温室等场所的安防预警。5.3 精度校准与长期稳定性虽然DS18B20出厂精度已经很高±0.5°C但如果对绝对精度有更高要求可以进行简单的单点校准。找一个你认为最可靠的温度计比如经过计量校准的水银温度计作为参考在某个恒定温度环境如冰水混合物约0°C室内恒温约25°C下同时读取参考温度计和DS18B20的值计算出一个偏移量Offset。然后在代码中对读取值进行补偿float calibrationOffset 0.5; // 假设DS18B20读数比真实值高0.5度 void loop(void) { sensors.requestTemperatures(); float rawTempC sensors.getTempCByIndex(0); float calibratedTempC rawTempC - calibrationOffset; // 显示 calibratedTempC }对于长期使用的项目需要注意DS18B20的长期漂移。工业级应用会定期校准。在一般DIY项目中其稳定性足以满足大多数需求。这个基于DS18B20和Arduino的数字温度计项目从硬件到软件从原理到实操基本上把关键点都覆盖了。它就像一把钥匙帮你打开了嵌入式传感世界的大门。无论是想深入了解单总线协议还是拓展到物联网应用从这里出发都是一个扎实的起点。实际做一遍遇到的问题和解决的思路远比只看文档来得深刻。
http://www.zskr.cn/news/1380329.html

相关文章:

  • 鸿蒙PC:Qt适配OpenHarmony实战【人名录】:单机联系人卡片,不读系统通讯录也能演示详情联动
  • 3步掌握开源Verilog仿真:从概念到实战的完整思维重塑
  • 微信投票怎么发起?海投票发起投票实操教程 - 资讯纵览
  • OpenCore Legacy Patcher完整指南:如何让老旧Mac重获新生运行最新macOS
  • 如何在ComfyUI中实现10倍效率的图像智能标签提取?
  • 中小型企业集成AI能力时借助Taotoken实现统一API管理与成本控制
  • phpMyAdmin 4.8.1文件包含漏洞CVE-2018-12613实战解析
  • 收藏干货|2026年程序员转型大模型指南,8个高薪岗位小白也能入局
  • 语音AI落地最后一公里卡点,PlayAI质量波动真相:采样率适配缺陷、韵律断层、情感衰减三大隐性陷阱
  • 太阳能供电PM2.5监测仪:从传感器选型到云端上传的完整物联网实践
  • Vue2-Verify:让前端验证码实现变得如此简单的完整指南
  • 通过TaotokenCLI工具一键配置开发环境与写入各工具配置教程
  • Windows 11终极清理优化指南:用Win11Debloat让你的系统焕然一新
  • 被导师夸到离谱?paperxie 毕业论文 AI 写作,把 “熬大夜” 直接变 “开倍速”
  • 5分钟实现Honey Select 2完整本地化:一站式游戏体验增强方案
  • 2026年港澳通行证照片手机拍摄保姆级教程:规格要求与拍摄方法详解
  • B站视频下载神器:BiliDownloader让你轻松离线收藏精彩内容
  • Taotoken五分钟接入指南,用curl快速测试多模型API连通性
  • 如何在5分钟内免费搭建工业级OpenPLC虚拟控制器
  • Lovable后端集成方案深度拆解(含Spring Boot 3.2+GraalVM+OpenTelemetry完整Demo)
  • 微信小程序包体积优化与分包实战:从2M困境到优雅突破
  • 除甲醛怎么选?2026年行业口碑企业推荐指南 - 品牌排行榜
  • DIY面包板专用5V电源:低成本改造Micro USB转接板
  • Stacking集成与SHAP可解释AI在教育公平研究中的应用
  • 武商一卡通回收指南:轻松选择回收平台,快速变现 - 团团收购物卡回收
  • 对比直接使用厂商API与通过Taotoken聚合调用的成本体感
  • 免费开源视频剪辑的终极指南:Avidemux如何让视频处理变得简单高效
  • REFramework终极指南:5分钟掌握RE引擎游戏Mod开发与VR支持
  • RFID手持终端机有哪些功能?选购指南帮你理清需求 - 资讯纵览
  • FM5057H 二合一锂电池保护 IC