百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

ESP8266-玩转DHT11温湿度和DS18B20温度模块

bigegpt 2024-08-05 11:52 10 浏览

DHT11温湿度模块

模块概述

DHT11数字温湿度传感器是一款温湿度复合传感器。每个DHT11传感器都在极为精确的湿度校验室中进行校准,校准系数储存在OTP内存中,传感器在检测信号时会调用这些校准系数。采用单总线接口使系统集成变得简易快捷,信号传输距离可达20米以上。

从DHT11的规格书可以看到,模块的温、湿度分辨率都是1,所以DHT11获取数值的小数部分都为0(规格书上说当前小数部分用于以后扩展,现读出为零)。据说新版本DHT11温度分辨率是0.1度,有小数部分。笔者购买的DHT11模块是没有小数部分的。

笔者使用的DHT11模块:

数据通信格式

模块的DATA引脚用于和微控制器通信,通过单总线协议,每次通讯时间4ms左右,具体数据格式如下:

一次完整的数据传输为40bit,高位先出。

数据格式:

  • 8bit湿度整数数据 + 8bit湿度小数数据 + 8bi温度整数数据 + 8bit温度小数数据+ 8bit校验和

注: 规格书指出:当前小数部分用于以后扩展,现读出为零。

若想了解单总线通信过程中信号的电平状态,详见DHT11规格书,这里就不再叙述了,网上也有很多讲解单总线协议的文章。

注:在编程时,采样周期间隔不得低于1秒钟。

模块编程示例

DHT模块接口介绍

先让NodeMCU固件开启对DHT模块的支持,具体操作见 ESP8266之NodeMCU固件编译 篇。

#define LUA_USE_MODULES_DHT    // 启用DHT模块

启用该模块后,我们就可以直接使用DHT的相关接口调用,完成对模块的操作。

查看NodeMCU的官方文档,找到DHT模块部分,如下图:

  • dht.read() 读取各种DHT传感器,包括DHT11、21、22、33、44湿度温度传感器。
  • dht.read11() 读取DHT11湿度温度传感器。
  • dht.readxx() 读取除DHT11之外的所有DHT传感器。

这里笔者使用dht.read11() 来获取DHT11模块的数据。

dht.read11() 接口详解

语法:dht.read11(pin)

参数:DHT11传感器的引脚号(不能为0),类型为数字。

返回:

  • status 返回操作的状态信息
  • temp 温度
  • humi 湿度
  • temp_dec 温度小数部分
  • humi_dec 湿度小数部分

注: 如果使用浮点固件,则temp和humi是浮点数。若果使用的是整数固件,则最终值必须从temp和temp_dec / humi和hum_dec连接在一起。

程序示例

如何获取DHT温湿度数据

将以下代码保存为dht11.lua文件(文件名也可以是其他,后缀一定要是.lua)。

--[[-------------------------------------NodeMCU | ESP8266 | NodeMCU | ESP8266  Pin   |   Pin   |   Pin   |   Pin-------------------------------------  D0    | GPIO16  |  D7     | GPIO13  D1    | GPIO5   |  D8     | GPIO15  D2    | GPIO4   |  D9     | GPIO3  D3    | GPIO0   |  D10    | GPIO1  D4    | GPIO2   |  D11    | GPIO9  D5    | GPIO14  |  D12    | GPIO10  D6    | GPIO12  |         |---------------------------------------]]-- 定义DHT11模块通信引脚为D4,对应ESP8266的GPIO2pin = 4-- 函数:DHT11模块获取数据function mydht11()    -- 获取DHT数据    status, temp, humi, temp_dec, humi_dec = dht.read11(pin)    -- 判断状态    if status == dht.OK then        -- 整型固件示例        print(string.format("FW:Integer, DHT Temperature:%d.%03d; Humidity:%d.%03d",              math.floor(temp),              temp_dec,              math.floor(humi),              humi_dec        ))        -- 浮点型固件示例        print("FW:Float, DHT Temperature:"..temp.."; ".."Humidity:"..humi.."\n\r")    -- checksum错误    elseif status == dht.ERROR_CHECKSUM then        print( "DHT Checksum error." )    -- 数据读取超时错误    elseif status == dht.ERROR_TIMEOUT then        print( "DHT timed out." )    end -- if()end -- mydht11()-- 主函数function main()    -- 每2秒获取一次数据。V3.0.x版本和V0.5.x版本在定时器使用上有差异。    local dht_timer = tmr.create()    dht_timer:alarm(2000, tmr.ALARM_AUTO, function() mydht11() end)end    -- main()-- 执行主函数main()

