Arduino实验——DHT11读取温湿度

网友投稿 1196 2022-11-12

Arduino实验——DHT11读取温湿度

Arduino实验——DHT11读取温湿度

DHT11 介绍

DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它包括一个电阻式感湿元件和一个 NTC 测温元件。每个 DHT11 传 感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在 OTP 内存中,传感器内部在检测信号的处理过程中要调用这些校准系数,用户 无需重新校准。单线制串行接口,使系统集成变得简易快捷。超小的体积、 极低的功耗,信号传输距离可达 20 米以上。

接口说明

管脚

信号

说明

1

VCC

外接 3.3 - 5V

2

GND

外接 GND

3

DO

数字量输出接口,接单片机 IO 口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GemGbz1i-1575631984278)(./images/DHT11模块3.jpg)]

电气参数

电源电压:3~5.5V(典型值:5V);温度量程:0~50℃,误差 ±2℃;湿度量程:20~95%RH,误差 ±5%RH;采样周期:大于等于1秒/次。

硬件连接

数据总线 DATA 使用上拉电阻拉高,因此总线空闲时为高电平。上拉电阻阻值推荐范围:4.7K~5.1K。必要时在 VDD 和 GND 之间并一个 100nF 的去耦电容。

本实验将传感器的 DATA 引脚连接到 Arduino 的 D2 口。

工作原理

DHT11 使用单一总线通信,即 DATA 引脚和单片机连接的线。总线总是处于 空闲状态 和 通信状态 这个2个状态之间。当单片机没有与 DHT11 交互时,总线处于空闲状态,在上拉电阻的作用下,处于高电平状态。当单片机和 DHT11 正在通信时,总线处于通信状态,一次完整的通信过程如下:

可以发现一帧为 40个bit,而每一个 bit 的传输时序逻辑为:每一个 bit 都以 50us 的低电平(DHT11 将总线拉低)为先导,然后紧接着 DHT11 拉高总线,如果这个高电平持续时间为 26~28us,则代表逻辑 0,如果持续 70us 则代表逻辑 1。

注意事项

DHT11 上电后,要等待 1 秒以越过不稳定状态,在此期间不能发送任何指令。DHT11 属于低速传感器,两次通信请求之间的间隔时间不能太短,一般来说要不能低于1秒。当前 DHT11 通信帧的小数部分默认都是 0,厂商预留给以后实现,所以一般只读取整数值部分即可。校验和定义为:前 4 个 Byte 的总和的低 8 位。

Arduino Test

#include "dht11.h"#define DHT_PIN 2DHT11 dht11(DHT_PIN);void setup(){ Serial.begin(9600); Serial.println("DHT11 TEST PROGRAM "); Serial.print("LIBRARY VERSION: "); Serial.println(DHT11LIB_VERSION); Serial.println();}void loop(){ // Wait a few seconds between measurements. delay(2000); int ret = dht11.read(); if(ret == DHTLIB_ERROR_CHECKSUM) { Serial.println("(E) Checksum failed"); return; } else if(ret == DHTLIB_ERROR_TIMEOUT) { Serial.println("(E) Read time out"); return; } Serial.print("Humidity: "); Serial.print((float)dht11.getHumidity(), 2); Serial.print("% Temperature: "); Serial.print((float)dht11.getTemperature(), 2); Serial.print("'C "); Serial.print((float)dht11.getTemperature(true), 2); Serial.println("'F");}

运行效果:

DHT11 类

这里使用了我自定义的类 DHT11,这个类在头文件 dht11.h 中,内容如下:

