-
Notifications
You must be signed in to change notification settings - Fork 0
/
DHT11.cpp
165 lines (141 loc) · 5.15 KB
/
DHT11.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
* Dht11.cpp
*
* Version 0.5
*
* DHT11 Temperature and humidity sensor library for Arduino.
*
* See http://playground.arduino.cc/main/DHT11Lib
*
* License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
* Datasheet: http://www.micro4you.com/files/sensor/DHT11.pdf
*
* Modification History:
* - George Hadjikyriacou - Version 0.1 (??)
* - SimKard - Version 0.2 (24/11/2010)
* - Rob Tillaart - Version 0.3 (28/03/2011)
* * Added comments
* * Removed all non-DHT11 specific code
* * Added References
* - Rob Tillaart - Version 0.4 (17/03/2012)
* * Added Arduino 1.0 support
* - Rob Tillaart - Version 0.4.1 (19/05/2012)
* * Added error codes
* - Andy Dalton - Version 0.5 (13/09/2013)
* * Replaced magic numbers with named constants
* * Factored out repeated code into a helper method.
* * Made pin a parameter to the constructor instead of a parameter
* to read()
* * Changed the error codes to an enumeration
* * Update the temp/humidity only if the checksum is correct
* * Added more comments
*/
#include "Dht11.h"
#define BITS_IN(object) (8 * sizeof((object)))
// The version of this code
const char* const Dht11::VERSION = "0.5";
// Various named constants.
enum {
/*
* Time required to signal the DHT11 to switch from low power mode to
* running mode. 18 ms is the minimal, add a few extra ms to be safe.
*/
START_SIGNAL_WAIT = 20,
/*
* Once the start signal has been sent, we wait for a response. The doc
* says this should take 20-40 us, we wait 5 ms to be safe.
*/
RESPONSE_WAIT = 5,
/*
* The time threshold between a 0 bit and a 1 bit in the response. Times
* greater than this (in ms) will be considered a 1; otherwise they'll be
* considered a 0.
*/
ONE_THRESHOLD = 40,
/*
* The number of bytes we expect from the sensor. This consists of one
* byte for the integral part of the humidity, one byte for the fractional
* part of the humidity, one byte for the integral part of the temperature,
* one byte for the fractional part of the temperature, and one byte for
* a checksum. The DHT11 doesn't capture the fractional parts of the
* temperature and humidity, but it doesn't transmit data during those
* times.
*/
RESPONSE_SIZE = 5,
/*
* The number of bits in a bytes.
*/
BITS_PER_BYTE = 8,
/*
* The 0-base most significant bit in a byte.
*/
BYTE_MS_BIT = 7,
/*
* The index in the response where the humidity reading is stored.
*/
HUMIDITY_INDEX = 0,
/*
* The index in the response where the temperature is stored.
*/
TEMPERATURE_INDEX = 2,
/*
* The index in the response where the checksum is stored.
*/
CHECKSUM_INDEX = 4,
};
Dht11::ReadStatus Dht11::read() {
uint8_t buffer[RESPONSE_SIZE] = { 0 };
uint8_t bitIndex = BYTE_MS_BIT;
ReadStatus status = OK;
// Request sample
pinMode(this->pin, OUTPUT);
digitalWrite(this->pin, LOW);
delay(START_SIGNAL_WAIT);
// Wait for response
digitalWrite(this->pin, HIGH);
delayMicroseconds(RESPONSE_WAIT);
pinMode(this->pin, INPUT);
// Acknowledge or timeout
// Response signal should first be low for 80us...
if ((status = this->waitForPinChange(LOW)) != OK) {
goto done;
}
// ... then be high for 80us ...
if ((status = this->waitForPinChange(HIGH)) != OK) {
goto done;
}
/*
* ... then provide 5 bytes of data that include the integral part of the
* humidity, the fractional part of the humidity, the integral part of the
* temperature, the fractional part of the temperature, and a checksum
* that is the sum of the integral parts of humidity and temperature.
*/
for (size_t i = 0; i < BITS_IN(buffer); i++) {
if ((status = this->waitForPinChange(LOW)) != OK) {
goto done;
}
unsigned long highStart = micros();
if ((status = this->waitForPinChange(HIGH)) != OK) {
goto done;
}
// 26-28 us = 0, 50 us = 1. 40 us is a good threshold between 0 and 1
if ((micros() - highStart) > ONE_THRESHOLD) {
buffer[i / BITS_PER_BYTE] |= (1 << bitIndex);
}
// Decrement or reset bitIndex
bitIndex = (bitIndex > 0) ? bitIndex - 1 : BYTE_MS_BIT;
}
// Check the checksum. Only if it's good, record the new values.
if (buffer[CHECKSUM_INDEX] == ( buffer[HUMIDITY_INDEX]
+ buffer[TEMPERATURE_INDEX])) {
// buffer[1] and buffer[3] should be the fractional parts of the
// humidity and temperature, respectively, but the DHT11 doesn't
// provide those values, so we omit them here.
this->humidity = buffer[HUMIDITY_INDEX];
this->temperature = buffer[TEMPERATURE_INDEX];
} else {
status = ERROR_CHECKSUM;
}
done:
return status;
}