打开ESPlorer工具,连接ESP8266模块(或者NodeMCU开发板),上传dht11.lua文件,点击reload按钮,刷新一下,就可以看到dht11.lua文件已经上传到ESP8266里了,点击dht11.lua,效果如下图。

可以看到,不论是使用整型还是浮点型,最终结果小数部分始终为0。

实物接线图如下:

在WEB页面上显示温湿度信息

要想在web页面上显示温湿度信息,首先我们的ESP8266必须得连上网络。

1) ESP8266模块联网

将一下代码保存为 connect_wifi.lua 文件,其中的wifi名 WIFI_NAME 和密码 WIFI_PASSWD,改为自己的wifi名和密码。

-- 连接到指定的wifi (这里不将配置保存到flash)print("Connecting WIFI...")wifi.setmode(wifi.STATION)        -- 设置wifi模式为客户端模式station_cfg={}station_cfg.ssid = "WIFI_NAME"        -- 设置wifi名station_cfg.pwd  = "WIFI_PASSWD"    -- 设置wifi密码station_cfg.save = false            -- 不将配置保存到flashwifi.sta.config(station_cfg)        -- 开始配置wifiwifi.sta.connect()                    -- 连接wifimytimer = tmr.create()                -- 创建一个定时器,检测连接wifi是否成功mytimer:alarm(1000, tmr.ALARM_AUTO, function()     if wifi.sta.getip() == nil then -- 没有获取到IP,连接失败,1s后继续检测        print("IP unavaiable, Waiting...")     else        mytimer:stop()               -- 连接成功,停止定时器        print("Config done, IP is "..wifi.sta.getip())  -- 打印IP地址    end end)

将 connect_wifi.lua 文件上传到ESP8266中,刷新文件,点击 connect_wifi.lua 开始连接wifi,如下图。

可以看到,成功获取了IP地址,表示ESP8266已经接入网络中。

2)实现web界面显示的代码

将一下代码到存到 dht-web.lua 文件,并上传到esp8266中。

