DHT11/DHT22接ESP32:读温湿度到OLED显示

2026-11-08 07:30:12 18阅读 所属项目:ESP32 开发板

给机器人加环境感知,温湿度是最便宜也最直观的一路信号。DHT11 和 DHT22 这两颗传感器在创客圈用了十几年,一颗几块钱,一根数据线就能出读数,配 ESP32 正合适——32 位双核、WiFi 现成,读到的温湿度既能走串口看,也能顺手推到 OLED 屏上做个桌面环境站。这篇把接线、装库、代码和常见的"读不出来"一次讲完,规格数值以 Aosong(ASAIR)器件手册和 Adafruit 库文档为准。

ESP32搭配DHT22温湿度传感器实拍

先分清 DHT11 和 DHT22

两颗外形几乎一样,内部都是一颗电阻式湿敏元件加一个 NTC 测温元件,芯片在传感器内部完成模数转换,直接输出数字信号,所以任何单片机都能接,不占 ADC。差别全在指标上:

指标DHT11DHT22
温度范围0~50℃,±2℃-40~80℃,±0.5℃
湿度范围20~90%RH,±5%0~100%RH,±2%
分辨率湿度1%、温度1℃湿度0.1%、温度0.1℃
工作电压3~5.5V3~6V
供电电流0.5~2.5mA1~1.5mA
采样周期1秒2秒
价格约1~5美元约4~10美元

一句话选型:室内看个大概、做玩具,DHT11 够用还便宜;要记录温差变化、做数据,多花几块钱上 DHT22,精度和量程都不是一个档次。两颗读取方式完全相同,代码里改一行宏就能互换。白色外壳带孔的是 DHT22(丝印 AM2302),蓝色小方块是 DHT11,拿到手一眼就能认出来。

DHT22与DHT11传感器外观对比

引脚定义与接线

裸传感器是 4 个引脚,正面对着你、从左往右数:

1 脚接电源(3.3V 或 5V);

2 脚是数据脚,接任意数字 GPIO,并且要在这脚和电源之间加一个 10kΩ 上拉电阻;

3 脚悬空不接;

4 脚接地。

如果买的是三脚的模块版,板上已经焊好上拉电阻,直接 VCC、GND、DATA 三根线接走即可,不用再外接电阻。这篇示例把数据脚接在 GPIO 4 上,其他能用的 GPIO 也行,改代码里的宏定义即可。

ESP32与DHT22面包板接线图

接线上有个细节值得留意:ESP32 的 IO 是 3.3V 逻辑,传感器 3.3V 供电时读数最稳;有些板子用 5V 供电也没问题,但要确认开发板该引脚是 5V 容忍的。面包板上把上拉电阻跨在数据脚和电源轨之间,别接成数据脚对地,那是新手最常见的翻车点。

装两个库,缺一不可

读取逻辑(单总线时序)不用自己写,Adafruit 的 DHT 库全包了。打开 Arduino IDE,进 Sketch → Include Library → Manage Libraries,搜"DHT"装 DHT sensor library(Adafruit 出品)。它还依赖 Adafruit Unified Sensor 库,继续搜"Adafruit Unified Sensor"装上,少这个编译会直接报 Adafruit_Sensor.h 找不到。

Arduino IDE库管理器安装DHT库

完整示例代码

下面是完整的测试程序,把传感器类型宏换成你手上的型号就能跑。用 DHT11 就把 DHTTYPE 那行换成 #define DHTTYPE DHT11(把注释换到另一行):

// Example testing sketch for various DHT humidity/temperature sensors written by ladyada
// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor

#include "DHT.h"

#define DHTPIN 4     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

程序结构很简单:setup 里 Serial.begin(9600) 起串口、dht.begin() 初始化;loop 里每 2 秒读一次。readHumidity() 出湿度,readTemperature() 默认出摄氏度,传 true 出华氏度。库还会用温湿度算体感温度(heat index), hic 是摄氏、hif 是华氏,都直接给你了。

看读数与排错

烧录后打开串口监视器,波特率 9600,正常输出长这样:Humidity: 42.30% Temperature: 25.60°C 77.08°F Heat index: 25.30°C 77.54°F。数字有小数点说明你接的是 DHT22;DHT11 的读数永远是整数,这也能反过来帮你确认宏定义没写错。

最常见的报错就是串口一直刷 Failed to read from DHT sensor!,按命中率排查:先查数据脚的宏 DHTPIN 是不是和你实际插的 GPIO 一致;再查上拉电阻有没有接、接没接成对地;然后看供电,接触不良和电压不对都出这个错;最后注意采样间隔,DHT22 两次读取至少隔 2 秒,读太勤也会失败。DHT 本身是慢传感器,读数可能有最多 2 秒的滞后,属于正常现象。

把读数送上 OLED

串口只是第一步,拿到 h 和 t 两个浮点数之后,显示就是纯输出问题。接一块 0.96 寸 SSD1306 OLED,I2C 两根线(SCL、SDA)接到 ESP32 对应引脚,用 Adafruit 的 SSD1306 和 GFX 库初始化后,在 loop 里把 Serial.print 换成 display.print 就能把温湿度刷到屏上——之前发过的 SSD1306 OLED 配 ESP32 那篇把 I2C 接线和库的用法讲得很细,两篇拼起来就是一个完整的桌面温湿度计。要更省事,直接用这次读数喂给行空板或机械臂的状态屏也一样。

整套下来成本不到二十块,是给任何桌面设备加环境感知的最短路径。先在串口把读数调稳,再考虑上屏、上云,一步一个坑地排,比一上来就堆功能靠谱得多。


作者:电机传感器师
链接:https://www.aiddithome.com/p/5a0b6860f5dff.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
4条评论
老张装机
1楼 · 16小时前

上周刚踩过上拉电阻这个坑,数据脚和地之间接了个10k,串口一直刷Failed to read,折腾一晚上才反应过来方向接反了。文里那句“别接成数据脚对地”真是血泪总结,新手一定记牢。另外补一句,DHT22用5V供电读数偶尔跳变的话,降到3.3V试试,我这边稳多了。

胶佬憨憨
2楼 · 16小时前

DHT11读出来永远是整数这个细节讲得好,我以前就是靠这个判断宏定义写没写错的。

只看不说话
3楼 · 16小时前

两块钱的传感器配ESP32做个桌面温湿度计,确实是成本最低的环境感知方案了,适合给刚入门的练手。

隔壁工位的好奇宝
4楼 · 16小时前

请问串口监视器乱码一般是哪里的问题?波特率9600我确认没选错,烧录也能过,就是显示的全是问号。