DHT11 与 DHT22 怎么选:精度、量程差别与 nan 读数排查

Cartoon of a large light-blue DHT11 sensor block on a small black circuit board beside a large white DHT22 sensor housing on a narrow black board with a red-and-black wire loop, both with three sideways silver header pins, a teal swap arrow between them and a blue microcontroller board cropped small in the corner

如果你要测的空气有机会跑到 90 %RH 以上,或者掉到 0 °C 以下,就买 DHT22——在马来西亚,户外、浴室和种植箱几乎全都算在里面。放在室内的话,DHT11 是真的够用。两颗传感器用的是同样三条接线、同样一个库,所以哪天改变主意,代价只是一行代码里的一个词。

DHT11 和 DHT22,真正的差别到底在哪里?

DHT11 和 DHT22——奥松(Aosong)也把后者当成 AM2302 在卖——其实是同一套设计做成了两个等级:一颗对湿度敏感的电容、一个温度元件,再加一颗单片机把两者都换算好,然后顺着一条线把算完的数字送出来。下面这些数字是奥松数据手册上的说法,不是我们自己量出来的。如果你手上正在比三个名字,那实际上只有两个零件:DHT22 和 AM2302 是同一颗感测元件、共用同一份数据手册,而 AM2302 是奥松通常印在带线版和装在载板上那种版本上的编号——所谓的三针模块,指的就是它。

数据手册规格 DHT11 DHT22 / AM2302
湿度量程 20–90 %RH 0–100 %RH
湿度精度 ±5 %RH ±2 %RH(最大 ±5 %RH)
湿度步进 1 %RH 0.1 %RH
温度量程 0 到 50 °C −40 到 80 °C
温度精度 ±2 °C ±0.5 °C
温度步进 1 °C 0.1 °C
供电 3.3–5.5 V 3.3–6 V
两次读取之间的最短间隔 2 s 2 s

步进那一行是结构决定的,不是四舍五入的选择。两颗传感器送出来的都刚好是 40 位:湿度两个字节、温度两个字节、校验和一个字节。在 DHT11 的数据帧里,每一对的第二个字节是小数部分,而奥松自己的示例就写着它永远是零——所以 DHT11 报不出 65.3 %RH,只能报 65。DHT22 把同样这两个字节当成一个以十分之一为单位的 16 位数来用,0.1 就是这么来的。

想自己试的话要备的零件——两颗传感器挑一颗,不是两颗都买

ItemPriceQty
DHT 11 DHT 22 Temperature and Humidity Sensor DHT22 High Sensitivity Sensor DHT11 For Aduino IOT - DHT11 SENSORDHT 11 DHT 22 Temperature and Humidity Sensor DHT22 High Sensitivity Sensor DHT11 For Aduino IOT - DHT11 SENSORDHT11HTRM4.95
DHT 11 DHT 22 Temperature and Humidity Sensor DHT22 High Sensitivity Sensor DHT11 For Aduino IOT - DHT22 SENSORDHT 11 DHT 22 Temperature and Humidity Sensor DHT22 High Sensitivity Sensor DHT11 For Aduino IOT - DHT22 SENSORDHT22HTRM14.95
Arduino Uno Compatible SMD UNO R3 with Type B Cable - ATMEGA328P with CH340G-Microcontroller ProjectArduino Uno Compatible SMD UNO R3 with Type B Cable - ATMEGA328P with CH340G-Microcontroller ProjectUNOCH34RM22.90
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-F 20CM40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-F 20CMDPWMF20RM3.20

两颗传感器挂在同一个产品页上,所以加入购物车之前,请先在下拉选单里选 DHT11 SENSOR 或 DHT22 SENSOR。公对母杜邦线可以从模块的排针直接插进 Uno 的排母,别的什么都不用。

只有想放到面包板上才需要