-- 定义DHT11通信引脚。pin = 4-- 实现一个简单地 HTTP服务器srv = net.createServer(net.TCP)-- 监听80端口srv:listen(80, function(conn)    conn:on("receive", function(sck, payload)        print(payload)        -- 获取温湿度信息        local status, temp, humi, temp_dec, humi_dec = dht.read11(pin)        -- 创建一个buf,用于存放web端的代码        local buf = "";        -- 让页面每3秒自动刷新一次        buf = buf.."<meta http-equiv="\"refresh\"" content="\"3\"">";        -- 设置页面编码,防止中文乱码        buf = buf.."<meta charset="\"utf-8\"">";        buf = buf.."<h2>HELLO DHT11</h2>";          buf = buf.."<p>当前温度: "..temp.."."..temp_dec.."'C</p>";          buf = buf.."<p>当前湿度: "..humi.."."..humi_dec.."%</p>";         sck:send(buf)    end)    conn:on("sent", function(sck) sck:close() end)end)

注: 新建文本是utf-8,代码中的编码就改为utf-8,保持编码一致性,否则中文显示会乱码。

上传 dht-web.lua 文件后,点击刷新,再点击 dht-web.lua,执行脚本。

打开浏览器,在地址栏输入esp8266的IP地址,就可以看到温湿度信息了,如下图。

由于笔者web端不熟,在此只能给一个简单的示例。至此,DHT11模块编程就介绍完了。


DS18B20温度模块

模块概述

DS18B20数字温度计提供9位至12位摄氏温度测量,并具有报警功能,具有非易失性用户可编程的上、下触发点。DS18B20通过1-Wire总线通信,根据定义只需要一条数据线(和GND)与中央微处理器通信。此外,DS18B20可以直接从数据线获得功率(“寄生功率”),消除了外部电源的需要。

每个DS18B20都有一个独特的64位串行代码,它允许多个DS18B20在同一单线总线上运行。因此,使用一个微处理器来控制分布在一个大区域的许多DS18B20s是很简单的。可以从该特性获益的应用包括暖通空调环境控制、建筑内部温度监控系统、设备或机械,以及过程监控和控制系统。

DS18B20的核心功能是它的直接数字温度传感器。温度传感器的分辨率可由用户配置为9位、10位、11位或12位,分别对应0.5℃、0.25℃、0.125℃和0.0625℃的增量。开机时的默认分辨率是12位。

笔者的DS18B20模块:

内存数据格式介绍

上图中:

  • BYTE0和BYTE1分别包含温度寄存器的LSB和MSB。这些字节是只读的。
  • BYTE2和BYTE3提供对TH和TL寄存器的访问,对应用户字节1和2。
  • BYTE4是配置寄存器,用来配置转换精度,9~12 位。
  • BYTE5~7保留。
  • BYTE8是CRC校验。

下图是温度LSB和MSB格式信息。

比如温度为+85度,计算如下:

  • BYTE0: 50H (LSB)
  • BYTE1: 05H (MSB)

温度计算:MSB左移8位,再或上LSB,最后乘以对应的分辨率(默认12bit,对应0.0625)。

Temp = ((BYTE1 << 8) | BYTE0) * 0.0625;

或者:

Temp = (BYTE1 * 256 + BYTE0) * 0.0625;

温度的正负号,由bit11 ~ bit15位确定,比如温度为-55度,计算如下:

  • BYTE0: 90H (LSB)

* BYTE1: FCH (MSB)

unsigned short T=0;    // 16bit临时变量unsigned flag = 0;     // 符号标志float Temp = 0;        // 存放最终温度结果if (BYTE1 & 0xF8) {   // 负数    flag = 1;    T = (BYTE1 << 8) | BYTE0;    T = (~T) + 1;    Temp = T * 0.0625;} else {              // 正数    flag = 0;    Temp = ((BYTE1 << 8) | BYTE0) * 0.0625;}// 最后由flag标志,来确定温度的正负号。if (flag) {    Temp = -Temp;}

上图是不同转换精度,对应所需的转换时间。默认12bit转换精度,转换一次温度需要750ms,即编程时,温度采样时间间隔必须大于750ms,否则读取的温度数据可能会有误。

模块编程示例

模块接口介绍

首先NodeMCU固件开启对DS18B20模块的支持,具体操作见 ESP8266之NodeMCU固件编译 篇。

#define LUA_USE_MODULES_OW      // 为啥是OW,见下文。

和DHT模块一样,启用该模块后,我们就不用自己编写单总线协议的驱动代码,直接使用DS18B20的相关接口调用就能完成对模块的操作。

查看NodeMCU的官方文档,找到DS18B20模块部分,如下图:

如上图,官方将DS18B20归在OW模块中,所以在配置固件时,要开启OW模块,才能支持DS18B20。

接口应用介绍

1)require() 创建对象

请求一个DS18B20对象。

ds18b20 = require("ds18b20")

2) 释放对象

ds18b20 = nilpackage.loaded["ds18b20"] = nil

3) ds18b20.read_temp() 获取温度

语法:

read_temp(callback, pin, unit, force_search, save_search)

