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

news2024/11/23 6:17:44

前言

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

后续会把之前写过的硬件模块再写一遍,因为之前都是使用的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_0

void 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 18


void 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打印到电脑上方便我们查看数据。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1640514.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

傅里叶变换的推导过程-part1三角函数的正交性

1. 三角函数的正交性 1.0 提出问题 1.1 普通向量的正交 1.2 普通函数的正交 1.3 证明三角函数正交为0 1.3.1 cosnx.conmx = 0 , (m!=n) 1.3.2 cosmx.sinnx = 0 , s

【c++】继承学习(一):继承机制与基类派生类转换

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章我们来学习继承部分 目录 1.继承的概念和定义继承的定义继承基类成员的访问方式变化 2.基类和派生类对象赋值转换3.继承中的作用域 1.继承的概念和定义 …

JAVA 学习·泛型(二)——通配泛型

有关泛型的基本概念&#xff0c;参见我的前一篇博客 JAVA 学习泛型&#xff08;一&#xff09;。 协变性 泛型不具备协变性 在介绍通配泛型之前&#xff0c;先来看一下下面的例子。我们定义了一个泛型栈&#xff1a; import java.util.ArrayList; class GenericStack<E>…

python 11Pandas数据可视化实验

实验目的&#xff1a; 学会使用Pandas操作数据集&#xff0c;并进行可视化。 数据集描述&#xff1a; 该数据集是CNKI中与“中药毒理反应”相关的文献信息&#xff0c;包含文章题目、作者、来源&#xff08;出版社&#xff09;、摘要、发表时间等信息。 实验要求&#xff1…

建设智慧校园,让师生生活更便捷

在时代快速发展的大背景下&#xff0c;建设智慧校园是学校发展的要求&#xff0c;也是广大师生更加期待的。智慧校园建设是集教学、科研、管理、学习、生活为一体的高度智能化的学习生活环境。整合、整合、优化资源&#xff0c;提高工作、学习、科研效率&#xff0c;提高学校管…

java递归-(迷宫问题)

前面 这里我们来玩个有趣的事情&#xff0c;链接是0221_韩顺平Java_老鼠出迷宫1_哔哩哔哩_bilibili 我们要找的是小老鼠按路径走到右下点 要点 我们这里方法调用时对于引用类型&#xff1a;如java中引用数据类型有哪些&#xff1f;_java引用数据类型-CSDN博客 会共享引用类型…

室内定位:技术与应用

书籍&#xff1a;Indoor Positioning: Technologies and Performance 作者&#xff1a;Samama, Nel 出版&#xff1a;IEEE 书籍推荐-《室内定位&#xff1a;技术与应用》https://mp.weixin.qq.com/s/wcx9FvKQks-ja1wbEM5PJg 01 书籍介绍 本书提供了实现室内定位的各种方法…

huggingface里如何查看具体任务的评估指标

如果我们在做一个模型训练任务的时候&#xff0c;可能会不知道这个任务在评估的时候使用什么指标&#xff0c;那么huggingface里边为我们提供了参考&#xff1a; 下面就来看看吧&#xff1a; https://huggingface.co/https://huggingface.co/ 点击"Docs"&#xff…

Linux系统配置JAVA环境

一、jar包下载 官网:https://www.oracle.com/java/technologies/downloads 二、文件上传 上传到linux服务器 解压 下面是解压的路径 三、修改profile文件 修改etc下的profile文件&#xff0c;添加以下内容 vim /etc/profileexport JAVA_HOME/root/java/jdk-17.0.11 expo…

0.96寸OLED显示屏模块

一、OLED模块简介 名称&#xff1a;0.96寸OLED显示屏 组成&#xff1a;一块PCB板&#xff08;OLED的外围电路&#xff09;、屏幕、驱动芯片&#xff08;内嵌在屏幕下方&#xff09; 驱动芯片&#xff1a;SSD1306&#xff08;本篇是基于此芯片&#xff09; / SSD1315&#xf…

Grafana 添加一台管理服务器

1、修改prometheus.yml 添加新服务器信息 2、重启pro 3、导入node文件 4、启动node 5、检验数据

【MyBatis】深入解析MyBatis:高效操作数据库技术详解

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【MyBatis】深入解析MyBatis&#xff1a;高效操作数据库技术详解 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 动态SQL1. \<if>标签2. \<trim&…

IO端子介绍及GPIO number计算

IO端子介绍 &#xff08;引脚&#xff0c;针脚&#xff09; 嵌入式系统的主芯片&#xff0c;有的IO资源少&#xff0c;有的IO资源多。 少的是这样的封装&#xff0c;IO管脚都在四周&#xff1b; 多的是这样的封装&#xff0c;IO 的PAD都在下面&#xff1a; MCU或MPU&#xff0c…

【软考高项】三十、成本管理基础内容

一、管理基础 就某些项目&#xff0c;特别是小项目而言&#xff0c;成本估算和成本预算之间的关系极其密切&#xff0c;以致可以将其视为一个过程&#xff0c;由一个人在较短的时间内完成。 项目成本管理重点关注完成项目活动所需资源的成本&#xff0c;但同时也考虑项目决策…

408数据结构-二叉树的遍历 自学知识点整理

前置知识&#xff1a;二叉树的概念、性质与存储结构 二叉树的遍历 二叉树的遍历是指按某条搜索路径访问树中每个结点&#xff0c;使得每个结点均被访问一次&#xff0c;而且仅被访问一次。 二叉树的递归特性: ①要么是棵空二叉树&#xff1b; ②要么就是由“根节点左子树右子树…

DiffusionGAN ——最快的小波扩散模型应用研究

介绍 扩散模型最近出现并迅速发展&#xff0c;吸引了许多研究人员的兴趣。这些模型能从随机的噪声输入生成高质量的图像。在图像生成任务中&#xff0c;它们的表现尤其优于最先进的生成模型&#xff08;GANs&#xff09;。扩散模型可以灵活地处理各种条件输入&#xff0c;从而…

蓝桥杯练习系统(算法训练)ALGO-949 勇士和地雷阵

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 勇士们不小心进入了敌人的地雷阵&#xff08;用n行n列的矩阵表示&#xff0c;*表示某个位置埋有地雷&#xff0c;-表示某个…

ASP.NET图书馆管理信息系统

摘  要 本文首先阐述了基于.NET Framework平台的图书馆管理信息系统的开发背景以及其实践意义&#xff0c;其次说明了图书馆管理信息系统的功能以及相比同类软件的创新之处。然后就图书馆管理系统开发中所使用的一些的技术进行研究探讨。主要针对数据库的设计技术、存储过程…

2024五一杯数学建模竞赛A题完整成品论文和代码分析:建立钢板切割的工艺路径动态规划、贪心与分层优化模型

2024五一杯数学建模竞赛A题&#xff1a;建立钢板切割的工艺路径动态规划、贪心与分层优化模型 2024五一数学建模A题完整代码和成品论文获取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/gyoz9ou5upvkv6nx?singleDoc# 本文文章较长&#xff0c;建议先目录。经过不懈的…

基于深度学习检测恶意流量识别框架(80+特征/99%识别率)

基于深度学习检测恶意流量识别框架 目录 基于深度学习检测恶意流量识别框架简要示例a.检测攻击类别b.模型训练结果输出参数c.前端检测页面d.前端训练界面e.前端审计界面&#xff08;后续更新了&#xff09;f.前端自学习界面&#xff08;自学习模式转换&#xff09;f1.自学习模式…