ItemPriceQty
MB102 Breadboard 170 400 830 Holes Breadboard Donut Board Arduino Prototype Multi Color - MINI BREADBOARD 170 HOLES (WHITE)MB102 Breadboard 170 400 830 Holes Breadboard Donut Board Arduino Prototype Multi Color - MINI BREADBOARD 170 HOLES (WHITE)BRB170HRM1.00
40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-M 20CM40pcs Dupont Wire 10cm 20cm 30cm for Breadboard DIY Experiment Jumper Wire Breadboard wire - DUPONT WIRE M-M 20CMDPWMM20RM3.50

迷你面包板加公对公杜邦线是另一条路,适合传感器得跟别的东西共用一条 5V 线的时候。

马来西亚的空气,会把你逼向哪一颗?

DHT11 那个 90 %RH 的湿度上限,决定了这里大部分人的选择。马来西亚气象局把全国相对湿度的日平均最大值放在 94% 以上,并说它「可能高达 100%」。入夜之后和下过雨之后,你窗外那口空气就坐在 DHT11 的顶点之上。

越过这个上限,DHT11 并不会大声地坏给你看。它只是跑到了出厂校准所涵盖的范围之外,而奥松对超出范围的部分没有公布任何精度数字——规格表上那个 ±5 %RH 就这样悄悄失效,读数却照样一副合情合理的样子送回来。一个你不能信、却看起来很像真的数字,比一个明显坏掉的数字更糟。奥松还点出了第二个代价:长期工作在标称范围之外,会加速传感器老化。

温度这一边,界线画在下面。DHT11 从 0 °C 起算,所以拿它做冰箱记录器或者冷冻库警报,根本得不到任何有效读数。放在室内的话,两颗都稳稳待在量程里,而 ±2 °C 拿来决定风扇什么时候该开,绰绰有余。

  • DHT11:室内房间监测、学校和 RBT 作业,还有任何到了某个门槛就去触发风扇的东西。
  • DHT22:户外、阳台、温室、浴室、孵化箱、种植箱、冰箱,以及任何你打算连着画上好几个星期的记录。
  • 两颗都不要:如果你只需要温度,或者探头会碰到水,那么防水的 DS18B20 根本没有湿度元件可以被毁掉。

好几颗传感器同时测一个房间,精度这个数字就变成看得见的东西了:

上拉电阻到底住在哪里——模块上,还是你的面包板上?

DHT 那条唯一的数据线是一条开漏总线:两端谁都不会去把它拉高。它们只能把它拉到地,然后松手,而唯一能把它拉回高电平的,只有一颗接到 VCC 的电阻。没有东西在上面拉着,松手就等于什么都没发生——线在那里浮着,传感器发出的低脉冲配不出对应的高电平边沿,库就超时了。于是从第一次读取开始,每一次都是 nan。

三针模块和四针裸传感器之间,差的就是这件事,而这也是我们两个型号都做成模块的原因。DHT11 模块把自己的做法摊开给你看:R1 位置上一颗印着 512 的贴片电阻,解码出来是 5.1 kΩ——正是奥松自己那份典型应用电路里的值。DHT22 模块围着那颗白色的 AM2302 做了同一件事:载板上带着上拉电阻,同时把传感器那只没用到的第三只脚留空不接,于是一个四针的零件到你手上时是三针,插上就能用。买裸的,这两件事就都归你自己处理。把那颗四只脚的零件带栅格的那一面朝向自己,从左到右数脚:第 1 脚是 VCC,第 2 脚是数据,第 3 脚在传感器内部哪里都不通,第 4 脚是 GND。上拉电阻横跨第 2 脚和第 1 脚——5.1 kΩ 或者 10 kΩ——第 3 脚空着就好。

