带有Arduino的DS18B20温度传感器程序流程图和原理

2021-05-2721:06:45带有Arduino的DS18B20温度传感器程序流程图和原理已关闭评论

 

DS18B20 1-Wire温度传感器的原理

DS18B20是由Maxim Integrated(以前的Dallas Semiconductor)生产的数字温度传感器。它是市场上最受欢迎的温度传感器之一,在较大的温度范围(-55°C至+ 125°C)内提供相当高的精度(±0.5°C)。由于传感器的工作电压为3.0至5.5 V,因此您可以将其与Arduino(以5 V工作)一起使用,也可以与具有3.3 V GPIO引脚的ESP32和Raspberry Pi等设备一起使用。

该传感器的主要优点之一是,它仅需要Arduino的一个数字引脚即可进行通信。使用Dallas Semiconductor的传感器连通的1-Wire ®协议。该协议的工作方式与I2C相似,但数据速率较低,范围更广。

另一个优点是,每个DS18B20传感器都有一个唯一的64位串行代码,该代码允许多个传感器在同一1-Wire总线上工作。因此,您可以从仅用一个Arduino引脚连接在一起的多个传感器读取数据(请参见下面的代码示例)。

传感器的分辨率可以通过编程方式设置为9、10、11或12位。这分别对应于0.5°C,0.25°C,0.125°C和0.0635°C的温度增量。上电时的默认分辨率为12位。

您可以在下表中找到更多规格。

DS18B20数字温度传感器规格

电源电压3.0至5.5 V
待机电流1微安
有功电流1.5毫安
测量范围-55°C至+ 125°C(-67°F至+257°F)
精度
(温度计误差)
从-10°C到+85°C
为±0.5°C从-30°C到+100°C为
±1°C从-55°C到+125°C为±2°C
解析度9位至12位(可编程)
转换时间<750毫秒(12位分辨率)
通讯协议1-Wire®总线协议
包裹3针TO-92
制造商Maxim Integrated
成本查看价格

有关更多信息,您也可以在此处查看数据表:

DS18B20传感器的类型

传感器通常以三种形式出现。最常见的类型是3引脚TO-92封装,看起来就像一个晶体管。

 

这种类型的传感器有时安装在分线板上,该分线板上可以包括电源LED和所需的4.7kΩ上拉电阻。始终确保检查PCB上的标记,因为引脚的顺序可能因制造商而异。

 

最后,您可以购买已连接电缆的防水探头型传感器。如果要测量远处,水下或地下的物体,则此样式很有用。

 

请注意,防水传感器的电缆通常使用PVC护套,因此建议将其保持在100°C以下。


接线–将DS18B20连接到Arduino

将DS18B20连接到Arduino相当容易,因为您只需要连接3个引脚即可。首先将GND引脚接地,并将V DD引脚连接至Arduino的5 V输出。

接下来,将中间引脚(DQ)连接到Arduino的任何数字引脚。在这种情况下,我使用了数字引脚2。您还必须在DQ引脚和5 V之间添加一个4.7kΩ的上拉电阻。这将使1-Wire总线的空闲状态保持高电平。

DS18B20数字温度传感器与Arduino的连接接线图原理图电路教程
具有Arduino Uno的DS18B20数字温度传感器接线图

下表中也提供了连接。

DS18B20-数字温度传感器引脚排列

请注意,当传感器的平坦侧面(上面印有文字)朝向您时,引脚1(GND)是最左侧的引脚。

DS18B20数字温度传感器连接

