超详细!基于树莓派Python编程使用dht11温湿度模块

article/2025/8/25 17:29:27

超详细!基于树莓派Python编程使用dht11温湿度模块

前言:

本人树莓派小白(电路知识也很有限),在树莓派上使用dht11模块时没有在网络上找到 很详细的教程,因此经历两天的摸索才得以正确使用该模块,所以我萌生了写一篇较为详细的教程的想法。如果同为小白,仔细研究dht11的使用会为其他的模块使用打下坚实的基础(例如:超声波模块、寻路模块等),如果你没有耐心看完本文可去文章末尾拿代码。

一、材料

1.树莓派
2.dht11温度模块
3.杜邦线(买模块一般都会送)

二、连线

dht11模块包含三个引脚:VCC(正极3.3v)、DATA(数据传输口)、GND(负极或0电位)树莓派GPIO参考图(本文使用BOARD编码即下图的编码模式)
在这里插入图片描述
其中VCC接树莓派任意3.3v接口
DATA接树莓派任意GPIO(本文接12)
GND接树莓派任意GND
VCC与GND勿接反(据说接反必烧)

三、dht11通信原理及对应Python编程

1.首先,对进行准备工作,引入一些库(官网系统自带,无需安装)和定义一下引脚。

import RPi.GPIO as GPIO   #引入RPi.GPIO模块,并实例化为GPIO,简化后面的模块调用
import time                #引入time模块
GPIO.setmode(GPIO.BOARD)    #定义GPIO编码方式
time.sleep(2)               #由于dht11的采样周期间隔为2s,此处防止dht无方响应
Pin=12                      #定义引脚,使用哪个就定义哪个

2.DATA 用于树莓派与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分整数部分和小数部分,一次完整的数据传输为40bit(40个二进制数),高位先出(代码在第5点处一并说明)(dht11与树莓派的通信过程见下图)。
在这里插入图片描述

3.dht11默认处于高电平状态 ,当树莓派发送开始信号(1段大于18μs的低电平),dht11接收到树莓派的开始信号后会转为工作模式,此时应将树莓派转的GPIO转为高电平状态然后将GPIO转为输入模式用于接收dht11的信号。

GPIO.setup(Pin,GPIO.OUT)    #将GPIO设置为输出模式
GPIO.output(Pin,0)          #向dht11发送低电平(开始信号)(其中0可以用Flase、GPIO.low代替,下文的1同理)
time.sleep(0.02)            #低电平持续时间0.02s大于dht11要求的0.018s
GPIO.output(Pin,1)          #向dht11发送高电平(理论上可以取消,但是实际使用中不发送高概率出错)
GPIO.setup(Pin,GPIO.IN)     #将GPIO转为输入模式,用以接收dht11的信号

4.接收到开始信号后dht11首先会发送一段持续80μs的低电平信号和80μs的高电平信号以回复树莓派的开始信号,然后将会发送40bit(40个二进制数)的湿度温度数据,每个bit都将以一段持续50μs的低电平信号开始(信号的开头是一样的,因此无法判断是0还是1),然后续以一段时间不等的高电平信号,其中如果发送二进制"0"将持续26-28μs,二进制"1"将持70μs。因此后续编程将根据高电平信号持续的时间来判断dht11发送的信号是0还是1。(前三行赋值代码放到这里是便于理解,实际运行过程高概率因为数据接收不全卡死,在后面会介绍一下)