中间那个坑,正是很多人相信「电阻可有可无」的原因。Adafruit 的库在读取期间会把引脚切成 INPUT_PULLUP,也就是启用 ATmega328P 的内部上拉——20 kΩ 到 50 kΩ。在 10 cm 的短线上,一颗裸传感器往往光靠这个就能跑。可是上升时间等于电阻乘以导线的电容,所以一颗 30 kΩ 的上拉,把同一条线充起来要比 5.1 kΩ 的慢上大约六倍,而传感器最短的那个脉冲只有 26 µs。线一拉长,读数就开始时好时坏。

卡通对比图:一颗白色带栅格的 DHT22 传感器装在黑色载板上,一个青色圆圈圈住板上一颗很小的贴片电阻;旁边是同一颗白色传感器的四脚裸件,一颗米色带色环的电阻焊在它两只银色的脚之间,同样被青色圆圈圈住
同一颗白色的 DHT22 传感器,两种买法。装在载板上,上拉电阻已经在那里了,是一颗很小的贴片电阻。买裸的,就是四只脚,加一颗要你自己接在数据脚和供电脚之间的电阻。

为什么读数会回来一个 nan,或者卡在同一个数字上?

当没有任何有效的 40 位数据帧到达时,DHT 库就回一个 nan——那是一份「什么都没听见」的报告,不是一个传感器数值。数字卡住不动是反过来的问题,成因也不同。下面四件事,几乎把这两种情况全包了。

你看到的现象 实际发生的事 怎么修
每一圈都是同一个数字,每两秒才变一次 你要读数的速度比库真正去取一次还快,于是它把上一次的缓存结果原样递给你 两次读取之间留 2 s
从第一次开始,每一次读取都是 nan 裸传感器没有上拉电阻、数据线插错脚,或者插着 DHT11 却声明成 DHT22 先查线,再查构造函数
nan 和好读数随机夹杂着出现 边沿太慢——线太长或者没有屏蔽、上拉太弱,或者用的是 3.3 V 逻辑 把线缩短,换 5.1 kΩ 上拉
数字有、也很稳,但离谱得不像话 插着 DHT22 却声明成 DHT11;数据帧被用错的规则拆开了 把构造函数里的型号改对

数字卡住这一条得摊开讲,因为没有任何东西会警告你。Adafruit 的 DHT 库把最短间隔定在 2000 ms;比这更早去要,它根本不跟传感器讲话,直接把上一次的结果还给你。所以一个带 delay(200) 的循环,会先给你十个一模一样的数字,然后才换一个新的。这也是为什么「DHT11 每秒可以读一次」这句被到处转述的话不适合拿来照做:奥松的 DHT11 数据手册写的是整个流程的间隔必须超过 2 秒,跟 DHT22 一模一样。

长线是在「位」这一层上垮掉的。每一个位都以 50 µs 的低电平开头,接着一段高电平,而这段高电平的长度就是数据:26–28 µs 是 0,70 µs 是 1,Arduino 靠给这段高电平计时来判断。导线的电容会把上升沿磨圆,于是线跨过逻辑阈值的时间偏晚,每一段高电平量出来都偏短。线够长,1 就被读成 0,校验和失败,你拿到的就是 nan。奥松给出的额定是:配 5.1 kΩ 上拉时可以拉到 20 m,而在 3.3 V 上限制在 100 cm——后面这个限制来自导线上的压降,不是边沿被磨圆,但它指向同一件事:线要短。

卡通对比图:一颗装在黑色载板上的白色 DHT22 传感器接到一块蓝色小型单片机板——上面是一段拉直的短三线接法,配一条清晰利落的青色方波;下面是一段盘绕的长三线接法,配一条橙色波形,它的上升沿全都歪倒下去,窄脉冲塌成一个个低矮的圆包
线长是怎么变成 nan 的。传感器在线的两端都把脉冲计得好好的,可是电容会把每一个上升沿磨圆。线一长,最短的那些脉冲几乎抬不离地,Arduino 就把它们的时间量错了,校验和于是失败。

怎么接线,又怎么证明它真的在工作?