DS18B20Arduino的
引脚1(GND)地线
针脚2(DQ)Pin 2 Arduino并通过4.7kΩ电阻器达到5V
PIN 3(V DD5伏

防水DS18B20传感器的连接方法相同。但是,导线的颜色可能会因制造商而异。地线(GND)通常为黑色或蓝色,电源线(VDD)通常为红色,信号线(DQ)通常为黄色或白色。如果不确定,我强烈建议您始终检查传感器的数据表。

防水DS18B20数字温度传感器连接

防水DS18B20Arduino的
黑线(GND)地线
黄线(DQ)Pin 2 Arduino并通过4.7kΩ电阻器达到5V
红线(V DD5伏

 


安装DallasTemperature和OneWire Arduino库

1-Wire通信协议有些复杂,需要一堆代码才能解析出该通信。因此,我们将使用Miles Burton的DallasTemperature Arduino库来简化这些传感器的编程。

该库允许您发出简单的命令以从传感器中读取温度数据。

您可以在GitHub上找到此库的源代码。

要安装库,请在Arduino IDE中转到“工具”>“管理库”(在Windows上为Ctrl + Shift + I)  。库管理器将打开并更新已安装库的列表。

安装Arduino库步骤1打开Library Manager

您可以搜索“ ds18b20 ”,并通过Miles Burton查找DallasTemperature库。选择最新版本,然后单击“安装”。

DallasTemperature库依赖于您还需要安装的OneWire Arduino库。该库负责1-Wire通信协议。

搜索“ onewire”,然后查找Jim StudtOneWire库。

 


具有Arduino示例代码的DS18B20温度传感器

使用以下示例代码,您可以从DS18B20传感器读取温度并将其显示在串行监视器中。

您可以使用Arduino IDE将示例代码上传到 Arduino。

要复制代码,请单击代码字段右上角的按钮。

/ * DS18B20 1-Wire数字温度传感器,带有Arduino示例代码。更多信息:https://www.makerguides.com * /
//包括所需的Arduino库:
#include <OneWire.h>
#include <DallasTemperature.h>
//定义1-Wire总线连接到Arduino的哪个引脚:
#定义ONE_WIRE_BUS 2
//创建一个oneWire类的新实例以与任何OneWire设备通信:
OneWire oneWire ONE_WIRE_BUS ;
//将oneWire引用传递给DallasTemperature库:
达拉斯温度传感器&oneWire ;
无效设置(){
//以9600的波特率开始串行通信:
序列号。开始9600 ;
//启动库:
传感器。开始();
}
无效循环(){
//向总线上的所有设备发送命令以执行温度转换:
传感器。requestTemperatures ();
//获取以摄氏度为单位的温度以获取设备索引:
浮动温度=传感器。getTempCByIndex 0 ; //索引0指向第一个设备
//获取以华氏度为单位的温度以获取设备索引:
float tempF =传感器。getTempFByIndex 0 ;
//在串行监视器中以摄氏度为单位打印温度:
序列号。打印“温度:”
序列号。打印tempC ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。打印“ C |” ;
//以华氏度打印温度
序列号。打印tempF ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。println “ F”
//等待1秒钟:
延迟1000 ;
}

您应该在“串行监视器”中看到以下输出(Ctrl + Shift + M)。

串行监视器输出

确保串行监视器的波特率也设置为9600。

代码如何工作

第一步是包括所需的Arduino库:

//包括所需的Arduino库:
#include <OneWire.h>
#include <DallasTemperature.h>

接下来,我定义了传感器的DQ引脚连接到Arduino的哪个引脚。语句#define可用于为常数指定名称。编译程序时,编译器将使用定义的值替换对此常量的所有引用。因此,在您提到的所有地方ONE_WIRE_BUS,编译程序时,编译器都会将其替换为值2。

//定义1-Wire总线连接到Arduino的哪个引脚:
#定义ONE_WIRE_BUS 2

此后,我创建了OneWire类的新对象,并将DQ引脚传递给其构造函数。您还需要创建DallasTemperature类的对象,并将oneWire对象作为参数传递。

请注意,我将DallasTemperature对象称为“传感器”,但您也可以使用其他名称。

OneWire oneWire ONE_WIRE_BUS ;
达拉斯温度传感器&oneWire ;

在代码的设置部分,我们以9600的波特率开始串行通信。接下来,我使用函数初始化总线begin()

无效设置(){
//以9600的波特率开始串行通信:
序列号。开始9600 ;
//启动库:
传感器。开始();
}

在代码的循环部分,我们从总线上所有传感器的命令开始,开始温度转换。

//向总线上的所有设备发送命令以执行温度转换:
传感器。requestTemperatures ();

接下来,我使用这些函数getTempCByIndex(deviceIndex)getTempFByIndex(deviceIndex)分别获取以摄氏度和华氏度为单位的温度。在这种情况下,我们只有1个传感器连接到总线。因为计数从零开始,所以我将传感器的索引设置为0。

//获取以摄氏度为单位的温度以获取设备索引:
浮动温度=传感器。getTempCByIndex 0 ; //索引0指向第一个设备
//获取以华氏度为单位的温度以获取设备索引:
float tempF =传感器。getTempFByIndex 0 ;

最后,温度在串行监视器中打印:

//在串行监视器中以摄氏度为单位打印温度:
序列号。打印“温度:”
序列号。打印tempC ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。打印“ C |” ;
//以华氏度打印温度
序列号。打印tempF ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。println “ F”

由于12位模式下的温度转换最多需要750 ms,因此我在每次测量之间增加了1秒的延迟。


在Arduino上使用多个DS18B20传感器

正如我在简介中提到的那样,您可以仅使用Arduino的一个引脚就可以从多个DS18B20传感器读取温度。您可以在下面找到两个示例代码。在第一个示例中,您可以通过连接的传感器的索引读取温度。因为所有传感器都连接到相同的1-Wire总线,所以第一个传感器的索引为0,第二个索引为1,依此类推。

在第二个示例中,我将向您展示如何读取每个传感器的唯一64位地址。然后可以使用该地址单独读取每个传感器。

接线–将多个DS18B20传感器连接到Arduino

将多个DS18B20传感器连接到Arduino就像连接一个一样简单。所有传感器都并联连接,即所有相同的引脚都连接在一起。就像以前一样,GND引脚接地,V DD引脚连接到5 V,DQ引脚连接到Arduino的引脚2。不要忘记DQ引脚和5 V之间的4.7kΩ上拉电阻。

请注意,我使用了一块面包板将所有引脚连接在一起。如果您不熟悉面包板的工作原理,请在此处找到说明。

多个DS18B20 1-Wire数字温度传感器连接到Arduino

多个带Arduino示例代码的DS18B20传感器

在下面的示例中,您可以按索引读取每个传感器的温度,并将其显示在串行监视器中。

/ *多个带Arduino示例代码的DS18B20 1-Wire数字温度传感器。更多信息:https://www.makerguides.com * /
//包括所需的Arduino库:
#include <OneWire.h>
#include <DallasTemperature.h>
//定义1-Wire总线连接到Arduino的哪个引脚:
#定义ONE_WIRE_BUS 2
//创建一个oneWire类的新实例以与任何OneWire设备通信:
OneWire oneWire ONE_WIRE_BUS ;
//将oneWire引用传递给DallasTemperature库:
达拉斯温度传感器&oneWire ;
int deviceCount = 0;
浮动温度
浮动温度
无效设置(){
//以9600的波特率开始串行通信:
序列号。开始9600 ;
//启动库:
传感器。开始();
//找到总线上的设备:
序列号。println “定位设备...”
序列号。打印“找到” ;
deviceCount =传感器。getDeviceCount ();
序列号。打印deviceCount ;
序列号。println “设备”
}
无效循环(){
//向总线上的所有设备发送命令以执行温度转换:
传感器。requestTemperatures ();
//显示每个传感器的温度
for int i = 0; i < deviceCount; i ++ {
序列号。打印“传感器” ;
序列号。打印i + 1 ;
序列号。打印“:” ;
tempC =传感器。getTempCByIndex i ;
tempF =传感器。getTempFByIndex i ;
序列号。打印tempC ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。打印“ C |” ;
序列号。打印tempF ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。println “ F”
}
序列号。println ();
延迟1000 ;
}

串行监视器中的输出应如下所示:

多个DS18B20温度传感器串行监控器输出
多个DS18B20传感器串行监视器输出

代码如何工作

此示例中的代码与之前的代码基本相同。

在设置部分,我添加了一个额外的功能,该功能可以计算连接到1-Wire总线的设备数量。

//找到总线上的设备:
序列号。println “定位设备...”
序列号。打印“找到” ;
deviceCount =传感器。getDeviceCount ();
序列号。打印deviceCount ;
序列号。println “设备”

在代码的循环部分中,我使用了for循环来循环遍历代码的一部分,该部分通过其索引为连接到总线的每个传感器获取温度。

//显示每个传感器的温度
for int i = 0; i < deviceCount; i ++ {
序列号。打印“传感器” ;
序列号。打印i + 1 ;
序列号。打印“:” ;
tempC =传感器。getTempCByIndex i ;
tempF =传感器。getTempFByIndex i ;
序列号。打印tempC ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。打印“ C |” ;
序列号。打印tempF ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。println “ F”
}

 


按地址读取传感器

为了按传感器的单个地址读取传感器,我们首先需要知道每个传感器的地址是什么。为此,您可以使用下面的示例草图。

草图在串行监视器中打印连接的传感器的地址。为了知道哪个传感器,您可以一次仅连接一个传感器,也可以依次添加一个新传感器。然后,您可以标记连接到1-Wire总线的每个传感器。

DS18B20地址查找器

/ *多个带Arduino示例代码的DS18B20 1-Wire数字温度传感器。
//包括所需的Arduino库:
#include <OneWire.h>
#include <DallasTemperature.h>
//定义1-Wire总线连接到Arduino的哪个引脚:
#定义ONE_WIRE_BUS 2
//创建一个oneWire类的新实例以与任何OneWire设备通信:
OneWire oneWire ONE_WIRE_BUS ;
//将oneWire引用传递给DallasTemperature库:
达拉斯温度传感器&oneWire ;
//创建变量:
int deviceCount = 0; //变量以存储连接的设备数
DeviceAddress设备地址;//变量以存储设备地址
无效设置(){
//以9600的波特率开始串行通信:
序列号。开始9600 ;
//启动库:
传感器。开始();
//找到总线上的设备:
序列号。println “定位设备...”
序列号。打印“找到” ;
deviceCount =传感器。getDeviceCount ();
序列号。打印deviceCount ;
序列号。println “设备”
序列号。println “打印地址...”
for int i = 0; i < deviceCount; i ++ {
序列号。打印“传感器” ;
序列号。打印i + 1 ;
序列号。打印“:” ;
传感器。getAddress deviceAddress,i ;
printAddress deviceAddress ;
}
}
无效循环(){
}
void printAddress DeviceAddress deviceAddress {
对于uint8_t i = 0; i < 8; i ++ {
序列号。打印“ 0x” ;
如果deviceAddress [ i ] < 0x10 {
序列号。打印“ 0” ;
}
序列号。打印deviceAddress [ i ] ,HEX ;
如果i < 7 {
序列号。打印“,” ;
}
}
序列号。println ();
}

串行监视器中的输出应如下所示:

DS18B20-地址查找器

现在记下所有传感器的地址,因为在下一个示例中将需要它们。

通过地址Arduino示例代码读取传感器

在以下示例中,您可以通过指定每个传感器的唯一地址来读取它们的温度。

/ *通过地址读取多个DS18B20 1-Wire数字温度传感器。
//包括所需的Arduino库:
#include <OneWire.h>
#include <DallasTemperature.h>
//定义1-Wire总线连接到Arduino的哪个引脚:
#定义ONE_WIRE_BUS 2
//创建一个oneWire类的新实例以与任何OneWire设备通信:
OneWire oneWire ONE_WIRE_BUS ;
//将oneWire引用传递给DallasTemperature库:
达拉斯温度传感器&oneWire ;
//连接到1-Wire总线的DS18B20传感器的地址
字节传感器1 [ 8 ] = { 0×28 为0x18 0xB4 ×49 0x0C 0×00 0×00 0x7C } ;
字节传感器2 [ 8 ] = { 0×28 的0xCC 0x19 ×49 0x0C 0×00 0×00 为0xBB } ;
字节传感器3 [ 8 ] = { 0×28 0x19 0xEF 0x48 0x0C 0×00 0×00 0×21 } ;
无效设置(){
//以9600的波特率开始串行通信:
序列号。开始9600 ;
//启动库:
传感器。开始();
}
无效循环(){
//向总线上的所有设备发送命令以执行温度转换:
传感器。requestTemperatures ();
序列号。打印“传感器1:” ;
printTemperature sensor1 ; //以sensor1的地址作为输入调用printTemperature函数
序列号。打印“传感器2:” ;
printTemperature sensor2 ;
序列号。打印“传感器3:” ;
printTemperature sensor3 ;
序列号。println (); //打印一个空行
延迟1000 ;
}
void printTemperature DeviceAddress address {
//获取以摄氏温度为单位的设备地址:
浮动温度=传感器。getTempC 地址;
//获取以华氏度为单位的设备地址的温度:
float tempF =传感器。getTempF 地址;
序列号。打印tempC ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。打印“ C |” ;
//以华氏度打印温度
序列号。打印tempF ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。println “ F”
}

请注意,您必须用在前面的示例代码中找到的地址替换第17至19行中的地址。

//连接到1-Wire总线的DS18B20传感器的地址
字节传感器1 [ 8 ] = { 0×28 为0x18 0xB4 ×49 0x0C 0×00 0×00 0x7C } ;
字节传感器2 [ 8 ] = { 0×28 的0xCC 0x19 ×49 0x0C 0×00 0×00 为0xBB } ;
字节传感器3 [ 8 ] = { 0×28 0x19 0xEF 0x48 0x0C 0×00 0×00 0×21 } ;

您应该在串行监视器中看到以下输出。

代码说明

每个传感器的地址由64位组成。在代码中,我们将地址指定为八个8位字节的数组。

//连接到1-Wire总线的DS18B20传感器的地址
字节传感器1 [ 8 ] = { 0×28 为0x18 0xB4 ×49 0x0C 0×00 0×00 0x7C } ;
字节传感器2 [ 8 ] = { 0×28 的0xCC 0x19 ×49 0x0C 0×00 0×00 为0xBB } ;
字节传感器3 [ 8 ] = { 0×28 0x19 0xEF 0x48 0x0C 0×00 0×00 0×21 } ;

该代码的设置部分与前面的示例相同。

在循环中,我们调用该printTemperature(DeviceAddress address)函数。在此自定义函数中,我们使用getTempC(address)getTempF(address)从地址作为参数传递的传感器中获取温度。

void printTemperature DeviceAddress address {
//获取以摄氏温度为单位的设备地址:
浮动温度=传感器。getTempC 地址;
//获取以华氏度为单位的设备地址的温度:
float tempF =传感器。getTempF tempC ;
序列号。打印tempC ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。打印“ C |” ;
//以华氏度打印温度
序列号。打印tempF ;
序列号。打印“ \ xC2 \ xB0” ; //显示度数符号
序列号。println “ F”
}

 


DallasTemperature Arduino库的其他功能

DallasTemperature库具有一些其他有用的内置函数,而我在上面的示例中尚未介绍。因此,我在下面列出了其中一些:

setResolution()

此功能可用于设置温度数字转换的分辨率。正如我在引言中提到的那样,可以将其设置为9、10、11或12位,分别对应于0.5°C,0.25°C,0.125°C和0.0625°C的增量。

您可能想知道为什么要更改分辨率,不是总是越高越好吗?选择较低分辨率的一个优势是,温度数字转换所需的时间要少得多。这意味着您可以在相同的时间内获取更多的温度读数。

从数据表中,我获得了以下信息:

解析度温度增量最长转换时间
9位0.5°摄氏度93.75毫秒
10位0.25°C187.5毫秒
11位0.125°摄氏度375毫秒
12位0.0625°C750毫秒

DallasTemperature库允许您使用函数设置分辨率setResolution()。可以将此功能添加到代码的设置或循环部分。

您可以如下设置所有连接的传感器的分辨率:

//将所有设备的分辨率设置为9、10、11或12位:
传感器。setResolution 9 ;

或者,您可以通过指定其地址为特定传感器单独设置它:

//连接到1-Wire总线的DS18B20传感器的地址
字节传感器1 [ 8 ] = { 0×28 为0x18 0xB4 ×49 0x0C 0×00 0×00 0x7C } ;
//将特定设备的分辨率设置为9、10、11或12位:
传感器。setResolution sensor1,9 ;

toFahrenheit()

此功能可用于将以摄氏度为单位的温度转换为华氏温度。

浮动温度=传感器。getTempCbyIndex 0 ;
float tempF = DallasTemperature :: toFahrenheit tempC ;

setHighAlarmTemp()和setLowAlarmTemp()

此功能以摄氏度为单位设置设备的内部高温和低温警报。

布尔hasAlarm()

当设备出现警报情况时,此函数返回true。您可以在此处找到这些功能的示例。

 


在I2C LCD上显示DS18B20温度读数

如果您想创建一个不需要计算机的独立项目,那么最好知道如何在LCD显示屏上显示温度读数。

使用下面的示例代码,您可以在16×2字符的I2C LCD上显示温度读数。

如下面的接线图所示,连接I2C LCD非常容易。您可以在下面查看我的详细教程以获取更多信息。

  • 如何使用Arduino控制字符I2C LCD

如果要使用标准的非I2C LCD,请看一下本文:

  • 如何在Arduino上使用16×2字符LCD
具有16×2字符I2C LCD和Arduino的DS18B20

下表中也提供了连接:

I2C LCD连接

I2C字符LCDArduino的
地线地线
VCC5伏
SDAA4
SCLA5

要使用I2C LCD,您将需要安装LiquidCrystal_I2C Arduino库。

在Arduino IDE中打开库管理器,然后搜索“ liquidcrystal_i2c”。现在向下滚动并查找Frank de Brabander的图书馆。选择最新版本,然后单击“安装”。

安装LiquidCrystal_I2C Arduino库

具有I2C LCD的DS18B20示例代码

/ * DS18B20 1-Wire数字温度传感器,带有16x2 I2C LCD和Arduino示例代码。
//包括所需的Arduino库:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
//定义1-Wire总线连接到Arduino的哪个引脚:
#定义ONE_WIRE_BUS 2
//创建一个oneWire类的新实例以与任何OneWire设备通信:
OneWire oneWire ONE_WIRE_BUS ;
//将oneWire引用传递给DallasTemperature库:
达拉斯温度传感器&oneWire ;
LiquidCrystal_I2C LCD 0×27 ,16,2 ;
//度数符号:
字节度[] = {
B00111,
00
B00111,
B00000,
B00000,
B00000,
B00000,
B00000
} ;
无效设置(){
//启动库:
传感器。开始();
//启动LCD并打开背光灯:
液晶显示器 初始化() ;
液晶显示器 背光();
//创建一个自定义字符:
液晶显示器 createChar 0,Degree ;
}
无效循环(){
//向总线上的所有设备发送命令以执行温度转换:
传感器。requestTemperatures ();
//获取以摄氏度为单位的温度以获取设备索引:
浮动温度=传感器。getTempCByIndex 0 ; //索引0指向第一个设备
//在LCD上打印温度;
液晶显示器 setCursor 0,0 ;
液晶显示器 打印“温度:”
液晶显示器 setCursor 0,1 ;
液晶显示器 打印tempC ;
液晶显示器 0 ; //打印自定义字符
液晶显示器 打印“ C”
//等待1秒钟:
延迟1000 ;
}

您应该在LCD上看到以下输出:

DS18B20-16x2-I2C-LCD-输出

结论

在本教程中,我向您展示了如何在Arduino上使用DS18B20 1-Wire数字温度传感器。希望您觉得它有用且有用。如果您这样做了,请分享这篇文章与同样喜欢电子产品和制作东西的朋友。

我很想知道您计划使用这些传感器构建(或已经构建)哪些项目。如果您有任何疑问,建议或认为本教程中缺少任何内容, 请在下面留下评论。

请注意,保留注释是为了防止垃圾邮件。

这项工作已根据 知识共享署名-非商业性-相同方式共享4.0国际许可进行了许可。