参数:

  • callback 在所有转换完成时接收所有结果。回调函数有一个参数:一个由传感器地址和一个温度值(字符串表示整数版本)寻址的数组。
  • pin 单线总线通信的引脚。如果为nil,则默认使用GPIO0 (D3)。
  • unit 单位可以是摄氏(“C”或ds18b20.C)、开尔文(“K”或ds18b20.K)或华氏度(“F”或ds18b20.F)。如果没有指定(nil),则是最后使用过单位。
  • force_search 如果不是nil,总线搜索设备在读出之前被执行。如果为nil,则使用内存中现有的传感器列表。如果还没有对总线进行搜索,也会执行搜索。
  • save_search 如果没有nil,则将传感器保存到文件ds18b20_save.lc。当read_temp被调用时,内存中的传感器列表为空并且文件ds18b20_save.lc出现,然后传感器地址从文件加载-当从电池和深度睡眠运行时-立即读出执行可用(没有总线扫描)。

程序实例

获取DS18B20温度数据

1) 方法1:使用ds18b20官方文档的示例,需要先下载 ds18b20.lua 文件,上传到esp8266。

Since Origin / Contributor Maintainer Source 2014-12-08 Huang Rui Huang Rui ds18b20.lua

将以下代码保存到ds18_test.lua 文件,上传到esp8266中。代码来自官方示例,稍作修改,用于连续读取温度。

local t = require("ds18b20")local pin = 4   -- 设置ds18b20数据引脚function readout(temp)  if t.sens then    print("Total number of DS18B20 sensors: ".. #t.sens)    for i, s in ipairs(t.sens) do      print(string.format("  sensor #%d address: %s%s",  i, ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(s:byte(1,8)), s:byte(9) == 1 and " (parasite)" or ""))    end  end  for addr, temp in pairs(temp) do    print(string.format("Sensor[%s] Temp: %s °C", ('%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X'):format(addr:byte(1,8)), temp))  end  -- Module can be released when it is no longer needed--[[ 用定时器连续读取,所以注释以下代码  t = nil  package.loaded["ds18b20"] = nil--]]end-- 每隔1秒读取一次温度local dht_timer = tmr.create()dht_timer:alarm(1000, tmr.ALARM_AUTO, function()     t:read_temp(readout, pin, t.C)end)

刷新文件,直接点击 ds18_test.lua ,即可看到温度获取成功。

2) 方法2:使用ow单总线模块,实现ds18b20的温度获取,代码来自官方ow模块示例,如下。

将以下代码保存到ds.lua文件,上传到esp8266中。

-- 18b20 Examplepin = 4   -- 设置ds18b20数据引脚ow.setup(pin)addr = ow.reset_search(pin)addr = ow.search(pin)if addr == nil then  print("No device detected.")else  print(addr:byte(1,8))  local crc = ow.crc8(string.sub(addr,1,7))  if crc == addr:byte(8) then    if (addr:byte(1) == 0x10) or (addr:byte(1) == 0x28) then      print("Device is a DS18S20 family device.")      tmr.create():alarm(1000, tmr.ALARM_AUTO, function()          ow.reset(pin)          ow.select(pin, addr)          ow.write(pin, 0x44, 1) -- convert T command          tmr.create():alarm(750, tmr.ALARM_SINGLE, function()              ow.reset(pin)              ow.select(pin, addr)              ow.write(pin,0xBE,1) -- read scratchpad command              local data = ow.read_bytes(pin, 9)              print(data:byte(1,9))              local crc = ow.crc8(string.sub(data,1,8))              print("CRC="..crc)              if crc == data:byte(9) then                 local t = (data:byte(1) + data:byte(2) * 256) * 625                 local sgn = t<0 and -1 or 1                 local tA = sgn*t                 local t1 = math.floor(tA / 10000)                 local t2 = tA % 10000                 print("Temperature="..(sgn<0 and "-" or "")..t1.."."..t2.." 'C")              end          end)      end)    else      print("Device family is not recognized.")    end  else    print("CRC is not valid!")  endend

刷新文件,点击ds.lua,即可看到成功获取温度。如下图。

至此,DS18B20模块编程就介绍完了。

相关推荐

Linux 命令 ncftp(文件传输)——想玩转linux就请一直看下去