DHT11 和 DHT22 模块的尾端都是一排三针的弯角公排针,而 Uno 上是排母,所以三条公对母杜邦线就是全部的接线工作。请看排针旁边的丝印,不要从板边去数,因为这两块载板印的顺序并不一样。DHT11 板上写的是 S、VCC、−,数据脚在 S 那一端;DHT22 板上写的是 +、out、−,数据脚在中间。两块板上位置相同的只有 − 脚——VCC 和数据互换了座位。

模块引脚(照丝印读) Uno 插孔 为什么
+(VCC) 5V 两颗传感器的标称都从 3.3 V 起,所以 5V 这条电源轨舒舒服服地落在范围内
−(GND) GND 共用的参考地——每一个脉冲的宽度都是相对它量出来的
S 或 out(数据) D2 任何数字引脚都行;D2 只是下面那段程序里写的那一个

在 3.3 V 的板子上——ESP32 或者 ESP8266,像下面那篇 OLED 监测器里用的那颗——请把模块的 + 接到 3V3 脚,不要接 5V。两颗传感器的标称都低到 3.3 V,所以在那里读得好好的;电源轨之所以重要,是因为数据线闲置时的电平就是你喂给 + 的那个电压:用 5V 供电,模块就会把 5 V 递给一个并不耐这个电压的 GPIO。你付出的代价是供电余量——导线上还能容忍多少压降才会让传感器吃不饱——这也正是上面那个 100 cm 的线长限制属于 3.3 V、而 20 m 那个属于 5 V 的原因。

这段程序需要 Adafruit 的 DHT sensor library。在 Arduino IDE 里打开 Tools → Manage Libraries,搜 DHT sensor library,装 Adafruit 那一个,它提示要不要一起装 Adafruit Unified Sensor 时请接受——少了这个依赖,DHT 库编译不过。

// 读一颗 DHT11 或 DHT22,每两秒把两个数值都打印一次。
// 要换传感器,只改一行:DHT22 -> DHT11。别的地方都不用动。
#include <DHT.h>

const uint8_t DHT_PIN = 2;   // 模块上的 S / out 脚
#define DHT_TYPE DHT22       // <-- 蓝色那颗填 DHT11,白色那颗填 DHT22

DHT dht(DHT_PIN, DHT_TYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
  delay(2000);               // 让传感器安安静静做完第一次转换
}

void loop() {
  float rh    = dht.readHumidity();
  float tempC = dht.readTemperature();

  if (isnan(rh) || isnan(tempC)) {
    // nan 表示那 40 位的数据帧根本没到,或者到了但校验和不对。
    Serial.println(F("no reading - check the data wire, the pull-up and DHT_TYPE"));
  } else {
    Serial.print(tempC, 1);
    Serial.print(F(" C   "));
    Serial.print(rh, 1);
    Serial.println(F(" %RH"));
  }

  delay(2000);               // 奥松:整个读取周期必须保持在 2 秒以上
}

用 9600 波特率打开串口监视器,应该每两秒出现一行。那一行 DHT_TYPE 就是这篇文章讲的那个开关:编译成 Uno 的程序,两种型号下都是同样的 5,184 字节。先从便宜那颗开始,是一个决定,不是一场赌博——前提是换传感器时,你要照着新板子的丝印把三条杜邦线重新插一遍,因为这两块载板并没有把数据脚放在同一个位置。

两颗传感器都接好、都在跑,如果你想亲眼看一下这个替换:

我们那篇 DHT11 + OLED 监测器把这些数字搬上了屏幕;如果你想改成在迷你面包板上做,我们的面包板指南讲清楚了哪些孔是通的。

卡通图:一块蓝色单片机板用红、黑、黄三条杜邦线接到装在黑色载板上的白色 DHT22 传感器,旁边躺着一颗没接线的浅蓝色 DHT11 传感器模块,两颗传感器之间画着一个青色的双向箭头
整套测试装置:从 Uno 拉三条杜邦线到模块的三只脚。旁边等着的那颗浅蓝色 DHT11 用的是同样三条线,但顺序不一样——它的数据脚在板子的 S 那一端,而白色模块的数据脚在中间。

