基于Freertos的ESP-IDF开发——6.使用DHT1温湿度传感器

news2024/11/18 7:27:31

基于Freertos的ESP-IDF开发——6.使用DHT1温湿度传感器

  • 0. 前言
  • 1. DHT11驱动原理
  • 2. 完整代码
  • 3. 演示效果
  • 4. 其他FreeRtos文章

0. 前言

开发环境:ESP-IDF 4.3
操作系统:Windows10 专业版
开发板:自制的ESP32-WROOM-32E
准备一个DHT11温湿度传感器

DHT11是比较经典的入门级温湿度传感器,这节我们学习使用它来测得周边环境的温湿度数据。

1. DHT11驱动原理

在这里插入图片描述
在这里插入图片描述
其控制时序如下:

  1. 主机发送起始信号:主机将总线拉低至少18ms,然后拉高20-40us,等待DHT11响应。
  2. DHT11响应信号:DHT11在收到起始信号后,会将总线拉低80us,然后拉高80us,表示已经准备好发送数据。
  3. DHT11发送数据:DHT11会依次发送40位数据,每一位数据的时间长度为50us,高电平表示1,低电平表示0。
  4. 主机接收数据:主机在接收到每一位数据后,会等待50us,然后再接收下一位数据。
  5. 数据校验:DHT11发送完40位数据后,会再次将总线拉低50us,然后拉高80us,表示数据已经发送完毕。主机接收到数据后,需要进行校验,确保数据的正确性。
  6. 通信结束:主机在接收到数据后,需要将总线拉高至少40us,表示通信结束。

需要注意的是,DHT11的控制时序非常严格,如果时序不正确,可能会导致数据传输失败。因此,在使用DHT11时,需要仔细按照时序进行控制。

首先,我们将引脚设置为输出模式,并将其拉低20毫秒,然后将其拉高,最后将其设置为输入模式。

然后,我们等待DHT11的响应信号,并开始读取数据。

我们使用FreeRTOS的计时器来计算每个位的持续时间,并将其转换为0或1的位。

2. 完整代码

#include <string.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <nvs_flash.h>
#include <driver/rmt.h>
#include <soc/rmt_reg.h>
#include "driver/gpio.h" 
#include <esp_log.h>

#define DHT11_GPIO	26		// DHT11引脚定义
const static char *TAG = "DHT11_Demo";

// 温度是10倍,/10有1位小数
int temp_x10 = 123;
int humidity = 60;
const int channel = 0;

uint8_t DHT11_PIN = -1;
// 将RMT读取到的脉冲数据处理为温度和湿度
static int parse_items(rmt_item32_t *item, int item_num, int *humidity, int *temp_x10);


// DHT11 初始化
void DHT11_Init(uint8_t dht11_pin)
{
	DHT11_PIN = dht11_pin;
	const int RMT_CLK_DIV = 80;										// RMT计数器时钟分频器
	const int RMT_TICK_10_US = (80000000 / RMT_CLK_DIV / 100000);	// RMT计数器10us.(时钟源是APB时钟)
	const int rmt_item32_tIMEOUT_US = 1000;							// RMT接收超时us
	rmt_config_t rmt_rx = {
		.gpio_num = dht11_pin,
		.channel = channel,
		.clk_div = RMT_CLK_DIV,
		.mem_block_num = 1,
		.rmt_mode = RMT_MODE_RX,					// 接收模式
		.rx_config.filter_en = false,
		.rx_config.filter_ticks_thresh = 100,
		.rx_config.idle_threshold = rmt_item32_tIMEOUT_US / 10 * (RMT_TICK_10_US),
	};
	rmt_config(&rmt_rx);
	rmt_driver_install(rmt_rx.channel, 1000, 0);	// 安装驱动
	//rmt_driver_uninstall(rmt_rx.channel)			// 卸载驱动
}