Bit=[]                     #定义列表,用以存储接收到的数据
Time=[]                    #存储数字0和数字1的高电位持续时间
K=0                         #定义循环初始值
while GPIO.input(Pin)==0:   #采用轮训检测dht的响应信号,如果输入高电平将跳出此循环(不懂可以查阅python的while continue用法)continue
while GPIO.input(Pin)==1:   #采用轮训检测dht的响应信号continue
while K<40:                 #循环40次用以接收dht11的40bit数据while GPIO.input(Pin)==0:#因为每bit数据以低电平开始,故此。continuebegin=time.time()       #低电平循环结束故此时是高电平信号,因此开始计时while GPIO.input(Pin)==1:#轮训高电平continueend=time.time()         #获取高电平信号的结束时间#Time.append(end-begin)#此处为了确定0和1的高电平持续时间if (end-begin)<0.00003: #检测高电平的持续时间判断输入是0还是1(0.00003可以自测一下,取一个适合你的时间)Bit.append(0)       #高电平小于0.00003s证明是0else:Bit.append(1)       #高电平大于0.00003s证明是1K=K+1                   #记录循环次数
#print(Time)				#观察时间特点以确定上文0.00003的取值

5.将得到40bit数据进行拆分、校验并转换为10进制数输出。

humidity1bit=Bit[0:8]       #根据dht11的信号原理获取所需的值(下同理)
humidity2bit=Bit[8:16]
temperature1bit=Bit[16:24]
temperature2bit=Bit[24:32]
checkbit = Bit[32:40]
humidity1=0
humidity2=0
temperature1=0
temperature2=0
check=0
for i in range(0,8):         #循环8次,将二进制数转换为十进制数humidity1+=humidity1bit[i]*(2**(7-i))humidity2+=humidity2bit[i]*(2**(7-1))temperature1+=temperature1bit[i]*(2**(7-i))temperature2+=temperature2bit[i]*(2**(7-i))check+=checkbit[i]*(2**(7-i))
temperature=temperature1+temperature2*0.1 #获取温度值(注意dht11的使用说明中明文写到整数位后是小数位故应乘0.1)
humidity=humidity1+humidity2*0.1        #(网上大部分都没乘0.1,他们的运行结果是整数,足可见网上的帖子都是复制粘着的水文)
checknum=temperature1+humidity1+temperature2+humidity2 #计算前32位数的值
if checknum==check:                         #检查前32位的值是否与校验位相等print("temp:%s,hum:%s"%(temperature,humidity))   #相等输出温度和湿度
else:print("dht11 check was wrong.  checknum:%s check:%s"%(

四、本人实际运行时遇到的一些错误

1.在准备阶段,由于dht11使用说明显示发送低电平开始信号后,可直接将GPIO调到输入模式。但是在实际操作过程中,将GPIO直接调到输入状态,后续接受到的数据高概率出现校验码不符的情况,如果在发送开始信号后加上发送高电平信号代码会减少此类错误。
2.本人第一次采用模块化编程,但是这种编程手段运行速度缓慢,会发生接收数据不全的情况,然后会卡到while循环的高电平状态,无法退出。
3.切记采用我这种检测高电平信号持续时间的方法,不要在whlie k <40:的循环内加入print等函数,不然会导致类似问题二循环不能退出的问题。
4.赋值语句要放到开头不然影响代码运行进度,而造成数据接收不全卡死在while循环内.(具体原因是dht11输出信号后会转入高电平状态,而赋值语句的加入影响代码运行进度使接收到的数据小于40bit而无法跳出while循环)

``

while K<40:while GPIO.input(Pin)==0:continuebegin=time.time()while GPIO.input(Pin)==1:      #我断点测试卡到这里,符合推测continueend=time.time()if (end-begin)<0.00003:Bit.append(0)else:Bit.append(1)K=K+1

五、完整代码及注释

import RPi.GPIO as GPIO   #引入RPi.GPIO模块,并实例化为GPIO,简化后面的模块调用
import time                #引入time模块
Bit=[]                     #定义列表,用以存储接收到的数据
Time=[]                    #存储数字0和数字1的高电位持续时间
K=0                         #定义循环初始值
GPIO.setmode(GPIO.BOARD)    #定义GPIO编码方式
time.sleep(2)               #由于dht11的采样周期间隔为2s,此处防止dht无方响应
Pin=12                      #定义引脚,使用哪个就定义哪个
GPIO.setup(Pin,GPIO.OUT)    #将GPIO设置为输出模式
GPIO.output(Pin,0)          #向dht11发送低电平(开始信号)(其中0可以用Flase、GPIO.low代替,下文的1同理)
time.sleep(0.02)            #低电平持续时间0.02s大于dht11要求的0.018s
GPIO.output(Pin,1)          #向dht11发送高电平(理论上可以取消,但是实际使用中不发送高概率出错)
GPIO.setup(Pin,GPIO.IN)     #将GPIO转为输入模式,用以接收dht11的信号
while GPIO.input(Pin)==0:   #采用轮训检测dht的响应信号,如果输入高电平将跳出此循环(不懂可以查阅python的while continue用法)continue
while GPIO.input(Pin)==1:   #采用轮训检测dht的响应信号continue
while K<40:                 #循环40次用以接收dht11的40bit数据while GPIO.input(Pin)==0:#因为每bit数据以低电平开始,故此。continuebegin=time.time()       #低电平循环结束故此时是高电平信号,因此开始计时while GPIO.input(Pin)==1:#轮训高电平continueend=time.time()         #获取高电平信号的结束时间#Time.append(end-begin)#此处为了确定0和1的高电平持续时间if (end-begin)<0.00003: #检测高电平的持续时间判断输入是0还是1(0.00003可以自测一下,取一个适合你的时间)Bit.append(0)       #高电平小于0.00003s证明是0else:Bit.append(1)       #高电平大于0.00003s证明是1K=K+1                   #记录循环次数
#print(Time)				#观察时间特点以确定上文0.00003的取值
humidity1bit=Bit[0:8]       #根据dht11的信号原理获取所需的值(下同理)
humidity2bit=Bit[8:16]
temperature1bit=Bit[16:24]
temperature2bit=Bit[24:32]
checkbit = Bit[32:40]
humidity1=0
humidity2=0
temperature1=0
temperature2=0
check=0
for i in range(0,8):         #循环8次,将二进制数转换为十进制数humidity1+=humidity1bit[i]*(2**(7-i))humidity2+=humidity2bit[i]*(2**(7-1))temperature1+=temperature1bit[i]*(2**(7-i))temperature2+=temperature2bit[i]*(2**(7-i))check+=checkbit[i]*(2**(7-i))
temperature=temperature1+temperature2*0.1 #获取温度值(注意dht11的使用说明中明文写到整数位后是小数位故应乘0.1)
humidity=humidity1+humidity2*0.1        #(网上大部分都没乘,他们的运行结果是整数,足可见网上的帖子都是复制粘着的水文)
checknum=temperature1+humidity1+temperature2+humidity2 #计算前32位数的值
if checknum==check:                         #检查前32位的值是否与校验位相等print("temp:%s,hum:%s"%(temperature,humidity))   #相等输出温度和湿度
else:print("dht11 check was wrong.  checknum:%s check:%s"%(checknum,check))#不等输出前32位值和校验位值

六、附录

1.dht11原理:
链接:https://pan.baidu.com/s/1bdQ0y9RWzJmOeZz986PJDg
提取码:tqzh
2.Python代码下载:
链接:https://pan.baidu.com/s/1F4qF0RY_xuFe5OJhgowPUg
提取码:qgxz
3.本人亲测使用树莓派IDE运行出错概率远高于使用命令行:sudo python dht11.py
4.对与0和1的判断网上有与我不同的想法,他的想法很巧妙(通过检测在高电平持续时间内能进行多少次赋值运算,进而通过检测k值来判断高电平持续时间),但有点难以理解(不如我的来的直接)可作为参考(我的代码和他的代码均有一定概率出错)

 
while j < 40:k = 0while GPIO.input(channel) == GPIO.LOW:continuewhile GPIO.input(channel) == GPIO.HIGH:k += 1		if k > 100:breakif k < 8:data.append(0)else:data.append(1)j += 1

http://chatgpt.dhexx.cn/article/MhhDC3L7.shtml

相关文章

树莓派Python开发第8课: PWM实验

第一课&#xff1a;什么是树莓派 第二课&#xff1a;树莓派能做什么 第三课&#xff1a;购买您的第一个树莓派 第四课&#xff1a;如何安装树莓派系统 第五课&#xff1a;树莓派Python编程手册 第六课&#xff1a;树莓派Python Led实验 第七课&#xff1a;树莓派Python 按键实验…

教你用树莓派Python打造一个音乐播放器

买了个树莓派3B&#xff0c;装好系统后灰落了好厚一层都不知道要干嘛。。。最近突发奇想&#xff1a;用树莓派做一个音乐播放器&#xff0c;每天6:30-7:20自动播放英语听力&#xff0c;强迫自己练习英语&#xff0c;也治治自己的懒床习惯&#xff0c;平时也可以用来听听歌。在这…

4步树莓派python3安装opencv,无需编译

4步树莓派python3安装opencv,无需编译 测试器件&#xff1a;树莓派4b 最近配置树莓派环境&#xff0c;装opencv时上网搜索发现教程挺麻烦而且过于老旧&#xff0c;现有一个简单方法分享一下 0.安装树莓派64位系统 可以使用官方软件安装系统 记得烧录前右下角高级设置配置ss…

树莓派 python驱动蜂鸣器

Author: Runsen 有问题&#xff0c;底部评论 蜂鸣器分为两种类型&#xff1a;“有源蜂鸣器”和“无源蜂鸣器”。 有源蜂鸣器内部具有多振动器&#xff0c;只需要在外部提供工作电压&#xff0c;它就能发出固定频率的声音。 无源蜂鸣器没有内部振荡源&#xff0c;需要外部驱动…

树莓派Python3安装运行OpenCV

1、安装 打开树莓派的命令行界面&#xff0c;输入命令即可完成安装。执行命令的时间更网速有关&#xff0c;请耐心等待。 sudo apt-get install python-opencv 是安装在python2 上的 sudo apt-get install python3-opencv 是安装在python3 上的 2、在Python3上测试OpenCV 安装…

树莓派Python开发教程:什么是树莓派

第一课&#xff1a;什么是树莓派 第二课&#xff1a;树莓派能做什么 第三课&#xff1a;购买您的第一个树莓派 第四课&#xff1a;如何安装树莓派系统 楔子 树莓派C语言版本的基础教程差不多写完了&#xff0c;原计划这个十一期间着手写Python部分&#xff0c;但是前几天又冒…

树莓派Python编程手册

第一课&#xff1a;什么是树莓派 第二课&#xff1a;树莓派能做什么 第三课&#xff1a;购买您的第一个树莓派 第四课&#xff1a;如何安装树莓派系统 第五课&#xff1a;树莓派Python编程手册 树莓派可以使用C语言&#xff0c;java&#xff0c;Python&#xff0c;而用python控…

树莓派 python3.9降级为python3.7

今天烧录了一个官方烧录器中的最新的镜像&#xff0c;打开之后python的版本是3.9的&#xff0c;之前做的一些东西都是基于python3.7的&#xff0c;再重新架构十分麻烦&#xff0c;于是干脆就把python3.9进行降级&#xff0c;降为python3.7. 这个镜像不像之前的一些镜像&#x…

第1.2.1章 树莓派python编程环境

树莓派3B&#xff0c;默认的python版本是2.7.13&#xff0c;但是操作系统自带了python3.5.3的IDE 因为现在主流都是用python3&#xff0c;那么我怎么讲python的环境切换到3呢&#xff1f; 1 python环境切换 参考将树莓派内置的 Python2.7 升级成 Python3 # 卸载 python2.7 su…

用python在树莓派上编程,你可以将项目扩展到令人难以置信的规模

树莓派是一个非常廉价的、只有手掌大小的完全可编程的计算机。虽然树莓派的体积小&#xff0c;但是它的潜力无限。你可以像使用常规台式计算机一样在树莓派上创建一个非常酷的工程。例如&#xff0c;你可以用树莓派搭建你自己的家用云存储服务器。 树莓派用什么语言编程&#x…

树莓派基础设置以及编程环境(python语言)

基础条件&#xff1a; 硬件&#xff1a;树莓派 3b 固件&#xff1a;2018-04-18-raspbian-stretch.img IO&#xff1a;树莓派3B的IO是3.3V&#xff0c;5V有风险。 一、python 使用方法 1.1、python2.7进入编程界面 左上角树莓派图标----->Programming----->Python2&…

树莓派教程(基于python编程)--入门篇

一&#xff1a;格式化SD卡 SD卡插入读卡器连接电脑&#xff0c;使用SDFormatter对SD卡进行格式化 &#xff08;重装烧录也要进行着SD卡格式化操作&#xff09; 二&#xff1a;下载官方镜像 http://downloads.raspberrypi.org/raspbian_latest 三&#xff1a;烧录SD卡 使用…

unity学习开发小球吃方块小游戏(从制作到发布程序,超详细全教程包你学会)

unity小球吃方块开发过程 你将学会用unity开发小游戏的基础知识吃方块游戏超详细全教程&#xff0c;保姆式教学包你学会一、创建对象创建PlayBall小球吃金币游戏项目&#xff0c;创建地面和小球。 二、添加脚本创建脚本使小球动起来&#xff0c;并用键盘控制小球的运动。 三、控…

python小游戏开发——井字棋

一家懂得用细节留住客户的3年潮牌老店我必须支持&#xff01;➕&#x1f6f0;&#xff1a;luyao1931 案例介绍 本案例采用 python 实现了一个简单的井字棋游戏。该游戏在控制台界面中进行&#xff0c;有游戏提示。游戏棋盘为 3 X 3 的九宫格样式&#xff0c;每个棋格与数字键盘…

使用Vue框架开发的贪吃蛇小游戏

注意&#xff1a;尽量不要用谷歌浏览器运行&#xff0c;因为谷歌浏览器会把GameValue翻译成中文&#xff0c;使游戏掉帧卡顿 解决办法&#xff1a;1.使用Edge浏览器&#xff0c;2.把谷歌浏览器的自动中文翻译关闭即可 游戏截图&#xff1a; 源码如下&#xff1a; <!DOCTY…

QT大作业——自制小游戏

The RPGgame with QT 一、 系统架构 该项目有4个ui组成&#xff0c;其中mainwindow作为项目程序入口&#xff0c;窗口跳转流程为&#xff1a;mainwindow->gamegraph->area_prairrie->playerstastus。 主要游戏功能装载在gamegraph和area_prairrie两个ui中&#xff0…

webpack + typescript 开发微信小游戏实践

源码地址 微信小游戏版本技术选型使用typescript开发 但是微信小游戏原生不支持 typescript 开发&#xff0c;于是探索一下使用ts开发微信小游戏 1. 创建小游戏 使用测试号&#xff0c;创建一个使用官方示例的小游戏 会生成一个可以直接运行的打飞机小游戏 2. 准备工作 …

小游戏开发引擎CocosCreator

小游戏 六彩跳棋 已经通过审核并且发布了好几天了&#xff0c;对跳棋感兴趣的朋友可以去看看&#xff0c;在微信游戏里搜索 六彩跳棋 &#xff0c;点击 立即玩 吧&#xff01;进去游戏后&#xff0c;需要点击 获取头像昵称 才能得到玩家数据&#xff0c;然后 划动屏幕 选择游戏…

unity开发微信小游戏1

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、准备工作二、官方文档三、WX开发者工具四、获得Appid五、获得AppidError: app.json: app.json六、资源下载失败404总结 前言 最开使用unity3d开发微信小游…

【微信小游戏】微信小游戏开发设置竖屏

微信小游戏开发环境默认横屏&#xff0c;对竖屏游戏非常不方便。 设置竖屏的入口十分隐蔽&#xff0c;以至于一度令我以为不能设置竖屏。 网上也根本搜不到解决方法&#xff0c;经过我的不懈努力&#xff0c;最终还是找到了设置方法。 原本是横屏的 按下面路径设置竖屏 开发…