├── DHT22.cpp ├── DHT22.h ├── README ├── examples └── Serial │ └── Serial.ino └── keywords.txt /DHT22.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DHT22.cpp - DHT22 sensor library 3 | Developed by Ben Adams - 2011 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | 20 | Humidity and Temperature Sensor DHT22 info found at 21 | http://www.sparkfun.com/products/10167 22 | 23 | Version 0.5: 15 Jan 2012 by Craig Ringer 24 | - Updated to build against Arduino 1.0 25 | - Made accessors inline in the header so they can be optimized away 26 | 27 | Version 0.4: 24-Jan-2011 by Ben Adams 28 | Added return code constants to keywords.txt 29 | Returns DHT_ERROR_CHECKSUM on check sum mismatch 30 | 31 | Version 0.3: 17-Jan-2011 by Ben Adams 32 | This version reads data 33 | Needs check sum code added at the end of readData 34 | 35 | Version 0.2: 16-Jan-2011 by Ben Adams 36 | Changed coding style to match other Arduino libraries. 37 | This version will not read data either! 38 | 39 | Version 0.1: 10-Jan-2011 by Ben Adams nethoncho AT gmail.com 40 | First Version is a skeleton. This version will not read data! 41 | Code adapted from the following sources: 42 | The Arduino OneWire lib 43 | http://sheepdogguides.com/arduino/ar3ne1humDHT11.htm 44 | 45 | */ 46 | 47 | #include "DHT22.h" 48 | #include 49 | #include 50 | 51 | extern "C" { 52 | #include 53 | #include 54 | #include 55 | } 56 | 57 | #define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) 58 | #define DIRECT_MODE_INPUT(base, mask) ((*(base+1)) &= ~(mask)) 59 | #define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) |= (mask)) 60 | #define DIRECT_WRITE_LOW(base, mask) ((*(base+2)) &= ~(mask)) 61 | //#define DIRECT_WRITE_HIGH(base, mask) ((*(base+2)) |= (mask)) 62 | 63 | // This should be 40, but the sensor is adding an extra bit at the start 64 | #define DHT22_DATA_BIT_COUNT 41 65 | 66 | DHT22::DHT22(uint8_t pin) 67 | { 68 | _bitmask = digitalPinToBitMask(pin); 69 | _baseReg = portInputRegister(digitalPinToPort(pin)); 70 | _lastReadTime = millis(); 71 | _lastHumidity = DHT22_ERROR_VALUE; 72 | _lastTemperature = DHT22_ERROR_VALUE; 73 | } 74 | 75 | // 76 | // Read the 40 bit data stream from the DHT 22 77 | // Store the results in private member data to be read by public member functions 78 | // 79 | DHT22_ERROR_t DHT22::readData() 80 | { 81 | uint8_t bitmask = _bitmask; 82 | volatile uint8_t *reg asm("r30") = _baseReg; 83 | uint8_t retryCount; 84 | uint8_t bitTimes[DHT22_DATA_BIT_COUNT]; 85 | int currentHumidity; 86 | int currentTemperature; 87 | uint8_t checkSum, csPart1, csPart2, csPart3, csPart4; 88 | unsigned long currentTime; 89 | int i; 90 | 91 | currentHumidity = 0; 92 | currentTemperature = 0; 93 | checkSum = 0; 94 | currentTime = millis(); 95 | for(i = 0; i < DHT22_DATA_BIT_COUNT; i++) 96 | { 97 | bitTimes[i] = 0; 98 | } 99 | 100 | if(currentTime - _lastReadTime < 2000) 101 | { 102 | // Caller needs to wait 2 seconds between each call to readData 103 | return DHT_ERROR_TOOQUICK; 104 | } 105 | _lastReadTime = currentTime; 106 | 107 | // Pin needs to start HIGH, wait until it is HIGH with a timeout 108 | cli(); 109 | DIRECT_MODE_INPUT(reg, bitmask); 110 | sei(); 111 | retryCount = 0; 112 | do 113 | { 114 | if (retryCount > 125) 115 | { 116 | return DHT_BUS_HUNG; 117 | } 118 | retryCount++; 119 | delayMicroseconds(2); 120 | } while(!DIRECT_READ(reg, bitmask)); 121 | // Send the activate pulse 122 | cli(); 123 | DIRECT_WRITE_LOW(reg, bitmask); 124 | DIRECT_MODE_OUTPUT(reg, bitmask); // Output Low 125 | sei(); 126 | delayMicroseconds(1100); // 1.1 ms 127 | cli(); 128 | DIRECT_MODE_INPUT(reg, bitmask); // Switch back to input so pin can float 129 | sei(); 130 | // Find the start of the ACK Pulse 131 | retryCount = 0; 132 | do 133 | { 134 | if (retryCount > 25) //(Spec is 20 to 40 us, 25*2 == 50 us) 135 | { 136 | return DHT_ERROR_NOT_PRESENT; 137 | } 138 | retryCount++; 139 | delayMicroseconds(2); 140 | } while(!DIRECT_READ(reg, bitmask)); 141 | // Find the end of the ACK Pulse 142 | retryCount = 0; 143 | do 144 | { 145 | if (retryCount > 50) //(Spec is 80 us, 50*2 == 100 us) 146 | { 147 | return DHT_ERROR_ACK_TOO_LONG; 148 | } 149 | retryCount++; 150 | delayMicroseconds(2); 151 | } while(DIRECT_READ(reg, bitmask)); 152 | // Read the 40 bit data stream 153 | for(i = 0; i < DHT22_DATA_BIT_COUNT; i++) 154 | { 155 | // Find the start of the sync pulse 156 | retryCount = 0; 157 | do 158 | { 159 | if (retryCount > 35) //(Spec is 50 us, 35*2 == 70 us) 160 | { 161 | return DHT_ERROR_SYNC_TIMEOUT; 162 | } 163 | retryCount++; 164 | delayMicroseconds(2); 165 | } while(!DIRECT_READ(reg, bitmask)); 166 | // Measure the width of the data pulse 167 | retryCount = 0; 168 | do 169 | { 170 | if (retryCount > 50) //(Spec is 80 us, 50*2 == 100 us) 171 | { 172 | return DHT_ERROR_DATA_TIMEOUT; 173 | } 174 | retryCount++; 175 | delayMicroseconds(2); 176 | } while(DIRECT_READ(reg, bitmask)); 177 | bitTimes[i] = retryCount; 178 | } 179 | // Now bitTimes have the number of retries (us *2) 180 | // that were needed to find the end of each data bit 181 | // Spec: 0 is 26 to 28 us 182 | // Spec: 1 is 70 us 183 | // bitTimes[x] <= 11 is a 0 184 | // bitTimes[x] > 11 is a 1 185 | // Note: the bits are offset by one from the data sheet, not sure why 186 | for(i = 0; i < 16; i++) 187 | { 188 | if(bitTimes[i + 1] > 11) 189 | { 190 | currentHumidity |= (1 << (15 - i)); 191 | } 192 | } 193 | for(i = 0; i < 16; i++) 194 | { 195 | if(bitTimes[i + 17] > 11) 196 | { 197 | currentTemperature |= (1 << (15 - i)); 198 | } 199 | } 200 | for(i = 0; i < 8; i++) 201 | { 202 | if(bitTimes[i + 33] > 11) 203 | { 204 | checkSum |= (1 << (7 - i)); 205 | } 206 | } 207 | 208 | _lastHumidity = currentHumidity & 0x7FFF; 209 | if(currentTemperature & 0x8000) 210 | { 211 | // Below zero, non standard way of encoding negative numbers! 212 | // Convert to native negative format. 213 | _lastTemperature = -(currentTemperature & 0x7FFF); 214 | } 215 | else 216 | { 217 | _lastTemperature = currentTemperature; 218 | } 219 | 220 | csPart1 = currentHumidity >> 8; 221 | csPart2 = currentHumidity & 0xFF; 222 | csPart3 = currentTemperature >> 8; 223 | csPart4 = currentTemperature & 0xFF; 224 | if(checkSum == ((csPart1 + csPart2 + csPart3 + csPart4) & 0xFF)) 225 | { 226 | return DHT_ERROR_NONE; 227 | } 228 | return DHT_ERROR_CHECKSUM; 229 | } 230 | 231 | // 232 | // This is used when the millis clock rolls over to zero 233 | // 234 | void DHT22::clockReset() 235 | { 236 | _lastReadTime = millis(); 237 | } 238 | -------------------------------------------------------------------------------- /DHT22.h: -------------------------------------------------------------------------------- 1 | #ifndef _DHT22_H_ 2 | #define _DHT22_H_ 3 | 4 | #include 5 | 6 | #define DHT22_ERROR_VALUE -995 7 | 8 | typedef enum 9 | { 10 | DHT_ERROR_NONE = 0, 11 | DHT_BUS_HUNG, 12 | DHT_ERROR_NOT_PRESENT, 13 | DHT_ERROR_ACK_TOO_LONG, 14 | DHT_ERROR_SYNC_TIMEOUT, 15 | DHT_ERROR_DATA_TIMEOUT, 16 | DHT_ERROR_CHECKSUM, 17 | DHT_ERROR_TOOQUICK 18 | } DHT22_ERROR_t; 19 | 20 | class DHT22 21 | { 22 | private: 23 | uint8_t _bitmask; 24 | volatile uint8_t *_baseReg; 25 | unsigned long _lastReadTime; 26 | short int _lastHumidity; 27 | short int _lastTemperature; 28 | 29 | public: 30 | DHT22(uint8_t pin); 31 | DHT22_ERROR_t readData(); 32 | short int getHumidityInt(); 33 | short int getTemperatureCInt(); 34 | void clockReset(); 35 | #if !defined(DHT22_NO_FLOAT) 36 | float getHumidity(); 37 | float getTemperatureC(); 38 | float getTemperatureF(); 39 | #endif 40 | }; 41 | 42 | // Report the humidity in .1 percent increments, such that 635 means 63.5% relative humidity 43 | // 44 | // Converts from the internal integer format on demand, so you might want 45 | // to cache the result. 46 | inline short int DHT22::getHumidityInt() 47 | { 48 | return _lastHumidity; 49 | } 50 | 51 | // Get the temperature in decidegrees C, such that 326 means 32.6 degrees C. 52 | // The temperature may be negative, so be careful when handling the fractional part. 53 | inline short int DHT22::getTemperatureCInt() 54 | { 55 | return _lastTemperature; 56 | } 57 | 58 | #if !defined(DHT22_NO_FLOAT) 59 | // Return the percentage relative humidity in decimal form 60 | inline float DHT22::getHumidity() 61 | { 62 | return float(_lastHumidity)/10; 63 | } 64 | #endif 65 | 66 | #if !defined(DHT22_NO_FLOAT) 67 | // Return the percentage relative humidity in decimal form 68 | // 69 | // Converts from the internal integer format on demand, so you might want 70 | // to cache the result. 71 | inline float DHT22::getTemperatureC() 72 | { 73 | return float(_lastTemperature)/10; 74 | } 75 | 76 | inline float DHT22::getTemperatureF() 77 | { 78 | return float(_lastTemperature) / 10 * 9 / 5 + 32; 79 | } 80 | #endif //DHT22_SUPPORT_FLOAT 81 | 82 | #endif /*_DHT22_H_*/ 83 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This repo has been archived. 2 | Checkout https://github.com/adafruit/DHT-sensor-library for a maintained code base. 3 | 4 | DHT22 sensor library 5 | Developed by Ben Adams - 2011 6 | 7 | Humidity and Temperature Sensor DHT22 info found at 8 | http://www.sparkfun.com/products/10167 9 | The same sensor has also been spotted going by the names RHT22, AM2302 10 | and RHT03 from a variety of vendors. It uses a non-standard 1-wire digital 11 | signalling protocol. 12 | 13 | To install this library for use with the Arduino IDE, copy it 14 | to the `libraries' folder and restart the IDE. For an example of 15 | how to use it, see File->Examples->DHT22->Serial . 16 | 17 | Version 0.5: 15-Jan-2012 by Craig Ringer 18 | Update to support Arduino 1.0 19 | Make accessors inlineable so they can be optimised away 20 | Preserve original integer values from sensor and offer access to them 21 | Permit floating point support to be disalbed by defining DHT22_NO_FLOAT before including DHT22.h 22 | 23 | Version 0.4: 24-Jan-2011 by Ben Adams 24 | Added return code constants to keywords.txt 25 | Returns DHT_ERROR_CHECKSUM on check sum mismatch 26 | 27 | Version 0.3: 17-Jan-2011 by Ben Adams 28 | This version reads data 29 | Needs check sum code added at the end of readData 30 | 31 | Version 0.2: 16-Jan-2011 by Ben Adams 32 | Changed coding style to match other Arduino libraries. 33 | This version will not read data either! 34 | 35 | Version 0.1: 10-Jan-2011 by Ben Adams nethoncho AT gmail.com 36 | First Version is a skeleton. This version will not read data! 37 | Code adapted from the following sources: 38 | The Arduino OneWire lib 39 | http://sheepdogguides.com/arduino/ar3ne1humDHT11.htm 40 | -------------------------------------------------------------------------------- /examples/Serial/Serial.ino: -------------------------------------------------------------------------------- 1 | #include 2 | // Only used for sprintf 3 | #include 4 | 5 | // Data wire is plugged into port 7 on the Arduino 6 | // Connect a 4.7K resistor between VCC and the data pin (strong pullup) 7 | #define DHT22_PIN 7 8 | 9 | // Setup a DHT22 instance 10 | DHT22 myDHT22(DHT22_PIN); 11 | 12 | void setup(void) 13 | { 14 | // start serial port 15 | Serial.begin(9600); 16 | Serial.println("DHT22 Library Demo"); 17 | } 18 | 19 | void loop(void) 20 | { 21 | DHT22_ERROR_t errorCode; 22 | 23 | // The sensor can only be read from every 1-2s, and requires a minimum 24 | // 2s warm-up after power-on. 25 | delay(2000); 26 | 27 | Serial.print("Requesting data..."); 28 | errorCode = myDHT22.readData(); 29 | switch(errorCode) 30 | { 31 | case DHT_ERROR_NONE: 32 | Serial.print("Got Data "); 33 | Serial.print(myDHT22.getTemperatureC()); 34 | Serial.print("C "); 35 | Serial.print(myDHT22.getHumidity()); 36 | Serial.println("%"); 37 | // Alternately, with integer formatting which is clumsier but more compact to store and 38 | // can be compared reliably for equality: 39 | // 40 | char buf[128]; 41 | sprintf(buf, "Integer-only reading: Temperature %hi.%01hi C, Humidity %i.%01i %% RH", 42 | myDHT22.getTemperatureCInt()/10, abs(myDHT22.getTemperatureCInt()%10), 43 | myDHT22.getHumidityInt()/10, myDHT22.getHumidityInt()%10); 44 | Serial.println(buf); 45 | break; 46 | case DHT_ERROR_CHECKSUM: 47 | Serial.print("check sum error "); 48 | Serial.print(myDHT22.getTemperatureC()); 49 | Serial.print("C "); 50 | Serial.print(myDHT22.getHumidity()); 51 | Serial.println("%"); 52 | break; 53 | case DHT_BUS_HUNG: 54 | Serial.println("BUS Hung "); 55 | break; 56 | case DHT_ERROR_NOT_PRESENT: 57 | Serial.println("Not Present "); 58 | break; 59 | case DHT_ERROR_ACK_TOO_LONG: 60 | Serial.println("ACK time out "); 61 | break; 62 | case DHT_ERROR_SYNC_TIMEOUT: 63 | Serial.println("Sync Timeout "); 64 | break; 65 | case DHT_ERROR_DATA_TIMEOUT: 66 | Serial.println("Data Timeout "); 67 | break; 68 | case DHT_ERROR_TOOQUICK: 69 | Serial.println("Polled to quick "); 70 | break; 71 | } 72 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For DHT22 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DHT22 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | readData KEYWORD2 16 | getHumidity KEYWORD2 17 | getHumidityInt KEYWORD2 18 | getTemperatureC KEYWORD2 19 | getTemperatureCInt KEYWORD2 20 | clockReset KEYWORD2 21 | 22 | ####################################### 23 | # Instances (KEYWORD2) 24 | ####################################### 25 | 26 | 27 | ####################################### 28 | # Constants (LITERAL1) 29 | ####################################### 30 | 31 | DHT_ERROR_NONE LITERAL1 32 | DHT_BUS_HUNG LITERAL1 33 | DHT_ERROR_NOT_PRESENT LITERAL1 34 | DHT_ERROR_ACK_TOO_LONG LITERAL1 35 | DHT_ERROR_SYNC_TIMEOUT LITERAL1 36 | DHT_ERROR_DATA_TIMEOUT LITERAL1 37 | DHT_ERROR_CHECKSUM LITERAL1 38 | DHT_ERROR_TOOQUICK LITERAL1 39 | --------------------------------------------------------------------------------