【硬件模块】DHT11数字式温湿度传感器模块

2024-05-02 19:36

本文主要是介绍【硬件模块】DHT11数字式温湿度传感器模块,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

今天在这边新开一个系列,那就是硬件模块。

后续会把之前写过的硬件模块再写一遍,因为之前都是使用的STM32来驱动模块的,而现在我快速上手ESP32系列也快结束了,因此我在原本文章的基础上再加上使用ESP32来驱动的部分构成硬件模块这个系列。

当然了,也不是吃老本的,这个系列也会写一些之前都没用过的模块,今天就先以DHT11这个之前都没写过的模块来开个头。

DHT11

DHT11是一款数字式温湿度传感器,它采用了已校准的数字信号输出方式,使得测量结果更加准确可靠。该传感器集成了温度测量、湿度测量和数字信号输出等功能,可以实时监测环境的温度和湿度变化。

DHT11传感器内部包含一个湿度检测电容和一个NTC温度测量元件,以及一个高性能的8位微控制器来处理信号。当传感器暴露在环境中时,温度传感器和湿度传感器能够感知到环境的温度和湿度,并将其转换为电信号。随后,微控制器将这些电信号转换为数字信号,并通过单总线通信协议输出给微处理器。

DHT11传感器具有多种优点。首先,它采用数字信号输出,使得读取数据变得简单方便,只需通过一根数据线即可完成温湿度读取。其次,DHT11的价格相对较低,适合大规模应用和低成本项目。此外,它还支持多种平台和开发板,如Arduino、Raspberry Pi等,可以广泛应用于各种嵌入式系统和物联网设备。

然而,DHT11传感器也存在一些缺点。首先,其精度相对较低,温度精度为±2°C,湿度精度为±5%RH,可能无法满足一些高精度测量的需求。其次,DHT11的响应时间较慢,通常需要2秒以上才能完成一次温湿度测量。此外,其测量范围也有限制,温度测量范围为0°C~50°C,湿度测量范围为20%~90%RH。

在实际应用中,DHT11传感器常用于室内环境监测、气象站和气象监测、温湿度控制系统以及物联网项目等领域。例如,在家庭、办公室、实验室等室内环境中,DHT11可以帮助维持舒适的生活和工作环境,并及时采取调节措施。在构建小型气象站时,DHT11可用于监测当地的温度和湿度,为农业、气象学研究以及天气预报等提供重要数据。同时,在温室、温室大棚和养殖场等环境中,DHT11传感器可以实现温湿度的自动控制,提供适宜的环境条件。此外,在物联网项目中,DHT11也是常用的传感器之一,可以实时监测和传输温湿度数据。

综上所述,DHT11是一款功能强大、简单易用且成本较低的温湿度传感器,适用于多种应用场景。然而,在选择使用时需要根据具体需求考虑其精度、响应时间以及测量范围等因素。

以上介绍来自文心一言。

简单来说就是DHT11这个温湿度传感器相当便宜,但是代价就是精度很差。

引脚

其中1号引脚是VCC,2号引脚是数据线,3号引脚没有用,4号引脚是GND。

供电电压的范围是3.3~5.5V

使用的通信协议是1-Wire,所以只需要2号引脚一根数据线即可。

时序

第一步是DHT11上电后需要等待1s,然后处于一个上拉输入的状态。

对于我们的单片机(主机)来说,我们要做的就是等DHT11一秒钟,其他不用操作。

第二步就是我们主机发送起始信号告诉DHT11开始采集数据了。

我们先拉低数据线18~30ms,可以拉个20ms。

之后再拉高延时一会等待DTH11反应,然后改为上拉输入模式。

第三步是DHT11收到信号之后等待数据线的低电平结束后会再拉低数据线83us表示收到,然后再拉高数据线87us通知我们的主机接收数据。

对于我们主机来说,我们发送完上面的起始信号检测数据线是不是被拉低了,如果是,那么我们再等待数据线拉高回去。

DHT11一共会发送40位数据,这40位数据分别代表什么含义这个稍后再说。

我们先看看数据0和1的区别,它们一开始都是拉低54us,不一样的是数据0后面拉高23~27us,而数据1后面拉高了66~74us。

也就是说不管是什么数据,都是先拉低后拉高,不一样的是后面拉高的持续时间。

因此我们可以先等待数据线拉高,拉高之后延时30us,如果是数据0,那么我们读出的将会是低电平,如果是数据1,那么我们读出的是高电平。这样就算是读出了一个bit。

