DHT22 library, based on Simon Cooksey's. Improved with some error checking and more rigid timing (interrupts off).
Fork of lib_dht22 by
dht22.cpp
00001 /* 00002 * (C) The University of Kent and Simon Cooksey 2015. 00003 * Proddled a bit by Fred 00004 */ 00005 00006 #include "mbed.h" 00007 #include <inttypes.h> 00008 00009 #include "dht22.h" 00010 00011 /* 00012 * The DHT22 uses a 1 wire interface, sending 1's and 0s by varying the length 00013 * of the HIGH time on the signal pin. 00014 */ 00015 00016 /* delay for approx 2 microseconds */ 00017 void DHT22::wait_2us (void) 00018 { 00019 int i; 00020 00021 /* 16 * 14 nops, plus loopend */ 00022 for (i=0; i<16; i++) { 00023 __asm__ __volatile__ (" \n" \ 00024 " nop \n" \ 00025 " nop \n" \ 00026 " nop \n" \ 00027 " nop \n" \ 00028 " nop \n" \ 00029 " nop \n" \ 00030 " nop \n" \ 00031 " nop \n" \ 00032 " nop \n" \ 00033 " nop \n" \ 00034 " nop \n" \ 00035 " nop \n" \ 00036 " nop \n" \ 00037 " nop \n"); 00038 00039 } 00040 return; 00041 } 00042 00043 00044 /* ensure the comms pin is set for input */ 00045 void DHT22::setinput (void) 00046 { 00047 if (!isinput) { 00048 dht22_s.input (); 00049 isinput = 1; 00050 } 00051 } 00052 00053 /* ensure the comms pin is set for output */ 00054 void DHT22::setoutput (void) 00055 { 00056 if (isinput) { 00057 dht22_s.output (); 00058 isinput = 0; 00059 } 00060 } 00061 00062 00063 int DHT22::wait_for_level (int lvl, const int max) 00064 { 00065 int time; 00066 00067 setinput (); 00068 00069 for (time=0; ((max == -1) || (time < max)) && (dht22_s != lvl); time += 2) { 00070 wait_2us (); 00071 } 00072 if ((max > 0) && (time >= max)) { 00073 /* timed out */ 00074 return -1; 00075 } 00076 00077 if (time) { 00078 /* means we saw a transition, so let it settle */ 00079 wait_2us (); 00080 time += 2; 00081 } 00082 00083 return time; 00084 } 00085 00086 00087 /* 00088 * Send a start bit to the DHT22 00089 */ 00090 void DHT22::send_start (void) 00091 { 00092 int dly; 00093 00094 //__disable_irq (); 00095 setoutput (); 00096 dht22_s = 0; 00097 /* drag low for 1ms */ 00098 for (dly=0; dly<(DHT22_START_BIT_TIME >> 1); dly++) { 00099 wait_2us (); 00100 } 00101 // wait_us (DHT22_START_BIT_TIME); 00102 dht22_s = 1; 00103 setinput (); 00104 //__enable_irq (); 00105 } 00106 00107 /* 00108 * Wait for the DHT22 to send the start bit ACK, after this we can read data. 00109 */ 00110 int DHT22::wait_start (void) 00111 { 00112 /* level should be 1 */ 00113 if (dht22_s == 0) { 00114 return -1; 00115 } 00116 if (wait_for_level (0, 500) < 0) { 00117 /* should respond in 20-200 us, it didn't in 500 */ 00118 return -2; 00119 } 00120 if (wait_for_level (1, 100) < 0) { 00121 /* only for 80 us (max 85 in datasheet) */ 00122 return -3; 00123 } 00124 if (wait_for_level (0, 100) < 0) { 00125 /* only for 80 us (max 85 in datasheet) */ 00126 return -4; 00127 } 00128 /* at this point we're about to start seeing the MSB of data [39-0] */ 00129 00130 return 0; 00131 } 00132 00133 /* 00134 * reads 8 bits of data, returns value [0-255] on success, -1 on error (timeout) 00135 */ 00136 int DHT22::read_byte (void) 00137 { 00138 int d, bit; 00139 int v = 0; 00140 00141 /* should be zero already */ 00142 if (dht22_s == 1) { 00143 return -1; 00144 } 00145 00146 for (bit=7; bit>=0; bit--) { 00147 /* expect it to stay low for 50us (max 55) */ 00148 if (wait_for_level (1, 100) < 0) { 00149 /* timed out after 100us */ 00150 return -2; 00151 } 00152 00153 00154 d = wait_for_level (0, 100); 00155 if (d < 0) { 00156 /* timed out after 100us */ 00157 return -3; 00158 } 00159 00160 00161 if (d > DHT22_SIGNAL_HIGH_LOW_BOUNDARY) { 00162 v |= (1 << bit); 00163 #ifdef DEBUG_DHT22 00164 debug = 1; 00165 } else { 00166 debug = 0; 00167 #endif 00168 } 00169 00170 } 00171 return v; 00172 } 00173 00174 00175 /* 00176 * Reads a packet of DHT22 data. 00177 * 00178 * Param data: the packet to fill. returns 0 on success, < 0 on error (timeout of some kind) 00179 */ 00180 int DHT22::read (DHT22_data_t *data) 00181 { 00182 uint8_t buf[5]; 00183 uint16_t u_hum, u_tmp; 00184 int i; 00185 00186 #ifdef DEBUG_DHT22 00187 debug = 0; 00188 #endif 00189 __disable_irq (); 00190 // Send start bits 00191 send_start(); 00192 00193 if (wait_start () < 0) { 00194 __enable_irq (); 00195 return -1; /* timed out waiting for start response */ 00196 } 00197 /* read 40 bits worth -- MSB first */ 00198 for (i=4; i>=0; i--) { 00199 int v = read_byte (); 00200 00201 if (v < 0) { 00202 /* timed out waiting for data */ 00203 __enable_irq (); 00204 return -2; 00205 } 00206 buf[i] = (uint8_t)v; 00207 } 00208 00209 /* yay, got here! -- sensor should release the wire in 50us (max 55) */ 00210 if (wait_for_level (1, 100) < 0) { 00211 /* timed out at this point, but still fill the buffer */ 00212 i = -3; 00213 } else { 00214 i = 0; 00215 } 00216 __enable_irq (); 00217 00218 /* unscramble */ 00219 u_hum = ((uint16_t)buf[4] << 8) | buf[3]; 00220 u_tmp = ((uint16_t)buf[2] << 8) | buf[1]; 00221 00222 if (u_hum & 0x8000) { 00223 data->humidity = 1 - (int)(u_hum ^ 0x8000); 00224 } else { 00225 data->humidity = (int)u_hum; 00226 } 00227 if (u_tmp & 0x8000) { 00228 data->temp = 1 - (int)(u_tmp ^ 0x8000); 00229 } else { 00230 data->temp = (int)u_tmp; 00231 } 00232 00233 data->checksum = buf[0]; 00234 00235 #ifdef DEBUG_DHT22 00236 debug = 0; 00237 #endif 00238 00239 return i; 00240 } 00241
Generated on Tue Jul 26 2022 11:03:49 by 1.7.2