// 将RMT读取到的脉冲数据处理为温度和湿度
static int parse_items(rmt_item32_t *item, int item_num, int *humidity, int *temp_x10)
{
	int i = 0;
	unsigned rh = 0, temp = 0, checksum = 0;
	if (item_num < 42){					// 检查是否有足够的脉冲数
		ESP_LOGI(TAG, "item_num < 42  %d",item_num);
		return 0;
	}
	item++;								// 跳过开始信号脉冲
	for (i = 0; i < 16; i++, item++){	// 提取湿度数据
		rh = (rh << 1) + (item->duration1 < 35 ? 0 : 1);
	}
	for (i = 0; i < 16; i++, item++){	// 提取温度数据
		temp = (temp << 1) + (item->duration1 < 35 ? 0 : 1);
	}
	for (i = 0; i < 8; i++, item++){	// 提取校验数据
		checksum = (checksum << 1) + (item->duration1 < 35 ? 0 : 1);
	}
	// 检查校验
	if ((((temp >> 8) + temp + (rh >> 8) + rh) & 0xFF) != checksum){
		ESP_LOGI(TAG, "Checksum failure %4X %4X %2X\n", temp, rh, checksum);
		return 0;
	}
	// 返回数据
	*humidity = rh >> 8;
	*temp_x10 = (temp >> 8) * 10 + (temp & 0xFF);
	return 1;
}


// 使用RMT接收DHT11数据
int DHT11_StartGet(int *temp_x10, int *humidity)
{
	RingbufHandle_t rb = NULL;
	size_t rx_size = 0;
	rmt_item32_t *item;
	int rtn = 0;
	//获得RMT RX环形缓冲区句柄,并处理RX数据
	rmt_get_ringbuf_handle(channel, &rb);
	if (!rb){
		return 0;
	}
	//发送20ms脉冲启动DHT11单总线
	gpio_set_level(DHT11_PIN, 1);
	gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT);
	ets_delay_us(1000);
	gpio_set_level(DHT11_PIN, 0);
	ets_delay_us(20000);

	//将rmt_rx_start和rmt_rx_stop放入缓存
	rmt_rx_start(channel, 1);
	rmt_rx_stop(channel);

	//信号线设置为输入准备接收数据
	gpio_set_level(DHT11_PIN, 1);
	gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT);

	//这次启动RMT接收器以获取数据
	rmt_rx_start(channel, 1);

	//从环形缓冲区中取出数据
	item = (rmt_item32_t *)xRingbufferReceive(rb, &rx_size, 2);
	if (item != NULL){
		int n;
		n = rx_size / 4 - 0;
		// 解析来自ringbuffer的数据值.
		rtn = parse_items(item, n, humidity, temp_x10);
		// 解析数据后,将空格返回到ringbuffer.
		vRingbufferReturnItem(rb, (void *)item);
	}
	//停止RMT接收
	rmt_rx_stop(channel);
	return rtn;
}

// 温度 湿度变量
int temp = 0,hum = 0;

// 主函数
void app_main(void)
{
	ESP_ERROR_CHECK(nvs_flash_init());
	vTaskDelay(100 / portTICK_PERIOD_MS);

	ESP_LOGI(TAG, "[APP] APP Is Start!~\r\n");
	ESP_LOGI(TAG, "[APP] IDF Version is %d.%d.%d",ESP_IDF_VERSION_MAJOR,ESP_IDF_VERSION_MINOR,ESP_IDF_VERSION_PATCH);
	ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
	ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
	
	DHT11_Init(DHT11_GPIO);
	while (1){
		if (DHT11_StartGet(&temp, &hum)){
			ESP_LOGI(TAG, "[%lld] temp->%i.%i C     hum->%i%%", esp_timer_get_time(), temp / 10, temp % 10, hum);
		}
		vTaskDelay(1000 / portTICK_PERIOD_MS);
	}
}

3. 演示效果

如图所示,这是我把它放在了我的电脑排风口附近测得的温度:
在这里插入图片描述

4. 其他FreeRtos文章

基于Freertos的ESP-IDF开发——0.Windows下espidf的环境搭建
基于Freertos的ESP-IDF开发——1.HelloWorld
基于Freertos的ESP-IDF开发——2.点亮一颗LED
基于Freertos的ESP-IDF开发——3.使用任务(上)
基于Freertos的ESP-IDF开发——3.使用任务(中)
基于Freertos的ESP-IDF开发——3.使用任务(下)
基于Freertos的ESP-IDF开发——4.使用任务的方式来点亮LED灯
基于Freertos的ESP-IDF开发——5.使用按键[不带消抖、带消抖、长按短按识别]

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

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

