Library for the Measurement Specialties' HTU21D Humidity and Temperature sensor. Code includes device's heater on/off control, serial number access, dew point calculations and RTOS hooks. To date, code tested on GR-PEACH, K64F and KL25Z boards with and w/o RTOS, SDFlash and USB serial Rx interrupts.
htu21d.cpp
00001 /** 00002 HTU21D / HPP828E031 driver for mbed. 00003 - Includes RTOS hooks if RTOS is detected during compile. 00004 Author: Kevin Braun 00005 **/ 00006 00007 #include "htu21d.h" 00008 00009 double theTempIs = 0.0; 00010 double theHumIs = 0.0; 00011 00012 #if not defined HTU21Di2cLOWLEVEL 00013 char htuBuffer[8]; 00014 #endif 00015 00016 //--------------------------------------------------------------------------------------------------------------------------------------// 00017 //Contstructor 00018 00019 htu21d::htu21d(PinName sda, PinName scl) : _i2c(sda, scl) { 00020 _i2c.frequency(400000); 00021 } 00022 00023 htu21d::htu21d(PinName sda, PinName scl, int i2cFrequency) : _i2c(sda, scl) { 00024 _i2c.frequency(i2cFrequency); 00025 } 00026 00027 //--------------------------------------------------------------------------------------------------------------------------------------// 00028 //Destructor 00029 00030 htu21d::~htu21d() { 00031 } 00032 00033 //--------------------------------------------------------------------------------------------------------------------------------------// 00034 //Perform a soft reset on the HTU21D. REturn of 1 = ok, 0 = timeout. 00035 00036 int htu21d::softReset() { 00037 int htu21 = 0; 00038 #if defined HTU21Di2cLOWLEVEL 00039 _i2c.start(); 00040 htu21 = _i2c.write(HTU21Di2cWRITE); //i2c, 1 = ack 00041 if(htu21 == 1) { 00042 _i2c.write(HTU21DRESET); //soft reset, must wait 15mS 00043 _i2c.stop(); 00044 wait_ms(16); //must wait a least 15mS for reset to finish 00045 htu21d::getSNReg(); //go load up the s/n registers 00046 } 00047 return(htu21); 00048 #else 00049 htuBuffer[0] = HTU21DRESET; 00050 htu21 = _i2c.write(HTU21Di2cWRITE, htuBuffer, 1, false); 00051 wait_ms(16); 00052 htu21d::getSNReg(); 00053 return(!(htu21)); 00054 #endif 00055 } 00056 00057 //--------------------------------------------------------------------------------------------------------------------------------------// 00058 //Get the HTU21D user register. Returns 8 bit register. 00059 00060 uint8_t htu21d::getUserReg() { 00061 #if defined HTU21Di2cLOWLEVEL 00062 int htu21 = 0; 00063 uint8_t htu21data = 0; 00064 _i2c.start(); 00065 htu21 = _i2c.write(HTU21Di2cWRITE); //i2c, 1 = ack 00066 if(htu21 == 1) { 00067 _i2c.write(HTU21DREADUSER); 00068 _i2c.start(); 00069 htu21 = _i2c.write(HTU21Di2cREAD); 00070 htu21data = _i2c.read(0); 00071 _i2c.stop(); 00072 } 00073 return(htu21data); 00074 #else 00075 htuBuffer[0] = HTU21DREADUSER; 00076 _i2c.write(HTU21Di2cWRITE, htuBuffer, 1, true); 00077 if(!(_i2c.read(HTU21Di2cREAD, htuBuffer, 1, false))) { 00078 return(htuBuffer[0]); 00079 } else { 00080 return(0); 00081 } 00082 #endif 00083 } 00084 00085 //--------------------------------------------------------------------------------------------------------------------------------------// 00086 //Turn ON the heater the HTU21D user register. 00087 00088 int htu21d::heaterOn() { 00089 uint8_t htu21data = htu21d::getUserReg(); 00090 htu21data |= HTU21DHEATER; 00091 #if defined HTU21Di2cLOWLEVEL 00092 int htu21 = 0; 00093 _i2c.start(); 00094 htu21 = _i2c.write(HTU21Di2cWRITE); //i2c, 1 = ack 00095 if(htu21 == 1) { 00096 _i2c.write(HTU21DWRITEUSER); 00097 htu21 = _i2c.write(htu21data); 00098 _i2c.stop(); 00099 } 00100 return(htu21); 00101 #else 00102 htuBuffer[0] = HTU21DWRITEUSER; 00103 htuBuffer[1] = htu21data; 00104 return(_i2c.write(HTU21Di2cWRITE, htuBuffer, 2, false)); 00105 #endif 00106 } 00107 00108 //--------------------------------------------------------------------------------------------------------------------------------------// 00109 //Turn OFF the heater the HTU21D user register. 00110 00111 int htu21d::heaterOff() { 00112 uint8_t htu21data = htu21d::getUserReg(); 00113 htu21data &= ~HTU21DHEATER; 00114 #if defined HTU21Di2cLOWLEVEL 00115 int htu21 = 0; 00116 _i2c.start(); 00117 htu21 = _i2c.write(HTU21Di2cWRITE); //i2c, 1 = ack 00118 if(htu21 == 1) { 00119 _i2c.write(HTU21DWRITEUSER); 00120 htu21 = _i2c.write(htu21data); 00121 _i2c.stop(); 00122 } 00123 return(htu21); 00124 #else 00125 htuBuffer[0] = HTU21DWRITEUSER; 00126 htuBuffer[1] = htu21data; 00127 return(_i2c.write(HTU21Di2cWRITE, htuBuffer, 2, false)); 00128 #endif 00129 00130 } 00131 00132 //--------------------------------------------------------------------------------------------------------------------------------------// 00133 //Get the status of the heater the HTU21D user register. 0 = off, 4 = on. 00134 00135 uint8_t htu21d::getHeater() { 00136 uint8_t htu21data = htu21d::getUserReg(); 00137 htu21data &= HTU21DHEATER; 00138 return(htu21data); 00139 } 00140 00141 //--------------------------------------------------------------------------------------------------------------------------------------// 00142 //generic routine to get temp or humidity from HTU21D. 00143 //Returns 14 bits of data (anded 0xFFFC) or 0000 if i2c timeout occurs. 00144 //After a read temp or humidity command, HTU21D responds with NACKs until data is ready. 00145 //NOTE: Use non-hold commands 00146 00147 uint16_t htu21d::getData(uint8_t reg) { 00148 int htu21cnt = 0; //number of NACKs before ACK or timeout 00149 #if defined HTU21Di2cLOWLEVEL 00150 uint16_t htu21data = 0; //returned data 00151 int htu21 = 0; //ACK flag 00152 _i2c.start(); 00153 htu21 = _i2c.write(HTU21Di2cWRITE); 00154 _i2c.write(reg); //read temp, no hold 00155 _i2c.stop(); 00156 if(htu21 == 0) return 0; //HTU21T not responding 00157 do { 00158 htu21cnt++; 00159 _i2c.start(); 00160 htu21 = _i2c.write(HTU21Di2cREAD); 00161 if(htu21 == 1) { 00162 htu21data = _i2c.read(1) << 8; 00163 htu21data |= _i2c.read(0) & 0xFC; 00164 _i2c.stop(); 00165 } 00166 wait_us(1000); 00167 } while((htu21cnt < 100) && (htu21 == 0)); //htu21cnt takes 55 to get temp, 16 for humidity (at 1mS loops) 00168 00169 if(htu21 == 0) return 0; //HTU21D ACK response timed out 00170 return(htu21data); //return 14 bit value 00171 #else 00172 htuBuffer[0] = reg; 00173 _i2c.write(HTU21Di2cWRITE, htuBuffer, 1, false); 00174 do { 00175 htu21cnt++; 00176 if(!(_i2c.read(HTU21Di2cREAD, htuBuffer, 2, false))) { 00177 return((htuBuffer[0] << 8) | htuBuffer[1]); 00178 } 00179 wait_us(1000); 00180 } while(htu21cnt < 100); 00181 return 0; 00182 #endif 00183 } 00184 00185 //--------------------------------------------------------------------------------------------------------------------------------------// 00186 //get temperature from HTU21D in degrees C. Returns with 255.0 if HTU21D had timed out. 00187 00188 float htu21d::getTemp() { 00189 uint16_t getData = htu21d::getData(HTU21DtempNOHOLD); 00190 if (getData == 0) return(255.0); //return with error 00191 double tempData = (double)getData / 65536.0; 00192 theTempIs = -46.85 + (175.72 * tempData); 00193 return(theTempIs); 00194 } 00195 00196 //--------------------------------------------------------------------------------------------------------------------------------------// 00197 //get humidity from HTU21D in percentage. Returns with 255.0 if HTU21D had timed out. 00198 00199 float htu21d::getHum() { 00200 uint16_t getData = htu21d::getData(HTU21DhumNOHOLD); 00201 if (getData == 0) return(255.0); //return with error 00202 double tempData = (double)getData / 65536.0; 00203 theHumIs = -6.0 + (125.0 * tempData); 00204 return(theHumIs); 00205 } 00206 00207 //--------------------------------------------------------------------------------------------------------------------------------------// 00208 //Calculate the Dew Point from getTemp and getHum. User must first execute both getTemp and getHum for an accurate result. 00209 //Calculations come from DHT library 00210 /* Copyright (C) Wim De Roeve 00211 * based on DHT22 sensor library by HO WING KIT 00212 * Arduino DHT11 library 00213 */ 00214 00215 float htu21d::getDewPt() { 00216 // dewPoint function NOAA 00217 // reference: http://wahiduddin.net/calc/density_algorithms.htm 00218 double A0= 373.15/(273.15 + (double)theTempIs); 00219 double SUM = -7.90298 * (A0-1); 00220 SUM += 5.02808 * log10(A0); 00221 SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ; 00222 SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ; 00223 SUM += log10(1013.246); 00224 double VP = pow(10, SUM-3) * theHumIs; 00225 double T = log(VP/0.61078); // temp var 00226 return (241.88 * T) / (17.558-T); 00227 } 00228 00229 float htu21d::getDewPtFast() { 00230 // delta max = 0.6544 wrt dewPoint() 00231 // 5x faster than dewPoint() 00232 // reference: http://en.wikipedia.org/wiki/Dew_point 00233 double h21DtzA = 17.271; 00234 double h21DtzB = 237.7; 00235 double h21DtzC = (h21DtzA * theTempIs) / (h21DtzB + theTempIs) + log(theHumIs/100); 00236 double h21DtzD = (h21DtzB * h21DtzC) / (h21DtzA - h21DtzC); 00237 return (h21DtzD); 00238 } 00239 00240 //--------------------------------------------------------------------------------------------------------------------------------------// 00241 //Get the HTU21D serial number registers. Returns 64 bit register. 00242 //should return 0x4854 00xx xxxx 32xx 00243 00244 void htu21d::getSNReg() { 00245 //get 16 bit SNC register, 8 bit SNC-CRC, 16 bit SNA register, 8 bit SNA-CRC 00246 #if defined HTU21Di2cLOWLEVEL 00247 int htu21 = 0; 00248 _i2c.start(); 00249 htu21 = _i2c.write(HTU21Di2cWRITE); //i2c, 1 = ack 00250 if(htu21 == 1) { 00251 _i2c.write(HTU21SNAC1); 00252 _i2c.write(HTU21SNAC2); 00253 _i2c.start(); 00254 htu21 = _i2c.write(HTU21Di2cREAD); 00255 HTU21sn.HTU21D_snc = _i2c.read(1) << 8; 00256 HTU21sn.HTU21D_snc |= _i2c.read(1); 00257 HTU21sn.HTU21D_crcc = _i2c.read(1); 00258 HTU21sn.HTU21D_sna = _i2c.read(1) << 8; 00259 HTU21sn.HTU21D_sna |= _i2c.read(1); 00260 HTU21sn.HTU21D_crca = _i2c.read(0); 00261 _i2c.stop(); 00262 } else { 00263 HTU21sn.HTU21D_snc = HTU21sn.HTU21D_crcc = HTU21sn.HTU21D_sna = HTU21sn.HTU21D_crca = 0; 00264 } 00265 #else 00266 htuBuffer[0] = HTU21SNAC1; 00267 htuBuffer[1] = HTU21SNAC2; 00268 _i2c.write(HTU21Di2cWRITE, htuBuffer, 2, true); 00269 if(!(_i2c.read(HTU21Di2cREAD, htuBuffer, 6, false))) { 00270 HTU21sn.HTU21D_snc = (htuBuffer[0] << 8) | htuBuffer[1]; 00271 HTU21sn.HTU21D_crcc = htuBuffer[2]; 00272 HTU21sn.HTU21D_sna = (htuBuffer[3] << 8) | htuBuffer[4]; 00273 HTU21sn.HTU21D_crca = htuBuffer[5]; 00274 } else { 00275 HTU21sn.HTU21D_snc = HTU21sn.HTU21D_crcc = HTU21sn.HTU21D_sna = HTU21sn.HTU21D_crca = 0; 00276 } 00277 #endif 00278 00279 //get 32 bit SNB register, 32 bit SNB-CRC - regs are intermixed 00280 #if defined HTU21Di2cLOWLEVEL 00281 htu21 = 0; 00282 _i2c.start(); 00283 htu21 = _i2c.write(HTU21Di2cWRITE); //i2c, 1 = ack 00284 if(htu21 == 1) { 00285 _i2c.write(HTU21SNB1); 00286 _i2c.write(HTU21SNB2); 00287 _i2c.start(); 00288 htu21 = _i2c.write(HTU21Di2cREAD); 00289 HTU21sn.HTU21D_snb = _i2c.read(1) << 24; 00290 HTU21sn.HTU21D_crcb = _i2c.read(1) << 24; 00291 HTU21sn.HTU21D_snb |= _i2c.read(1) << 16; 00292 HTU21sn.HTU21D_crcb |= _i2c.read(1) << 16; 00293 HTU21sn.HTU21D_snb |= _i2c.read(1) << 8; 00294 HTU21sn.HTU21D_crcb |= _i2c.read(1) << 8; 00295 HTU21sn.HTU21D_snb |= _i2c.read(1); 00296 HTU21sn.HTU21D_crcb |= _i2c.read(0); 00297 _i2c.stop(); 00298 } else { 00299 HTU21sn.HTU21D_snb = HTU21sn.HTU21D_crcb = 0; 00300 } 00301 #else 00302 htuBuffer[0] = HTU21SNB1; 00303 htuBuffer[1] = HTU21SNB2; 00304 _i2c.write(HTU21Di2cWRITE, htuBuffer, 2, true); 00305 if(!(_i2c.read(HTU21Di2cREAD, htuBuffer, 8, false))) { 00306 HTU21sn.HTU21D_snb = (htuBuffer[0] << 24) | (htuBuffer[2] << 16) | (htuBuffer[4] << 8) | htuBuffer[6]; 00307 HTU21sn.HTU21D_crcb = (htuBuffer[1] << 24) | (htuBuffer[3] << 16) | (htuBuffer[5] << 8) | htuBuffer[7]; 00308 } else { 00309 HTU21sn.HTU21D_snb = HTU21sn.HTU21D_crcb = 0; 00310 } 00311 #endif 00312 } 00313
Generated on Tue Jul 12 2022 18:12:19 by 1.7.2