我是IT悟道,点击右上方“关注”,每天分享IT、科技、数码方面的干货。Linuxncftp命令Linux命令大全Linuxncftp命令用于传输文件。FTP让用户得以下载存放于服务器主机的文件,...

玩转 Linux 之:磁盘分区、挂载知多少?

今天来聊聊linux下磁盘分区、挂载的问题,篇幅所限,不会聊的太底层,纯当科普!!1、Linux分区简介1.1主分区vs扩展分区硬盘分区表中最多能存储四个分区,但我们实际使用时一般只分为两...

一文带你了解 Linux 文件权限,从基础到高级

在Linux中,每个文件和目录都关联了一组权限,定义了不同用户对其的访问能力。权限分为三类:读取(read,r)、写入(write,w)和执行(execute,x),分别用字母r、w、x...

Linux 使用 socat 让云服务器作为跳板机的方法

概念三台机器:客户端A(192.168.1.11)服务器B(192.168.1.88)跳板机C(192.168.1.32)实现A与B的双向数据传输,本该这样:A<...

Linux启动流程之ROM-CODE(linux启动详解)

1.从哪里开始?下图是AM335X核心板和功能框图:AM335X核心板的存储信息如下:AM335X核心板运行linux系统,在这里提出一个问题:上电后指令从哪里开始执行?DDRorEMMC?2....

「Linux」——select和epoll详解(linux epoll详解)

select和epoll详解select和epoll的区别(面试常考)select一、什么是select1.select函数原型2.参数解释3.参数timeout取值4.返回值5.监控原理二、sele...

Linux中使用输入输出和错误重定向, 赶紧收藏!

Linux中的每个进程都提供三个打开的文件(通常称为文件描述符),分别是标准的输入、输出和错误文件。StandardInput是键盘,抽象为文件,使编写脚本和程序更容易。StandardOut...

「正点原子Linux连载」第七十一章Linux 4G通信实验

1)实验平台:正点原子Linux开发板2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》关注官方微信号公众号,获取更多资料:正点原子第七十一章Linux4G通信实验前面我们学习了如何在Li...

LSM Oops 内存错误根因分析与解决

作者简介:吴文涵,图形算法出身,同时热爱linux内核开发的工程师,喜欢推导并乐于分享。版权声明:本文最先发表于“泰晓科技”微信公众号,欢迎转载,转载时请在文章的开头保留本声明。Oops是...

连你家电器的算力都不放过,新发现Linux恶意软件用IoT设备挖矿

萧箫发自凹非寺量子位|公众号QbitAI继电脑和手机后,挖矿病毒也盯上了IoT设备。无论是智能冰箱、彩电还是洗衣机,但凡有点算力的(物联网和端侧)设备都可能被这种病毒感染,用于挖掘加密货币等...

Linux-AT命令干货分享,还不赶紧收藏!

苹果iOS 26锁屏大升级:更个性更沉浸 有五大亮点

【CNMO科技消息】CNMO注意到,苹果近日在iOS26开发者预览版中推出了多项锁屏界面创新功能,可以大幅提升用户个性化设置与操作便捷性。这些更新不仅优化了视觉体验,还通过技术手段增强了交互效率,为...

福彩 3D 第 2025178 期:心水407 !大小奇偶双平衡 + 跨度适配,速收藏

福彩3D第2025178期:497后和值回落!五维分析+形态调整策略福彩3D2025177期开奖号码497,组六形态,大小比2:1,奇偶比1:2,和值20,跨度5。面对大...

一加 Ace5 至尊版手机首发适配和平精英手游

7月8日消息,据用户反馈,一加Ace5至尊版手机开启新版本系统推送,升级包大小约6.83MB、版本号为15.0.2.215(CN01),适配了腾讯《和平精英》手游144Hz高刷。IT...

外媒称苹果今年秋季将推出超15款新品 远不止iPhone 17

【CNMO科技消息】2025年已过半程,有外媒指出苹果计划在今年秋季推出超过15款新产品,涵盖iPhone革新、M5芯片设备迭代、可穿戴设备升级及智能家居布局等。苹果1.iPhone17系列:产品...