DHT 温度传感器集成
DHT 温度传感器集成
本节详细介绍如何在 ESP32 中集成 DHT 温湿度传感器,包括库配置、数据读取和代码编写。学习完成后,您将能够:
- 安装和配置 DHT 传感器库
- 编写温湿度数据读取代码
- 处理传感器读取失败的情况
- 理解 DHT 传感器的时序要求和限制
在开始本节之前,请确保:
- 已完成硬件接线
- ESP32 开发环境已配置(Arduino IDE 或 PlatformIO)
- 具备基本的 C/C++ 编程知识
- 了解 ESP32 GPIO 操作方法
Library Setup
Section titled “Library Setup”Arduino IDE
Section titled “Arduino IDE”在 Arduino IDE 中安装 DHT 传感器库:
1. 打开 Arduino IDE2. 点击 工具 → 管理库 (Sketch → Include Library → Manage Libraries)3. 搜索 "DHT sensor library" by Adafruit4. 选择最新版本,点击安装5. 安装依赖库 "Adafruit Unified Sensor Lib"库信息:
- 库名称:DHT sensor library
- 作者:Adafruit
- 版本:1.4.4+
- 功能:支持 DHT11、DHT22、DHT21 等型号
PlatformIO
Section titled “PlatformIO”在 PlatformIO 中配置库依赖:
; platformio.ini[env:esp32dev]platform = espressif32board = esp32devframework = arduinomonitor_speed = 115200
lib_deps = adafruit/DHT sensor library@^1.4.4 adafruit/Adafruit Unified Sensor@^1.1.9Code Implementation
Section titled “Code Implementation”Basic DHT Reading
Section titled “Basic DHT Reading”#include <DHT.h>#include <DHT_U.h>
// DHT 传感器配置#define DHTPIN 4 // 数据引脚连接到 GPIO 4#define DHTTYPE DHT22 // DHT22 (AM2302),如使用 DHT11 则改为 DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() { Serial.begin(115200); Serial.println("DHT22 Sensor Test");
dht.begin(); // 初始化 DHT 传感器}
void loop() { // 等待 2 秒(DHT22 的最小读取间隔) delay(2000);
// 读取湿度值 float humidity = dht.readHumidity(); // 读取温度值(摄氏度) float temperature = dht.readTemperature(); // 读取温度值(华氏度) float fahrenheit = dht.readTemperature(true);
// 检查读取是否成功 if (isnan(humidity) || isnan(temperature)) { Serial.println("Failed to read from DHT sensor!"); return; }
// 计算体感温度(热指数) float heatIndex = dht.computeHeatIndex(fahrenheit, humidity);
// 打印结果 Serial.print("Temperature: "); Serial.print(temperature); Serial.print("°C / "); Serial.print(fahrenheit); Serial.print("°F, Humidity: "); Serial.print(humidity); Serial.print("%, Heat Index: "); Serial.print(heatIndex); Serial.println("°F");}Non-Blocking Reading
Section titled “Non-Blocking Reading”使用非阻塞延时模式替代 delay():
#include <DHT.h>
#define DHTPIN 4#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// 非阻塞定时器变量unsigned long previousMillis = 0;const unsigned long interval = 3000; // 每 3 秒读取一次
// 存储读取值float temperature = 0;float humidity = 0;bool sensorError = false;
void setup() { Serial.begin(115200); dht.begin(); Serial.println("Non-Blocking DHT22 Reader Started");}
void loop() { unsigned long currentMillis = millis();
// 非阻塞定时读取 if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; readSensorData(); }
// 此处可执行其他任务 // 例如:处理 MQTT 连接、接收命令等}
void readSensorData() { float newHumidity = dht.readHumidity(); float newTemperature = dht.readTemperature();
if (isnan(newHumidity) || isnan(newTemperature)) { sensorError = true; Serial.println("Sensor read failed - will retry next cycle"); return; }
sensorError = false; temperature = newTemperature; humidity = newHumidity;
Serial.print("Updated - Temp: "); Serial.print(temperature); Serial.print("°C, Humidity: "); Serial.print(humidity); Serial.println("%");}Multiple Samples Averaging
Section titled “Multiple Samples Averaging”为提高测量稳定性,可采样多次取平均值:
#include <DHT.h>
#define DHTPIN 4#define DHTTYPE DHT22#define SAMPLE_COUNT 5 // 采样次数
DHT dht(DHTPIN, DHTTYPE);
struct SensorReading { float temperature; float humidity;};
SensorReading getAveragedReading() { float tempSum = 0; float humSum = 0; int validSamples = 0;
for (int i = 0; i < SAMPLE_COUNT; i++) { float t = dht.readTemperature(); float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) { tempSum += t; humSum += h; validSamples++; }
delay(100); // 采样间隔 100ms }
SensorReading result = {0, 0};
if (validSamples > 0) { result.temperature = tempSum / validSamples; result.humidity = humSum / validSamples; }
return result;}
void setup() { Serial.begin(115200); dht.begin(); Serial.println("Averaged DHT22 Reader");}
void loop() { SensorReading reading = getAveragedReading();
if (reading.temperature == 0 && reading.humidity == 0) { Serial.println("All samples failed!"); } else { Serial.print("Averaged - Temp: "); Serial.print(reading.temperature, 1); // 1 位小数 Serial.print("°C, Humidity: "); Serial.print(reading.humidity, 1); Serial.println("% (based on " + String(validSamples) + " samples)"); }
delay(5000);}DHT Sensor Protocol
Section titled “DHT Sensor Protocol”Communication Protocol
Section titled “Communication Protocol”DHT22 使用单总线协议与微控制器通信:
1. MCU 将数据线拉低至少 18ms (启动信号)2. MCU 释放数据线并拉高 20-40μs3. DHT22 将数据线拉低 80μs (响应信号)4. DHT22 将数据线拉高 80μs (准备发送)5. DHT22 发送 40 位数据 (5 字节) - 字节 0: 湿度整数部分 - 字节 1: 湿度小数部分 - 字节 2: 温度整数部分 - 字节 3: 温度小数部分 - 字节 4: 校验和6. 校验和 = 字节0 + 字节1 + 字节2 + 字节3 (仅低 8 位)时序要求:
- 启动信号低电平时间:≥ 18ms
- 数据位 “0”:高电平 26-28μs
- 数据位 “1”:高电平 70μs
- 读取间隔:≥ 2 秒
售前提示:DHT22 的最大采样率为 2 次/秒(每 500ms 一次),但在实际应用中建议 3-5 秒读取一次以降低功耗。这对于绝大多数环境监测场景已经足够。
验证传感器读取
Section titled “验证传感器读取”void verifySensor() { Serial.println("=== DHT22 Verification ==="); Serial.print("Sensor model: DHT22 (AM2302)\n"); Serial.print("Reading interval: 3 seconds\n"); Serial.print("Expected accuracy: ±0.5°C, ±2% RH\n\n");
// 读取 10 次数据并输出 for (int i = 1; i <= 10; i++) { float t = dht.readTemperature(); float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) { Serial.print("Sample "); Serial.print(i); Serial.print(": "); Serial.print(t, 1); Serial.print("°C, "); Serial.print(h, 1); Serial.println("%"); }
delay(3000); }
Serial.println("\n=== Verification Complete ===");}验证检查清单:
- 串口输出温度值稳定,波动在 ±0.5°C 以内
- 湿度值符合当前环境(握在手中湿度应上升)
- 无 NaN 或无效值输出
- 采样间隔稳定在设定值
Issue 1: 持续读取失败
Section titled “Issue 1: 持续读取失败”症状:每次读取都返回 NaN
可能原因:
- 上拉电阻缺失
- 引脚定义错误
- DHT 传感器损坏
解决方案:
- 确认 DHT22 DATA 引脚有 4.7kΩ-10kΩ 上拉电阻
- 确认
DHTPIN定义与接线一致 - 尝试更换传感器模块
Issue 2: 间歇性读取失败
Section titled “Issue 2: 间歇性读取失败”症状:偶尔返回 NaN,但大多数时候正常
可能原因:
- 电源噪声干扰
- 传感器老化
- 线缆过长
解决方案:
- 在传感器 VCC 和 GND 之间添加 100μF 去耦电容
- 缩短传感器与 ESP32 之间的连线(< 20cm)
- 在软件中添加重试逻辑
- ✅ 推荐: 将 DHT 传感器安装在通风良好的位置,远离热源
- ✅ 推荐: 在户外使用时增加防水外壳
- ✅ 推荐: 定期校准传感器(每 6-12 个月)
- ❌ 避免: 传感器靠近 ESP32 WiFi 天线(射频干扰)
- ❌ 避免: 高湿度环境(>90% RH)长期使用
- ❌ 避免: 阳光直射传感器(会导致温度测量偏高)
Summary
Section titled “Summary”本节要点总结:
- DHT 库配置:Arduino IDE 使用库管理器安装,PlatformIO 配置 lib_deps
- 代码实现:调用
dht.readTemperature()和dht.readHumidity()获取数据 - 错误处理:使用
isnan()检查读取是否成功 - 精度限制:DHT22 精度 ±0.5°C / ±2%RH,每 2 秒最多读取一次
- 非阻塞设计:使用 millis() 定时替代 delay(),避免阻塞主循环