接下来为了时序能够接上,我们再等待数据线拉低(如果是数据0则不用等待,数据线就是拉低的状态)。

重复上面的步骤8次,我们就读出了一个Byte。

最后读完40个bit(5个Byte)之后,我们再来个结束信号。

实际上我们不需要什么操作,上面都是DTH11需要执行的。

我们只要在读出数据之后等待60us即可。

数据

现在我们来看看五个Byte都是些什么含义。

从头到尾依次是湿度的整数,湿度的小数(一直都是0,不需要管它),温度的整数,温度的小数,校验位。

一共有两个数据,湿度和温度。

其中湿度的小数一直都是0。温度的小数对应的值乘上0.1度就是对应的温度。

最后一个校验位是前四位加起来的值。如果前四位加起来不等于校验位,那么表示数据出错了。

需要注意的是前四位数相加的值需要强转成8bit的类型才能和校验位进行比较。

STM32驱动代码

下面的代码里涉及OLED显示和Delay延时函数的部分需要自己实现。

 OLED只是为了展示读取的数据,没有的小伙伴用串口通信打印到电脑上也可以。

延时函数网上随便一搜就有,也可以翻一下我之前的文章,直接复制粘贴也行。

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"#define DHT11_DATE_PROT GPIO_Pin_0void Z_DHT11_Init(void);
void Z_DHT11_Output(void);
void Z_DHT11_Input(void);
void Z_DHT11_SetDate(BitAction val);
uint8_t Z_DHT11_GetDate(void);
uint8_t Z_DHT11_GetByte(void);
void Z_DHT11_GetTemperatureAndHumidity(void);//初始化DHT11
void Z_DHT11_Init(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);Z_DHT11_Output();Z_DHT11_SetDate(1);Delay_s(1);
}//将数据线配置为输出模式
void Z_DHT11_Output(void){GPIO_InitTypeDef itd;itd.GPIO_Mode=GPIO_Mode_Out_PP;         //推挽输出itd.GPIO_Pin=DHT11_DATE_PROT;itd.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&itd);
}//将数据线配置为输入模式
void Z_DHT11_Input(void){GPIO_InitTypeDef itd;itd.GPIO_Mode=GPIO_Mode_IPU;            //上拉输入itd.GPIO_Pin=DHT11_DATE_PROT;itd.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&itd);
}void Z_DHT11_SetDate(BitAction val){GPIO_WriteBit(GPIOA,DHT11_DATE_PROT,val);
}uint8_t Z_DHT11_GetDate(void){return GPIO_ReadInputDataBit(GPIOA,DHT11_DATE_PROT);
}//读取一个Byte
uint8_t Z_DHT11_GetByte(void){uint8_t data;for(uint8_t i=0;i<8;i++){while(Z_DHT11_GetDate()==0);Delay_us(30);data<<=1;if(Z_DHT11_GetDate()==1) data|=1;while(Z_DHT11_GetDate()==1);}return data;
}uint8_t DTH11_Data[5];
//获取温湿度
void Z_DHT11_GetTemperatureAndHumidity(void){Z_DHT11_Output();Z_DHT11_SetDate(0);Delay_ms(20);Z_DHT11_SetDate(1);Delay_us(30);Z_DHT11_Input();if(Z_DHT11_GetDate()!=0) return;while(Z_DHT11_GetDate()==0);while(Z_DHT11_GetDate()==1);DTH11_Data[0]=Z_DHT11_GetByte();DTH11_Data[1]=Z_DHT11_GetByte();DTH11_Data[2]=Z_DHT11_GetByte();DTH11_Data[3]=Z_DHT11_GetByte();DTH11_Data[4]=Z_DHT11_GetByte();Delay_us(60);
}int main(void){OLED_Init();Z_DHT11_Init();while(1){Z_DHT11_GetTemperatureAndHumidity();if((uint8_t)(DTH11_Data[0]+DTH11_Data[2]+DTH11_Data[3])!=DTH11_Data[4]) continue;OLED_ShowNum(1,1,DTH11_Data[0],2);OLED_ShowNum(1,4,DTH11_Data[1],2);OLED_ShowNum(2,1,DTH11_Data[2],2);OLED_ShowNum(2,4,DTH11_Data[3],2);OLED_ShowNum(3,1,DTH11_Data[4],2);Delay_ms(500);}
}

数据可以正常读取,就是精度确实有点低。

ESP32驱动代码

其实只需要把STM32的代码改改就行了,差别不大。

ESP32的代码相比较STM32会更简洁一些。

