极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 37170|回复: 14

【教程】 DHT11 湿度温度传感器 Q & A

[复制链接]
发表于 2015-4-29 03:39:05 | 显示全部楼层 |阅读模式
本帖最后由 tsaiwn 于 2015-4-29 03:47 编辑

Q: DHT11 的教程何处找 ?
A:
   请看官方网站的关于 DHT11Lib:
      http://playground.arduino.cc/Main/DHT11Lib
   里面就有:
      dht11.h
      dht11.cpp
     以及范例 test_dewpoint.ino

   里面也有教你怎么用:
   (a)在 arduino IDE 的 libraries 目录下建立一个目录 dht11 (其实名称不重要),
      然后用文本编辑器复制贴上该 dht11.h 与 dht11.cpp 存盘到该 dht11 目录内!
   (b)建立新草稿码档案
      把 范例 test_dewpoint.ino 复制贴入即可
   (c)当然要记得把你 DHT11 传感器的 Data pin 连接到 Arduino 的 Pin 2
        ( 因为范例中用 #define DHT11PIN 2  )


Q: DHT11 如何连接 ?
A:
   DHT11       Arduino
   VDD -----    5Volt 或 3.3V 也可
   Data -----  任何 pin 都可接收信号
   NC   -----  不管它
   GND  -----   GND

Q: DHT11 要使用库文件吗 ?
A:
   不使用库直接写当然可以, 例如:
     http://www.geek-workshop.com/thread-14544-1-1.html
   但使用库可让你的程序码看起来短短的容易理解!  (后面有给超级简单范例)

Q: DHT11 的库在哪 ?
A:
   网络上可以找到很多 DHT11 的库, 最简单的就刚刚最前面说的,
   在官方网站  http://playground.arduino.cc/Main/DHT11Lib
   它有教你如何把库放进去(英文的? 我前面不是翻译了吗 !)
   好啦,
   我做成压缩文件放在最后(用我这去解压缩比较好, 用了后在IDE内仔细看我给的简单范例就知道!)


Q: DHT11 的库要如何安装 ?
A:
   刚刚说过了啊, 不然下载这篇内的 Dht11.zip 后,
   存到你的 arduino IDE 内的  libraries 目录内, 解压缩即可!
   或是 Sketch  >  Import Library...  >  Add Library...
   然后选该下载的压缩文件
   注意这样安装库会跑到你的 sketch 草稿簿目录下的 libraries 目录!

Q: DHT11 的湿度与温度为何小数部分都永远是 0 ?
A:
   DHT11 本来就是湿度与温度都只有整数,
   如果你要有小数, 可改用 DHT22 / DHT33 / DHT44
   但注意 DHT11 的库不能用于 DHT22/33/44 喔, 可以改用这:
      http://playground.arduino.cc/Main/DHTLib

Q: 把 DHT11 与其他传感器合用后为何就湿度与温度都是 0 ?
A:
   DHT11 读取数据时不可以被 ISR( ) 中断太久,
   所以如果你其他会用到中断处理程序 ISR( ) 且会在 ISR( ) 内超过 20 us 那就可能会有问题!
   请注意, 20us 其实很久, 通常在 ISR( ) 内不应该做太多事情 !
   以 16MHz 的 clock 来说, 20us 大约可以执行 80句 C/C++ 语言的指令!
   此时简单的解决方式就是在对 DHT11 做 .read(pin); 之前写 cli( ); 禁止中断 !
   在 .read(pin); 之后立即写 sei( ); 以便允许中断 !

Q: 我只在  ISR( ) 内做了 analogRead( ) 并把数据用 Serial.println( ) 共两句怎就出问题了?
   不是说可以用 20us 做 80句左右吗?
A:
   ㄟ, 那句 analogRead( ) 就要大约 108us 喔!
   请注意, analogRead( ) 不是一句, 是调用一个函数, 且该函数要等待硬件做 A to D 转换,
   所以像这要花掉大约 0.11 ms 的句子不太应该在 ISR( ) 内做
   另外, Serial.print( ) 虽然通常不太占用 CPU 时间,
   但是串口输出缓存区只有 64 char, 如果你的中断来得太快,
   导致把串口输出缓存区塞满, 则之后的 .print( ) 就变成要花 CPU 的时间等待,
   在波特率 9600 之下, 打印一个 char 就要大约 1.1ms = 1100us,
   这是非常非常慢的事!
   所以通常建议不可以在中断处理程序内做 Serial.print 输出的事情 !

Q: 为何湿度与温度都不会变 ?
A:
   你可能只有在 setup( ) 内对 dht11 做 .read(pin) 一次,
   然后在 loop( ) { 内都没再去 .read(pin);
   注意, 如果 DHT11 是代表 dht11 的类别对象(对象, Object),
   则 DHT11.read(2); 才是通过 Pin 2 去跟 DHT11 要数据,
   如果你只是写 int temp = DHT11.temperature;
   这样只是拿到上次 .read( ) 拿回内存的温度, 并没有去跟 DHT11 要数据 !!

Q: 官方网站的范例太复杂, 有没有简单些的范例 ?
A:
   好吧, 我就写一个超级短的范例给大家测试:
     (也放入了底下的Dht11.zip压缩文件内)
     (dht11 庫要用我这去解压缩比较好, 至于怎么好, 用了后在IDE内仔细看我给的简单范例就知道!)

  1. //simple dht11 testing example -- by tsaiwn @ cs.nctu.edu.tw
  2. #include <dht11.h>
  3. dht11 ggyy;   // 注意现在 ggyy 代表 DHT11 传感器
  4. const int pin = 2;  // 请把 DHT11 的 data pin 连到 arduino Pin 2
  5. void setup( ) {
  6.   Serial.begin(9600);
  7. }
  8. void loop( ) {
  9.   ggyy.read(pin);  // 读取 DHT11 传感器
  10.   Serial.print(String("") + "Humidity = "+ ggyy.humidity + " %");
  11.   Serial.println(String("")+", temperature = "+ ggyy.temperature +" °C");
  12.   delay(2222);  // 规定至少要等 2 秒再次读 dht11
  13. }
复制代码


这样够简短了吧 ?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2015-4-29 03:57:15 | 显示全部楼层
这也补一张图片方便查看

回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-29 04:01:26 | 显示全部楼层
tsaiwn 发表于 2015-4-29 03:57
这也补一张图片方便查看

方便查看
Reference
     http://playground.arduino.cc/Main/DHT11Lib

dht11.h
  1. //
  2. //    FILE: dht11.h
  3. // VERSION: 0.4.1
  4. // PURPOSE: DHT11 Temperature & Humidity Sensor library for Arduino
  5. // LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
  6. //
  7. // DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
  8. //
  9. //     URL: http://playground.arduino.cc/Main/DHT11Lib
  10. //
  11. // HISTORY:
  12. // George Hadjikyriacou - Original version
  13. // see dht.cpp file
  14. //

  15. #ifndef dht11_h
  16. #define dht11_h

  17. #if defined(ARDUINO) && (ARDUINO >= 100)
  18. #include <Arduino.h>
  19. #else
  20. #include <WProgram.h>
  21. #endif

  22. #define DHT11LIB_VERSION "0.4.1"

  23. #define DHTLIB_OK                                0
  24. #define DHTLIB_ERROR_CHECKSUM        -1
  25. #define DHTLIB_ERROR_TIMEOUT        -2

  26. class dht11
  27. {
  28. public:
  29.     int read(int pin);
  30.         int humidity;
  31.         int temperature;
  32. };
  33. #endif
  34. //
  35. // END OF FILE
  36. //
复制代码
dht11.cpp
  1. //
  2. //    FILE: dht11.cpp
  3. // VERSION: 0.4.1
  4. // PURPOSE: DHT11 Temperature & Humidity Sensor library for Arduino
  5. // LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
  6. //
  7. // DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
  8. //
  9. // HISTORY:
  10. // George Hadjikyriacou - Original version (??)
  11. // Mod by SimKard - Version 0.2 (24/11/2010)
  12. // Mod by Rob Tillaart - Version 0.3 (28/03/2011)
  13. // + added comments
  14. // + removed all non DHT11 specific code
  15. // + added references
  16. // Mod by Rob Tillaart - Version 0.4 (17/03/2012)
  17. // + added 1.0 support
  18. // Mod by Rob Tillaart - Version 0.4.1 (19/05/2012)
  19. // + added error codes
  20. //

  21. #include "dht11.h"

  22. // Return values:
  23. // DHTLIB_OK
  24. // DHTLIB_ERROR_CHECKSUM
  25. // DHTLIB_ERROR_TIMEOUT
  26. int dht11::read(int pin)
  27. {
  28.         // BUFFER TO RECEIVE
  29.         uint8_t bits[5];
  30.         uint8_t cnt = 7;
  31.         uint8_t idx = 0;

  32.         // EMPTY BUFFER
  33.         for (int i=0; i< 5; i++) bits[i] = 0;

  34.         // REQUEST SAMPLE
  35.         pinMode(pin, OUTPUT);
  36.         digitalWrite(pin, LOW);
  37.         delay(18);
  38.         digitalWrite(pin, HIGH);
  39.         delayMicroseconds(40);
  40.         pinMode(pin, INPUT);

  41.         // ACKNOWLEDGE or TIMEOUT
  42.         unsigned int loopCnt = 10000;
  43.         while(digitalRead(pin) == LOW)
  44.                 if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

  45.         loopCnt = 10000;
  46.         while(digitalRead(pin) == HIGH)
  47.                 if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

  48.         // READ OUTPUT - 40 BITS => 5 BYTES or TIMEOUT
  49.         for (int i=0; i<40; i++)
  50.         {
  51.                 loopCnt = 10000;
  52.                 while(digitalRead(pin) == LOW)
  53.                         if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

  54.                 unsigned long t = micros();

  55.                 loopCnt = 10000;
  56.                 while(digitalRead(pin) == HIGH)
  57.                         if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

  58.                 if ((micros() - t) > 40) bits[idx] |= (1 << cnt);
  59.                 if (cnt == 0)   // next byte?
  60.                 {
  61.                         cnt = 7;    // restart at MSB
  62.                         idx++;      // next byte!
  63.                 }
  64.                 else cnt--;
  65.         }

  66.         // WRITE TO RIGHT VARS
  67.         // as bits[1] and bits[3] are allways zero they are omitted in formulas.
  68.         humidity    = bits[0];
  69.         temperature = bits[2];

  70.         uint8_t sum = bits[0] + bits[2];  

  71.         if (bits[4] != sum) return DHTLIB_ERROR_CHECKSUM;
  72.         return DHTLIB_OK;
  73. }
  74. //
  75. // END OF FILE
  76. //
复制代码
回复 支持 反对

使用道具 举报

发表于 2015-4-29 10:59:42 | 显示全部楼层
谢谢分享学习一下
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-4-30 01:23:58 | 显示全部楼层
本帖最后由 tsaiwn 于 2015-4-30 01:28 编辑
tsaiwn 发表于 2015-4-29 04:01
方便查看
Reference
     http://playground.arduino.cc/Main/DHT11Lib



再补充说明以下这段:

   这时 pin 刚变 LOW 表示 1 bit 正要传送过来
                loopCnt = 10000;
                while(digitalRead(pin) == LOW)
                        if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

   依据图片, dht11 的每个 bit 开始会拉低 50 us
   所以, 如果等了 51 us 还没变 HIGH 就可判定 timeout
   可是保险起见, 通常我们会多等一下, 例如等 80 us
   所以, 其实上述 loopCnt 应该设 300 就够了, 设 10000 是更保守
   如果 time out 就 return 返回了,
   会到这表示此时 pin 变 HIGH,
   立即用 t 记下 micros( )

                unsigned long t = micros();

                loopCnt = 10000;
                while(digitalRead(pin) == HIGH)
                        if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT;

依据图片, 如果这 bit 是 0,
则 dht11 会在 28 us 后拉低 pin,
如果这 bit 是 1, 则会让 pin 在 HIGH 维持 70 us 才拉低电平;
因此, 只要超过 90 us ( 保守一点啦)没变 LOW 就可判定 timeout
不过这 loopCnt = 10000; 相当于至少 250 us  是超级保守啰!
                if ((micros() - t) > 40) bits[idx] |= (1 << cnt);
    这句 if 是说如果收到的是 1 就把 1 塞入该 Byte 该有的位置
  为何用 micros( ) -t > 40 作条件呢?
  因为刚说了, 依据图片如果 bit 是 0, 则 HIGH 应维持约 28us,
        如果 bit 是 1, 则 HIGH 应维持 70 us;
        假如你用 micros( ) -t > 30 当然也可以,
        可是 28 和 30 太近, 万一 dht 自己时序不准确呢 !?
        所以保守一点, 用 40 us 当作门坎 !
        假如用 70 us 当门坎则也很危险,
        因万一 dht11 不准确在 68 us 就拉低, 那 1 就被判为 0 了,
        所以, 最好的门坎应该在 40 到 55 之间 !
还有,
从这就可看出万一你在 ISR( ) 内做太多事会影响 dht11 读取!
你看, 假如你刚做了 unsigned long t = micros();
  然后就被 ISR( ) 抢走 CPU 执行权,
  只要在 ISR( )内做超过 70 us 就铁定出问题 !
  Why ?
  因为这时 pin 一定已经变 LOW,
  然而在 ISR( ) 内因为中断禁止会导致 micros( ) 几乎不变!
     (注意, 中断禁止是 millis( ) 不会变, 但 micros( )略为会变!)
  这样相当于 Arduino 这边时间静止, 但其实 dht11 已经过了 70us,
  于是到底是 0 还是 1 我们会搞错!
  如果 ISR( ) 做事超过 78us, 甚至可能影响下一个 bit 的接收!
这里的 78us 是因为万一这 bit 是 0, 会在 28 us 后拉低电平,
表示另一个 bit 即将开始, 依据图片, 开始是拉低持续 50us,
所以, 78 us 之后我们就又拉高, 这样我们没看到拉低,
相当于错过了一个 bit 啰 !


注意喔,
一个 analogRead( ) 就要大约 108us =  大约0.11 ms
所以, 尽量不要在 ISR( ) 内做  analogRead( )

回复 支持 反对

使用道具 举报

发表于 2015-5-7 19:28:00 | 显示全部楼层
为什么DHT11返回的值是乱码的啊
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-5-7 20:52:42 | 显示全部楼层
yanglang00 发表于 2015-5-7 19:28
为什么DHT11返回的值是乱码的啊

什么叫做返回乱码
DHT11 返回的一定是 int
int 任何数值都是可能的整型,
如果你把它当作一个 char 就有可能是乱码 !
回复 支持 反对

使用道具 举报

发表于 2015-5-8 14:26:29 | 显示全部楼层
谢谢偶,差不多搞定了,原来是板卡选择错了
回复 支持 反对

使用道具 举报

发表于 2015-10-29 19:00:22 | 显示全部楼层
能加个QQ吗 我有一些问题想请教你
回复 支持 反对

使用道具 举报

发表于 2015-11-13 12:12:05 | 显示全部楼层
....大哥,您太 他 妈 精 辟了!!!!这一篇我断断续续从昨天晚上看到了现在,有些地方反复看了好几次!!谢您了,收获良多!!

哪天,能开个贴介绍一下mpu6050之类的姿态传感器吗?
回复 支持 反对

使用道具 举报

发表于 2015-11-13 22:14:27 来自手机 | 显示全部楼层
说的很详细了
回复 支持 反对

使用道具 举报

发表于 2018-1-14 18:35:43 | 显示全部楼层
高人分享的确实6666
回复 支持 反对

使用道具 举报

发表于 2018-1-16 15:00:56 | 显示全部楼层
为什么我的DH11湿度会乱跳。
回复 支持 反对

使用道具 举报

发表于 2018-4-19 19:27:57 | 显示全部楼层
您好,为什么我用的源程序,测试之后温度湿度一直显示零度
回复 支持 反对

使用道具 举报

发表于 2020-2-6 17:49:30 | 显示全部楼层
问下要用几个dht11该怎么做呢?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-18 16:24 , Processed in 0.060844 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表