1. 读取DHT11温湿度传感器数据

读取DHT11温湿度传感器数据 学习卡片

任务说明

本案例使用DHT11数字温湿度传感器连接树莓派GPIO引脚,通过Python脚本读取环境温度与相对湿度,并在终端打印结果。DHT11采用单总线协议,数据帧为40位(8位湿度整数、8位湿度小数、8位温度整数、8位温度小数、8位校验和),校验和等于前四个字节之和的低8位。

硬件连接

DHT11传感器模块通常有3个引脚(VCC、DATA、GND),部分模块带4脚(含NC空脚)。连接关系如下:

  • VCC → 树莓派3.3V(Pin 1)
  • DATA → 树莓派GPIO4(Pin 7,BCM编号)
  • GND → 树莓派GND(Pin 6)

DATA引脚需外接10kΩ上拉电阻至3.3V(多数模块已内置上拉电阻,可直接连接)。

树莓派 GPIO 40-Pin 1 3.3V 7 GPIO4 6 GND 10k 3.3V DHT11 温湿度传感器 VCC (1) DATA (2) GND (4) ● VCC (3.3V) ● DATA (GPIO4) ● GND

Python实现代码

创建文件 dht11_read.py,代码如下:

#!/usr/bin/env python3
import time
import RPi.GPIO as GPIO

DHT_PIN = 4  # BCM编号GPIO4

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

def read_dht11(pin):
    """读取DHT11数据,返回(湿度, 温度)或None"""
    data = []
    
    # 发送起始信号:主机拉低至少18ms
    GPIO.setup(pin, GPIO.OUT)
    GPIO.output(pin, GPIO.LOW)
    time.sleep(0.02)  # 20ms
    GPIO.output(pin, GPIO.HIGH)
    time.sleep(0.00004)  # 40us
    
    # 切换为输入模式,读取响应
    GPIO.setup(pin, GPIO.IN)
    
    # 等待DHT11拉低响应信号(80us低+80us高)
    timeout = time.time() + 0.1
    while GPIO.input(pin) == GPIO.HIGH:
        if time.time() > timeout:
            return None
    # 80us低电平
    while GPIO.input(pin) == GPIO.LOW:
        pass
    # 80us高电平
    while GPIO.input(pin) == GPIO.HIGH:
        pass
    
    # 读取40位数据
    for _ in range(40):
        # 每个位以50us低电平开始
        while GPIO.input(pin) == GPIO.LOW:
            pass
        # 高电平持续时间决定0或1
        start = time.time()
        while GPIO.input(pin) == GPIO.HIGH:
            pass
        duration = time.time() - start
        data.append(1 if duration > 0.00005 else 0)  # 50us阈值
    
    # 解析数据
    if len(data) != 40:
        return None
    
    humidity_int = bits_to_byte(data[0:8])
    humidity_dec = bits_to_byte(data[8:16])
    temp_int = bits_to_byte(data[16:24])
    temp_dec = bits_to_byte(data[24:32])
    checksum = bits_to_byte(data[32:40])
    
    # 校验
    calc = (humidity_int + humidity_dec + temp_int + temp_dec) & 0xFF
    if calc != checksum:
        return None
    
    humidity = humidity_int + humidity_dec / 10.0
    temperature = temp_int + temp_dec / 10.0
    return (round(humidity, 1), round(temperature, 1))

def bits_to_byte(bits):
    """将8位bit列表转换为整数"""
    val = 0
    for b in bits:
        val = (val << 1) | b
    return val

try:
    while True:
        result = read_dht11(DHT_PIN)
        if result:
            humidity, temperature = result
            print(f"湿度: {humidity}%  温度: {temperature}°C")
        else:
            print("读取失败,重试中...")
        time.sleep(2)  # DHT11采样周期≥1s,建议2s
except KeyboardInterrupt:
    print("\n程序已退出")
finally:
    GPIO.cleanup()

运行与验证

依赖安装:

sudo apt update
sudo apt install -y python3-pip
sudo pip3 install RPi.GPIO

运行程序:

python3 dht11_read.py

验证方法:程序启动后每2秒读取一次数据。正常工作时终端会持续输出类似以下格式的数据行:

湿度: 45.0%  温度: 26.0°C

判定标准:

  1. 终端能稳定输出温湿度数值,且湿度在20%~90%、温度在0~50°C范围内(DHT11量程);
  2. 用手捏住传感器或向传感器哈气,湿度数值应明显上升,说明数据真实反映环境变化;
  3. 若输出“读取失败”,检查接线和上拉电阻,程序会自动重试。

注意事项:DHT11采样间隔需大于1秒,本程序设为2秒;GPIO4为BCM编号,对应物理引脚7,请勿接错。