Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of TH02_humidity_temp by
th02.cpp
00001 // ********************************************************************************** 00002 // Driver definition for HopeRF TH02 temperature and humidity sensor 00003 // ********************************************************************************** 00004 // Creative Commons Attrib Share-Alike License 00005 // You are free to use/extend this library but please abide with the CC-BY-SA license: 00006 // http://creativecommons.org/licenses/by-sa/4.0/ 00007 // 00008 // For any explanation see TH02 sensor information at 00009 // http://www.hoperf.com/sensor/app/TH02.htm 00010 // 00011 // Code based on following datasheet 00012 // http://www.hoperf.com/upload/sensor/TH02_V1.1.pdf 00013 // 00014 // Written by Charles-Henri Hallard (http://hallard.me) 00015 // 00016 // History : V1.00 2014-07-14 - First release 00017 // V1.10 2015-04-13 - changed to Wire library instead of m_I2C 00018 // 00019 // All text above must be included in any redistribution. 00020 // 00021 // ********************************************************************************** 00022 #include "th02.h" 00023 #include "mbed.h" 00024 #include "math.h" 00025 00026 // Class Constructor 00027 00028 TH02::TH02(PinName sda,PinName scl,uint8_t address): m_I2C(sda, scl) 00029 { 00030 _address = address; // m_I2C Module Address 00031 _last_temp = TH02_UNINITIALIZED_TEMP; // Last measured temperature (for linearization) 00032 _last_rh = TH02_UNINITIALIZED_RH; // Last measured RH 00033 //m_I2C.frequency(10000); //set 10khz i2c frequency 00034 00035 } 00036 00037 TH02::~TH02() 00038 { 00039 00040 } 00041 00042 00043 00044 /* ====================================================================== 00045 Function: writeCommand 00046 Purpose : write the "register address" value on m_I2C bus 00047 Input : register address 00048 true if we need to release the bus after (default yes) 00049 Output : Arduino Wire library return code (0 if ok) 00050 Comments: 00051 ====================================================================== */ 00052 uint8_t TH02::writeCommand(uint8_t command, bool release) 00053 { 00054 int iError; 00055 (void) m_I2C.start(); 00056 //Wire.beginTransmission(_address); 00057 iError=m_I2C.write(_address);// send adress of i2c slave 00058 00059 if (iError==1) { // ack received 00060 // Wire.write(command) ; 00061 iError= m_I2C.write(command); 00062 00063 00064 if (release==true) { 00065 m_I2C.stop();// return stop error code 00066 } 00067 } 00068 00069 if (iError==1) iError=0;// ack received 00070 else iError=1;// no ack 00071 return iError; 00072 } 00073 00074 /* ====================================================================== 00075 Function: writeRegister 00076 Purpose : write a value on the designed register address on m_I2C bus 00077 Input : register address 00078 value to write 00079 Output : Arduino Wire library return code (0 if ok) 00080 Comments: 00081 ====================================================================== */ 00082 uint8_t TH02::writeRegister(uint8_t reg, uint8_t value) 00083 { 00084 int iError; 00085 00086 bool ret = false; 00087 00088 //Wire.beginTransmission(_address); 00089 (void) m_I2C.start(); 00090 iError=m_I2C.write(_address);// send adress of i2c slave 00091 // Wire.write(reg); 00092 if (iError==1) { 00093 00094 iError= m_I2C.write(reg); 00095 00096 // Wire.write(value); 00097 (void) m_I2C.write(value); 00098 } 00099 // return Wire.endTransmission(); 00100 m_I2C.stop();// return stop error code 00101 if (iError==1) iError=0;// ack received 00102 else iError=1;// no ack 00103 wait_ms(1); 00104 return iError; 00105 } 00106 00107 /* ====================================================================== 00108 Function: readRegister 00109 Purpose : read a register address value on m_I2C bus 00110 Input : register address 00111 pointer where the return value will be filled 00112 Output : Arduino Wire library return code (0 if ok) 00113 Comments: 00114 ====================================================================== */ 00115 uint8_t TH02::readRegister(uint8_t reg, uint8_t * value) 00116 { 00117 uint8_t ret ; 00118 int iAck,iRedVal,iError; 00119 // Send a register reading command 00120 // but DO NOT release the m_I2C bus 00121 // (void) m_I2C.start(); 00122 //iError=m_I2C.write(_address);// send adress of i2c slave 00123 00124 //if (iError==1) // ack received 00125 //{ 00126 ret = writeCommand(reg, false);// no stop 00127 00128 if ( ret == 0) { //if command ok 00129 // Wire.requestFrom( (uint8_t) _address, (uint8_t) 1); 00130 (void) m_I2C.start(); 00131 iError=m_I2C.write(_address+0x01);// send adress of i2c slave in read mode 00132 *value =m_I2C.read(0);//send non ack 00133 // if (Wire.available() != 1) 00134 /*if (iAck != 1) 00135 00136 // Other error as Wire library 00137 ret = 4; 00138 else 00139 // grab the value*/ 00140 // *value = iRedVal; // return Red value by ref 00141 00142 //} 00143 00144 // Ok now we have finished 00145 // Wire.endTransmission(); 00146 00147 } 00148 (void) m_I2C.stop();// return stop error code 00149 wait_ms(1); 00150 return ret; 00151 } 00152 00153 /* ====================================================================== 00154 Function: getId 00155 Purpose : Get device ID register 00156 Input : pointer where the return value will be filled 00157 Output : Arduino Wire library return code (0 if ok) 00158 Comments: - 00159 ====================================================================== */ 00160 uint8_t TH02::getId(uint8_t * pvalue) 00161 { 00162 return (readRegister(TH02_ID, pvalue)); 00163 } 00164 00165 /* ====================================================================== 00166 Function: getStatus 00167 Purpose : Get device status register 00168 Input : pointer where the return value will be filled 00169 Output : Arduino Wire library return code (0 if ok) 00170 Comments: 00171 ====================================================================== */ 00172 uint8_t TH02::getStatus(uint8_t * pvalue) 00173 { 00174 return (readRegister(TH02_STATUS, pvalue)); 00175 } 00176 00177 /* ====================================================================== 00178 Function: isConverting 00179 Purpose : Indicate if a temperature or humidity conversion is in progress 00180 Input : - 00181 Output : true if conversion in progress false otherwise 00182 Comments: 00183 ====================================================================== */ 00184 bool TH02::isConverting(void) 00185 { 00186 uint8_t status; 00187 // Get status and check RDY bit 00188 if ( getStatus(&status) == 0) 00189 00190 { 00191 // printf("\n lecture status %x",status); 00192 if ( (status & TH02_STATUS_RDY) ==1 ) 00193 return true; 00194 } 00195 return false; 00196 } 00197 00198 /* ====================================================================== 00199 Function: getConfig 00200 Purpose : Get device configuration register 00201 Input : pointer where the return value will be filled 00202 Output : Arduino Wire library return code (0 if ok) 00203 Comments: 00204 ====================================================================== */ 00205 uint8_t TH02::getConfig(uint8_t * pvalue) 00206 { 00207 return (readRegister(TH02_CONFIG, pvalue)); 00208 } 00209 00210 /* ====================================================================== 00211 Function: setConfig 00212 Purpose : Set device configuration register 00213 Input : value to set 00214 Output : true if succeded, false otherwise 00215 Comments: 00216 ====================================================================== */ 00217 uint8_t TH02::setConfig(uint8_t config) 00218 { 00219 return (writeRegister(TH02_CONFIG, config)); 00220 } 00221 00222 /* ====================================================================== 00223 Function: startTempConv 00224 Purpose : Start a temperature conversion 00225 Input : - fastmode true to enable fast conversion 00226 - heater true to enable heater 00227 Output : true if succeded, false otherwise 00228 Comments: if heater enabled, it will not be auto disabled 00229 ====================================================================== */ 00230 uint8_t TH02::startTempConv(bool fastmode, bool heater) 00231 { 00232 // init configuration register to start and temperature 00233 uint8_t config = TH02_CONFIG_START | TH02_CONFIG_TEMP; 00234 00235 // set fast mode and heater if asked 00236 if (fastmode) config |= TH02_CONFIG_FAST; 00237 if (heater) config |= TH02_CONFIG_HEAT; 00238 00239 // write to configuration register 00240 return ( setConfig( config ) ); 00241 } 00242 00243 /* ====================================================================== 00244 Function: startRHConv 00245 Purpose : Start a relative humidity conversion 00246 Input : - fastmode true to enable fast conversion 00247 - heater true to enable heater 00248 Output : true if succeded, false otherwise 00249 Comments: if heater enabled, it will not be auto disabled 00250 ====================================================================== */ 00251 uint8_t TH02::startRHConv(bool fastmode, bool heater) 00252 { 00253 // init configuration register to start and no temperature (so RH) 00254 uint8_t config = TH02_CONFIG_START; 00255 00256 // set fast mode and heater if asked 00257 if (fastmode) config |= TH02_CONFIG_FAST; 00258 if (heater) config |= TH02_CONFIG_HEAT; 00259 00260 // write to configuration register 00261 return ( setConfig( config ) ); 00262 } 00263 00264 /* ====================================================================== 00265 Function: waitEndConversion 00266 Purpose : wait for a temperature or RH conversion is done 00267 Input : 00268 Output : delay in ms the process took. 00269 Comments: if return >= TH02_CONVERSION_TIME_OUT, time out occured 00270 ====================================================================== */ 00271 uint8_t TH02::waitEndConversion(void) 00272 { 00273 // okay this is basic approach not so accurate 00274 // but avoid using long and millis() 00275 uint8_t time_out = 0; 00276 00277 // loop until conversion done or duration >= time out 00278 while (isConverting() && (time_out <= TH02_CONVERSION_TIME_OUT) ) { 00279 ++time_out; 00280 wait_ms(2); 00281 } 00282 00283 // return approx time of conversion 00284 return (time_out); 00285 } 00286 00287 /* ====================================================================== 00288 Function: roundInt 00289 Purpose : round a float value to int 00290 Input : float value 00291 Output : int value rounded 00292 Comments: 00293 ====================================================================== */ 00294 int16_t TH02::roundInt(float value) 00295 { 00296 00297 // check positive number and do round 00298 if (value >= 0.0f) 00299 value = floor(value + 0.5f); 00300 else 00301 value = ceil(value - 0.5f); 00302 00303 // return int value 00304 return (static_cast<int16_t>(value)); 00305 } 00306 00307 /* to avoid math library may I need to test something 00308 like that 00309 float TH02::showDecimals(float x, int numDecimals) 00310 { 00311 int y=x; 00312 double z=x-y; 00313 double m=pow(10,numDecimals); 00314 double q=z*m; 00315 double r=round(q); 00316 return static_cast<double>(y)+(1.0/m)*r; 00317 } 00318 */ 00319 00320 00321 /* ====================================================================== 00322 Function: getConversionValue 00323 Purpose : return the last converted value to int * 10 to have 1 digit prec. 00324 Input : float value 00325 Output : value rounded but multiplied per 10 or TH02_UNDEFINED_VALUE on err 00326 Comments: - temperature and rh raw values (*100) are stored for raw purpose 00327 - the configuration register is checked to see if last conv was 00328 a temperature or humidity conversion 00329 ====================================================================== */ 00330 int16_t TH02::getConversionValue(void) 00331 { 00332 char cMaChaine[4]; 00333 int iError; 00334 int32_t result=0 ; 00335 uint8_t config; 00336 int16_t ret = TH02_UNDEFINED_VALUE; 00337 00338 // Prepare reading address of ADC data result 00339 /*if ( writeCommand(TH02_DATAh, false) == 0 ) // no stop 00340 {*/ 00341 // Read 2 bytes adc data result MSB and LSB from TH02 00342 //Wire.requestFrom( (uint8_t) _address, (uint8_t) 2); 00343 writeCommand(TH02_DATAh, false); 00344 00345 // read of two register 00346 (void) m_I2C.start(); 00347 iError=m_I2C.write(_address+1);// send adress of i2c slave read mode 00348 if (iError==1) { 00349 cMaChaine[0]= m_I2C.read(1);// read first byte with ack 00350 cMaChaine[1]=m_I2C.read(0);// read first byte without ack 00351 00352 m_I2C.stop();// rperform stop 00353 00354 00355 00356 //iError= m_I2C.read (_address,cMaChaine,4,false);// send stop at end 00357 // printf (" \n\r lecture I2C: %02x %02x",cMaChaine[0],cMaChaine[1]); 00358 //} 00359 result=(cMaChaine[0]<<8 )|cMaChaine[1]; 00360 // Get configuration to know what was asked last time 00361 00362 if (getConfig(&config)==0) { 00363 // last conversion was temperature ? 00364 if( config & TH02_CONFIG_TEMP) { 00365 result >>= 2; // remove 2 unused LSB bits 00366 result *= 100; // multiply per 100 to have int value with 2 decimal 00367 result /= 32; // now apply datasheet formula 00368 if(result >= 5000) { 00369 result -= 5000; 00370 } else { 00371 result -= 5000; 00372 result = -result; 00373 } 00374 00375 // now result contain temperature * 100 00376 // so 2134 is 21.34 C 00377 00378 // Save raw value 00379 _last_temp = result; 00380 } 00381 // it was RH conversion 00382 else { 00383 result >>= 4; // remove 4 unused LSB bits 00384 result *= 100; // multiply per 100 to have int value with 2 decimal 00385 result /= 16; // now apply datasheet formula 00386 result -= 2400; 00387 00388 // now result contain humidity * 100 00389 // so 4567 is 45.67 % RH 00390 _last_rh = result; 00391 } 00392 00393 // remember result value is multiplied by 10 to avoid float calculation later 00394 // so humidity of 45.6% is 456 and temp of 21.3 C is 213 00395 ret = roundInt(result/10.0f); 00396 } 00397 } 00398 00399 else{ 00400 00401 m_I2C.stop();// rperform stop 00402 } 00403 return ret; 00404 } 00405 00406 00407 00408 00409 00410 /* ====================================================================== 00411 Function: getConpensatedRH 00412 Purpose : return the compensated calulated humidity 00413 Input : true if we want to round value to 1 digit precision, else 2 00414 Output : the compensed RH value (rounded or not) 00415 Comments: 00416 ====================================================================== */ 00417 int16_t TH02::getConpensatedRH(bool round) 00418 { 00419 float rhvalue ; 00420 float rhlinear ; 00421 int16_t ret = TH02_UNDEFINED_VALUE; 00422 00423 // did we had a previous measure RH 00424 if (_last_rh != TH02_UNINITIALIZED_RH) { 00425 // now we're float restore real value RH value 00426 rhvalue = (float) _last_rh / 100.0 ; 00427 00428 // apply linear compensation 00429 rhlinear = rhvalue - ((rhvalue*rhvalue) * TH02_A2 + rhvalue * TH02_A1 + TH02_A0); 00430 00431 // correct value 00432 rhvalue = rhlinear; 00433 00434 // do we have a initialized temperature value ? 00435 if (_last_temp != TH02_UNINITIALIZED_TEMP ) { 00436 // Apply Temperature compensation 00437 // remember last temp was stored * 100 00438 rhvalue += ((_last_temp/100.0) - 30.0) * (rhlinear * TH02_Q1 + TH02_Q0); 00439 } 00440 00441 // now get back * 100 to have int with 2 digit precision 00442 rhvalue *= 100; 00443 00444 // do we need to round to 1 digit ? 00445 if (round) { 00446 // remember result value is multiplied by 10 to avoid float calculation later 00447 // so humidity of 45.6% is 456 00448 ret = roundInt(rhvalue/10.0f); 00449 } else { 00450 ret = (int16_t) rhvalue; 00451 } 00452 } 00453 00454 return ret; 00455 } 00456 00457 /* ====================================================================== 00458 Function: getLastRawRH 00459 Purpose : return the raw humidity * 100 00460 Input : 00461 Output : int value (ie 4123 for 41.23%) 00462 Comments: 00463 ====================================================================== */ 00464 int32_t TH02::getLastRawRH(void) 00465 { 00466 return _last_rh; 00467 } 00468 00469 /* ====================================================================== 00470 Function: getLastRawTemp 00471 Purpose : return the raw temperature value * 100 00472 Input : 00473 Output : int value (ie 2124 for 21.24 C) 00474 Comments: 00475 ====================================================================== */ 00476 int32_t TH02::getLastRawTemp(void) 00477 { 00478 return _last_temp; 00479 }
Generated on Sat Jul 16 2022 23:02:48 by