因为ESP32可以将GPIO口初始化成既可以输入也可以输出,因此不需要像STM32那样切换GPIO口的模式。我们只需要初始化一次GPIO口的模式即可,记得加上上拉电阻。

#include <stdio.h>
#include <unistd.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"#define DHT11_DATE_PROT 18void Z_DHT11_Init(void);
void Z_DHT11_SetDate(uint8_t val);
uint8_t Z_DHT11_GetDate(void);
uint8_t Z_DHT11_GetByte(void);
void Z_DHT11_GetTemperatureAndHumidity(void);// 初始化DHT11
void Z_DHT11_Init(void){gpio_config_t init = {.intr_type = GPIO_INTR_DISABLE,         // 失能中断;.mode = GPIO_MODE_INPUT_OUTPUT,         // 输出模式.pin_bit_mask = (1ULL << DHT11_DATE_PROT),.pull_down_en = GPIO_PULLDOWN_DISABLE,  // 失能下拉模式.pull_up_en = GPIO_PULLUP_ENABLE,      // 使能上拉模式};gpio_config(&init);Z_DHT11_SetDate(1);vTaskDelay(1000/portTICK_PERIOD_MS);
}void Z_DHT11_SetDate(uint8_t val){gpio_set_level(DHT11_DATE_PROT,val);
}uint8_t Z_DHT11_GetDate(void){return gpio_get_level(DHT11_DATE_PROT);
}// 读取一个Byte
uint8_t Z_DHT11_GetByte(void){uint8_t data = 0;for (uint8_t i = 0; i < 8; i++){while (Z_DHT11_GetDate() == 0);usleep(30);data <<= 1;if (Z_DHT11_GetDate() == 1)     data |= 1;while (Z_DHT11_GetDate() == 1);}return data;
}uint8_t DTH11_Data[5];
// 获取温湿度
void Z_DHT11_GetTemperatureAndHumidity(void){Z_DHT11_SetDate(0);vTaskDelay(20/portTICK_PERIOD_MS);Z_DHT11_SetDate(1);usleep(30);if (Z_DHT11_GetDate() != 0) return;while (Z_DHT11_GetDate() == 0);while (Z_DHT11_GetDate() == 1);DTH11_Data[0] = Z_DHT11_GetByte();DTH11_Data[1] = Z_DHT11_GetByte();DTH11_Data[2] = Z_DHT11_GetByte();DTH11_Data[3] = Z_DHT11_GetByte();DTH11_Data[4] = Z_DHT11_GetByte();usleep(60);
}void app_main(void){Z_DHT11_Init();while (1){Z_DHT11_GetTemperatureAndHumidity();if ((uint8_t)(DTH11_Data[0] + DTH11_Data[2] + DTH11_Data[3]) != DTH11_Data[4])  continue;printf("%d,%d,%d,%d,%d\r\n",DTH11_Data[0],DTH11_Data[1],DTH11_Data[2],DTH11_Data[3],DTH11_Data[4]);vTaskDelay(1000/portTICK_PERIOD_MS);}
}

ESP32移植STM32代码成功,并且还可以直接通过printf打印到电脑上方便我们查看数据。

说好听一点叫移植,说不好听一点那就是把代码抄过来改改能跑就行。

我们在改代码的时候,函数声明什么的都可以不改,只需要把每个函数里的逻辑适配成我们要移植的芯片的逻辑就行。

这篇关于【硬件模块】DHT11数字式温湿度传感器模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/955009

相关文章

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

Python logging模块使用示例详解

《Pythonlogging模块使用示例详解》Python的logging模块是一个灵活且强大的日志记录工具,广泛应用于应用程序的调试、运行监控和问题排查,下面给大家介绍Pythonlogging模... 目录一、为什么使用 logging 模块?二、核心组件三、日志级别四、基本使用步骤五、快速配置(bas

Python datetime 模块概述及应用场景

《Pythondatetime模块概述及应用场景》Python的datetime模块是标准库中用于处理日期和时间的核心模块,本文给大家介绍Pythondatetime模块概述及应用场景,感兴趣的朋... 目录一、python datetime 模块概述二、datetime 模块核心类解析三、日期时间格式化与

Python如何调用指定路径的模块

《Python如何调用指定路径的模块》要在Python中调用指定路径的模块,可以使用sys.path.append,importlib.util.spec_from_file_location和exe... 目录一、sys.path.append() 方法1. 方法简介2. 使用示例3. 注意事项二、imp

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中