相关文章

【Element-ui】el-table大数据量渲染卡顿问题

1、场景描述 在项目开发中&#xff0c;遇到在表格中一次性加载完的需求&#xff0c;且加载数量不少&#xff0c;有几百几千条&#xff0c;并且每条都可能有自己的下拉框&#xff0c;输入框来做编辑功能&#xff0c;此时普通的el-table肯定会导致浏览器卡死&#xff0c;那么怎么…

Windows10 双网卡配置,轻松实现内外互通

1 背景 我平常需要连接外网查阅资料&#xff0c;聊天等&#xff0c;做实验时需要将写到的代码打包部署到内网服务器中&#xff0c;所以需要频繁地切换内外网&#xff0c;修改静态网络配置。很是苦恼。 2 方法 最近&#xff0c;我找到了几种解决办法。 方法一、…

uniapp DIY可视化工具 控件拖拽工具怎么开发/拖拽库/模板引擎

uniapp DIY可视化工具 控件拖拽工具怎么开发 答&#xff1a;需要 (**拖拽库**) &#xff08;**模板引擎**&#xff09;代码自动生成 python有哪些模板引擎 Jinja2是一个小型但快速且易于使用的以纯python编写的独立模板引擎&#xff08;最主要的模板&#xff09;Chameleon是T…

深度学习之卷积神经网络(CNN)

大家好&#xff0c;我是带我去滑雪&#xff01; 卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;是一种基于深度学习的前馈神经网络&#xff0c;主要用于图像和视频识别、分类、分割和标注等计算机视觉任务。它主要由卷积层、池化层、全连接…

【开源、应用】QT—TCP网络上位机的设计

本文设计一个终端控制的上位机软件&#xff08;如“设计目标”下图所示&#xff09;&#xff0c;可以和STM32、Adruino等通信实现无线局域网控制系统。 本文的通信内容和图表内容可以参考作者之前的文章 STM32ESP8266连接电脑Qt网络上位机——QT篇https://blog.csdn.net/qq_53…

【STM32G431RBTx】备战蓝桥杯嵌入式→决赛试题→第六届

文章目录 前言一、题目二、模块初始化三、代码实现interrupt.h:interrupt.c:main.h:main.c: 四、完成效果五、总结 前言 无 一、题目 二、模块初始化 1.LCD这里不用配置&#xff0c;直接使用提供的资源包就行 2.ADC:开启ADCsingle-ended 3.LED:开启PC8-15,PD2输出模式就行了…

【JVM001】宋红康JVM字节码举例