#ifndef dht11_h#define dht11_h#if defined(ARDUINO) && (ARDUINO >= 100)#include #else#include #endif#define DHT11LIB_VERSION "0.1.0"#define DHTLIB_OK 0#define DHTLIB_ERROR_CHECKSUM -1#define DHTLIB_ERROR_TIMEOUT -2#define BEGIN_TIME 20// ms#define GO_TIME 30// us#define REPLY_LOW_TIME 83// us#define REPLY_HIGH_TIME 87// us#define DATA_LOW_TIME 54// us#define DATA_HIGH_0_TIME 24// us#define DATA_HIGH_1_TIME 71// us#define RELEASE_TIME 54// us#define THINK_TIME 40// usclass DHT11{public: DHT11(uint8_t pin); uint8_t read(uint8_t usec=55); float getHumidity(); float getTemperature(bool isFahrenheit=false); float convertCtoK(float c); float convertCtoF(float c); float convertFtoC(float f); double dewPoint(double celsius, double humidity); double dewPointFast(double celsius, double humidity); float computeHeatIndex(float temperature, float percentHumidity, bool isFahrenheit=true);private: uint8_t data[5]; uint8_t _pin; void resetBuffer(uint8_t *buf, uint8_t size); uint8_t checksum();};#endif

函数实现在 dht11.c 中,在构造函数 ​​DHT11()​​​ 中初始化引脚,在 ​​read()​​​ 函数中实现与 dht11 传感器的通信并获取原始温湿度值,通过 ​​getHumidity()​​​ 和 ​​getTemperature()​​ 函数获取当前温湿度值。DHT11 类中同时提供了一些温湿度转换的功能函数,有需要的小伙伴可以测试一下。整个 dht11.c 文件的内容如下。

#include "dht11.h"/*! * @brief Instantiates a new DHT class * @param pin * pin number that sensor is connected */DHT11::DHT11(uint8_t pin) { _pin = pin; pinMode(_pin, INPUT_PULLUP);}/*! * @brief Reset the specific buffer * @param buf * buffer that you want to reset * @param size * how many bytes you want to reset */void DHT11::resetBuffer(uint8_t *buf, uint8_t size){ for (int i=0; i 5 BYTES or TIMEOUT for (int i=0; i<40; i++) { loopCnt = 10000; while(digitalRead(_pin) == LOW) if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT; t1 = micros(); loopCnt = 10000; while(digitalRead(_pin) == HIGH) if (loopCnt-- == 0) return DHTLIB_ERROR_TIMEOUT; t2 = micros(); if(t2 < t1) delta = UINT32_MAX - t1 + t2; else delta = t2 - t1; if(delta > THINK_TIME) { data[index] |= (1 << bit); } // Next byte or not if (bit == 0) { bit = 7; index++; } else bit--; } if (data[4] != checksum()) { return DHTLIB_ERROR_CHECKSUM; } return DHTLIB_OK;}/*! * @brief Calculate checksum * @return The last 8 bit of checksum value */uint8_t DHT11::checksum(){ uint16_t sum = 0; for(int i=0; i 79) { hi = -42.379 + 2.04901523 * temperature + 10.14333127 * percentHumidity + -0.22475541 * temperature * percentHumidity + -0.00683783 * pow(temperature, 2) + -0.05481717 * pow(percentHumidity, 2) + 0.00122874 * pow(temperature, 2) * percentHumidity + 0.00085282 * temperature * pow(percentHumidity, 2) + -0.00000199 * pow(temperature, 2) * pow(percentHumidity, 2); if ((percentHumidity < 13) && (temperature >= 80.0) && (temperature <= 112.0)) hi -= ((13.0 - percentHumidity) * 0.25) * sqrt((17.0 - abs(temperature - 95.0)) * 0.05882); else if ((percentHumidity > 85.0) && (temperature >= 80.0) && (temperature <= 87.0)) hi += ((percentHumidity - 85.0) * 0.1) * ((87.0 - temperature) * 0.2); } return isFahrenheit ? hi : convertFtoC(hi);}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Neo4j Spatial数据导入
下一篇:slf4j使用log4j的配置参数方式
相关文章

 发表评论

暂时没有评论,来抢沙发吧~