我们从真实客户身上看到的常见错误

为了让显示看起来跟手,就在一个很紧的循环里一直读。结果恰恰相反:任何快过两秒的读取都会拿到缓存里那个数字,于是画面更新得很顺滑,内容却是旧的。

因为数字「看起来差不多对」,就买 DHT11 去做户外或浴室的记录器。它当然看起来对——超过 90 %RH,DHT11 就跑到了那个 ±5 %RH 精度所标称的范围之外,而一个没有标称的数字,看起来照样像个数字。合情合理不等于正确,而这正是多花的那几令吉真的买到了东西的场合。

把传感器装在它要监测的那个东西的同一个盒子里。奥松要求它远离任何会改变局部温度的东西;因为相对湿度本来就是相对温度来定义的,一颗发热的稳压器会同时把两个读数都带偏。

换传感器时把杜邦线整排平移过去。这两块载板的引脚定义并不一样:数据脚在 DHT11 板的 S 那一端,在 DHT22 板的中间,位置相同的只有 −。把 DHT11 的接法原封不动搬过来,Uno 的 5V 就会落在 DHT22 的数据脚上,而 D2 落在它的供电脚上——很快就能烧掉一颗传感器。每次换传感器,都把三条杜邦线全部拔掉,照着丝印重新插一遍。

FAQ

DHT11 和 DHT22 真正的区别是什么?

是量程和分辨率,不是可靠性。奥松给 DHT11 的标称是 20–90 %RH 和 0–50 °C,±5 %RH 与 ±2 °C,读数以整数为步进;给 DHT22 的是 0–100 %RH 和 −40 到 80 °C,±2 %RH 与 ±0.5 °C,步进 0.1。接线、协议和库完全相同,而且两者都要求两次读取之间隔两秒。

我的 DHT22 为什么一直回 nan?

nan 表示没有任何有效的 40 位数据帧到达。如果每一次读取都是这样,先怀疑数据脚、四针裸传感器缺了上拉电阻,或者构造函数里的型号写错了。如果是好读数和 nan 交替出现,那就是数据帧到了但坏了——把线缩短,并加一颗 5.1 kΩ 的上拉电阻。

DHT22 传感器要怎么测试?

DHT22 载板的引脚顺序,横着读是 +、out、−,所以数据脚是中间那一只。+ 接 5V,− 接 GND,out 接 D2,把上面那段程序烧进去,再用 9600 波特率打开串口监视器。每两秒出现一行,就代表传感器在讲话。对着它轻轻呵一口气:湿度应该往上爬,然后慢慢降回来——这说明感测元件是活的,而不是只有校验和对而已。

DHT11 或 DHT22 可以校准吗?

严格说来不行。每一颗传感器都在出厂时校准过,系数烧在片上存储器里,它每读一次都会去查一次。奥松公布的,是给一颗被留在饱和空气里的传感器用的恢复流程:先在 50–60 °C、低于 10 %RH 的环境放一段时间,再在 20–30 °C、高于 70 %RH 的环境放几个小时。用饱和盐溶液做一个湿度罐,可以拿来核对读数靠不靠谱,但那不是一个你能写回传感器里的调整。

DHT22 传感器和 DHT22 模块有什么不同?

裸传感器就是那颗白色的四脚零件本身,上拉电阻要你自己接在数据脚和 VCC 之间。模块是同一颗零件装在一块载板上,电阻已经在板上了,并且把传感器那只没用到的第三只脚省掉——所以它出来是三针。传感器是同一颗;模块是那颗插上就能用的。

最后更新:2026 年 9 月。有问题?WhatsApp 联系我们

Leave a Reply

Your email address will not be published. Required fields are marked *