宋红康JVM字节码举例 1 Integer package jvmT; public class IntegerTest {public static void main(String[] args) {Integer i 5;int y 5;System.out.println(iy); //trueInteger i6 5;Integer y6 5;System.out.println(i6y6);//trueInteger i5 128;Integer y5 128;System.…

SpringBoot中使用lombok

1.添加依赖 在项目的根目录中找到pom.xml&#xff0c;在dependencies下复制这段代码 <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifac…

解决Python爬虫中selenium模块中的find_element_by_id方法无法使用

如有错误&#xff0c;敬请谅解&#xff01; 此文章仅为本人学习笔记&#xff0c;仅供参考&#xff0c;如有冒犯&#xff0c;请联系作者删除&#xff01;&#xff01; 我们在学习selenium模块的时候&#xff0c;经常会用到 browser.find_element_by_id命令&#xff0c;但随着se…

代码随想录算法训练营第四十六天 | bool的背包题,细节多

139.单词拆分 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;动态规划之完全背包&#xff0c;你的背包如何装满&#xff1f;| LeetCode&#xff1a;139.单词拆分_哔哩哔哩_bilibili 状态&#xff1a;不会做&#xff0c;不知道怎么把bool类型与背包…

推荐系统系列之推荐系统概览(下)

在推荐系统概览的第一讲中&#xff0c;我们介绍了推荐系统的常见概念&#xff0c;常用的评价指标以及首页推荐场景的通用召回策略。本文我们将继续介绍推荐系统概览的其余内容&#xff0c;包括详情页推荐场景中的通用召回策略&#xff0c;排序阶段常用的排序模型&#xff0c;推…

软件测试实验:loadrunner的高级使用

目录 前言实验目的实验内容实验要求实验过程loadrunner中插入事务与集合点loadrunner中插入检查点loadrunner中参数化-table分析报告功能loadrunner手动设置场景loadrunner监视图标 总结 前言 本实验主要介绍了loadrunner这一强大的性能测试工具的高级使用方法&#xff0c;包括…

python实现九宫格的车辆路径轨迹上位机界面

实验环境&#xff1a;wxFormBuilder v3.5 python3.7.5 MC9S12G128开发板 基本功能&#xff1a;控制开发板上的按键&#xff0c;模拟车辆移动的上下左右四个方位&#xff0c;通过can通信告诉上位机界面&#xff0c;车辆轨迹的移动方位&#xff1b; 1. python重新封装control…

技巧:jetbrain全家桶系列如何撤销已经提交本地仓库但还没push的commit

目录 1. 哎呀&#xff0c;不小心把不能提交的“机密”加入commit了2. 使用reset来修复的话要注意有坑&#xff0c;选Soft和Mixed&#xff0c;千万别选Hard和Keep3. 使用revert&#xff0c;只能修修补补&#xff0c;但commit还在&#xff0c;当然有好处是会留下使用痕迹&#xf…

异常处理机制

编程错误 编写程序时遇到的错误可大致分为 2 类&#xff0c;分别为语法错误和运行时错误。 语法错误 语法错误&#xff0c;也就是解析代码时出现的错误。当代码不符合Python语法规则时&#xff0c;Python解释器在解析时就会报出SyntaxError语法错误&#xff0c;与此同时还会…

服务(第二十六篇)redis的主从复制、哨兵、集群

主从复制&#xff1a; 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(Master)&#xff0c;后者称为从节点(Slave)&#xff1b;数据的复制是单向的&#xff0c;只能由主节点到从节点。 原理&#xff1a; 主从关系确定…

[算法前沿]--009-HuggingFace介绍(大语言模型底座)

基础介绍 HuggingFace 是一家专注于自然语言处理(NLP)、人工智能和分布式系统的创业公司,创立于2016年。最早是主营业务是做闲聊机器人,2018年 Bert 发布之后,他们贡献了一个基于 Pytorch 的 Bert 预训练模型,即 pytorch-pretrained-bert,大受欢迎,进而将重心转向维护…

PoseiSwap以2500万美元估值,再获新一轮融资

近日&#xff0c;Nautilus Chain 上的首个 DEX PoseiSwap 宣布&#xff0c;其目前已经以 2500 万美元的估值&#xff0c;从 Gate Labs、Emurgo Ventures、Republic以及Cipholio Ventures 等行业顶级投资机构中&#xff0c;获得了新一轮的融资&#xff0c;不过目前该融资的具体数…

asp.net网上捐赠系统

一该源码功能十分的全面&#xff0c;具体介绍如下&#xff1a; 本版本软件主要完成三个功能&#xff1a; 1、建立网上捐赠功能 实现网上捐赠程序自动化&#xff0c;智能化&#xff0c;在捐赠者与受捐者填写各种资料后&#xff0c;自动保存方便以后调阅查询&#xff0c…

Java【网络编程1】详解DatagramSocket和DatagramPacket类, 逐行代码解析如何服务器客户端通信(附代码)

文章目录 前言一、认识 Socket(套接字), TCP 协议和 UDP 协议1, 什么是 Socket(套接字)2, 浅谈 TCP 协议和 UDP 协议的区别和特点 二、基于 UDP 协议的 Socket API1, DatagramSocket 类2, DatagramPacket 类 三、逐行代码解析网络编程1, 逐行解析客户端1.1, 核心成员方法 start…