![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
corrected TH02 sample program
Dependencies: mbed
Fork of TH02_humidity_temp by
Diff: th02.cpp
- Revision:
- 1:8326614f3037
- Parent:
- 0:f1951c6c9187
--- a/th02.cpp Fri Mar 17 10:13:49 2017 +0000 +++ b/th02.cpp Mon Oct 21 09:10:15 2019 +0000 @@ -9,7 +9,7 @@ // http://www.hoperf.com/sensor/app/TH02.htm // // Code based on following datasheet -// http://www.hoperf.com/upload/sensor/TH02_V1.1.pdf +// http://www.hoperf.com/upload/sensor/TH02_V1.1.pdf // // Written by Charles-Henri Hallard (http://hallard.me) // @@ -26,10 +26,12 @@ // Class Constructor TH02::TH02(PinName sda,PinName scl,uint8_t address): m_I2C(sda, scl) -{ - _address = address; // m_I2C Module Address - _last_temp = TH02_UNINITIALIZED_TEMP; // Last measured temperature (for linearization) - _last_rh = TH02_UNINITIALIZED_RH; // Last measured RH +{ + _address = address; // m_I2C Module Address + _last_temp = TH02_UNINITIALIZED_TEMP; // Last measured temperature (for linearization) + _last_rh = TH02_UNINITIALIZED_RH; // Last measured RH +//m_I2C.frequency(10000); //set 10khz i2c frequency + } TH02::~TH02() @@ -41,179 +43,185 @@ /* ====================================================================== Function: writeCommand -Purpose : write the "register address" value on m_I2C bus +Purpose : write the "register address" value on m_I2C bus Input : register address true if we need to release the bus after (default yes) Output : Arduino Wire library return code (0 if ok) -Comments: +Comments: ====================================================================== */ uint8_t TH02::writeCommand(uint8_t command, bool release) - {int iError; - (void) m_I2C.start(); - //Wire.beginTransmission(_address); - iError=m_I2C.write(_address);// send adress of i2c slave - - if (iError==1) - { - // Wire.write(command) ; - iError= m_I2C.write(command); - } - if (release==true) - { m_I2C.stop();// return stop error code - } - if (iError==1) iError=0;// ack received - else iError=1;// no ack - return iError; +{ + int iError; + (void) m_I2C.start(); + //Wire.beginTransmission(_address); + iError=m_I2C.write(_address);// send adress of i2c slave + + if (iError==1) { // ack received +// Wire.write(command) ; + iError= m_I2C.write(command); + + + if (release==true) { + m_I2C.stop();// return stop error code + } + } + + if (iError==1) iError=0;// ack received + else iError=1;// no ack + return iError; } /* ====================================================================== Function: writeRegister -Purpose : write a value on the designed register address on m_I2C bus +Purpose : write a value on the designed register address on m_I2C bus Input : register address value to write Output : Arduino Wire library return code (0 if ok) -Comments: +Comments: ====================================================================== */ uint8_t TH02::writeRegister(uint8_t reg, uint8_t value) -{ int iError; - - bool ret = false; +{ + int iError; + + bool ret = false; + + //Wire.beginTransmission(_address); + (void) m_I2C.start(); + iError=m_I2C.write(_address);// send adress of i2c slave +// Wire.write(reg); + if (iError==1) { - //Wire.beginTransmission(_address); - (void) m_I2C.start(); - iError=m_I2C.write(_address);// send adress of i2c slave - // Wire.write(reg); - if (iError==1){ - - iError= m_I2C.write(reg); - - // Wire.write(value); - (void) m_I2C.write(value); - } - // return Wire.endTransmission(); + iError= m_I2C.write(reg); + +// Wire.write(value); + (void) m_I2C.write(value); + } +// return Wire.endTransmission(); m_I2C.stop();// return stop error code - if (iError==1) iError=0;// ack received - else iError=1;// no ack - return iError; + if (iError==1) iError=0;// ack received + else iError=1;// no ack + wait_ms(1); + return iError; } /* ====================================================================== Function: readRegister -Purpose : read a register address value on m_I2C bus +Purpose : read a register address value on m_I2C bus Input : register address pointer where the return value will be filled Output : Arduino Wire library return code (0 if ok) -Comments: +Comments: ====================================================================== */ uint8_t TH02::readRegister(uint8_t reg, uint8_t * value) { - uint8_t ret ; - int iAck,iRedVal,iError; - // Send a register reading command - // but DO NOT release the m_I2C bus - // (void) m_I2C.start(); - // iError=m_I2C.write(_address);// send adress of i2c slave - - //if (iError==1) - - ret = writeCommand(reg, false); + uint8_t ret ; + int iAck,iRedVal,iError; + // Send a register reading command + // but DO NOT release the m_I2C bus +// (void) m_I2C.start(); + //iError=m_I2C.write(_address);// send adress of i2c slave + + //if (iError==1) // ack received + //{ + ret = writeCommand(reg, false);// no stop - if ( ret == 0) //if command ok - { - // Wire.requestFrom( (uint8_t) _address, (uint8_t) 1); - (void) m_I2C.start(); - iError=m_I2C.write(_address+0x01);// send adress of i2c slave in read mode -iRedVal=m_I2C.read(0);//send non ack - // if (Wire.available() != 1) - /*if (iAck != 1) - - // Other error as Wire library - ret = 4; - else - // grab the value*/ - *value = iRedVal; // return Red value by ref - - //} - - // Ok now we have finished - // Wire.endTransmission(); - - } - (void) m_I2C.stop();// return stop error code - return ret; -} + if ( ret == 0) { //if command ok + // Wire.requestFrom( (uint8_t) _address, (uint8_t) 1); + (void) m_I2C.start(); + iError=m_I2C.write(_address+0x01);// send adress of i2c slave in read mode + *value =m_I2C.read(0);//send non ack + // if (Wire.available() != 1) + /*if (iAck != 1) + + // Other error as Wire library + ret = 4; + else + // grab the value*/ + // *value = iRedVal; // return Red value by ref + + //} + + // Ok now we have finished +// Wire.endTransmission(); + + } + (void) m_I2C.stop();// return stop error code + wait_ms(1); + return ret; +} /* ====================================================================== Function: getId -Purpose : Get device ID register +Purpose : Get device ID register Input : pointer where the return value will be filled Output : Arduino Wire library return code (0 if ok) Comments: - ====================================================================== */ uint8_t TH02::getId(uint8_t * pvalue) { - return (readRegister(TH02_ID, pvalue)); + return (readRegister(TH02_ID, pvalue)); } /* ====================================================================== Function: getStatus -Purpose : Get device status register +Purpose : Get device status register Input : pointer where the return value will be filled Output : Arduino Wire library return code (0 if ok) -Comments: +Comments: ====================================================================== */ uint8_t TH02::getStatus(uint8_t * pvalue) { - return (readRegister(TH02_STATUS, pvalue)); + return (readRegister(TH02_STATUS, pvalue)); } /* ====================================================================== Function: isConverting -Purpose : Indicate if a temperature or humidity conversion is in progress +Purpose : Indicate if a temperature or humidity conversion is in progress Input : - Output : true if conversion in progress false otherwise -Comments: +Comments: ====================================================================== */ bool TH02::isConverting(void) { - uint8_t status; - // Get status and check RDY bit - if ( getStatus(&status) == 0) - - { printf("\n lecture status %x",status); - if ( (status & TH02_STATUS_RDY) ==1 ) - return true; -} - return false; + uint8_t status; + // Get status and check RDY bit + if ( getStatus(&status) == 0) + + { + // printf("\n lecture status %x",status); + if ( (status & TH02_STATUS_RDY) ==1 ) + return true; + } + return false; } /* ====================================================================== Function: getConfig -Purpose : Get device configuration register +Purpose : Get device configuration register Input : pointer where the return value will be filled Output : Arduino Wire library return code (0 if ok) -Comments: +Comments: ====================================================================== */ uint8_t TH02::getConfig(uint8_t * pvalue) { - return (readRegister(TH02_CONFIG, pvalue)); + return (readRegister(TH02_CONFIG, pvalue)); } /* ====================================================================== Function: setConfig -Purpose : Set device configuration register +Purpose : Set device configuration register Input : value to set Output : true if succeded, false otherwise -Comments: +Comments: ====================================================================== */ uint8_t TH02::setConfig(uint8_t config) { - return (writeRegister(TH02_CONFIG, config)); + return (writeRegister(TH02_CONFIG, config)); } /* ====================================================================== Function: startTempConv -Purpose : Start a temperature conversion +Purpose : Start a temperature conversion Input : - fastmode true to enable fast conversion - heater true to enable heater Output : true if succeded, false otherwise @@ -221,20 +229,20 @@ ====================================================================== */ uint8_t TH02::startTempConv(bool fastmode, bool heater) { - // init configuration register to start and temperature - uint8_t config = TH02_CONFIG_START | TH02_CONFIG_TEMP; - - // set fast mode and heater if asked - if (fastmode) config |= TH02_CONFIG_FAST; - if (heater) config |= TH02_CONFIG_HEAT; - - // write to configuration register - return ( setConfig( config ) ); + // init configuration register to start and temperature + uint8_t config = TH02_CONFIG_START | TH02_CONFIG_TEMP; + + // set fast mode and heater if asked + if (fastmode) config |= TH02_CONFIG_FAST; + if (heater) config |= TH02_CONFIG_HEAT; + + // write to configuration register + return ( setConfig( config ) ); } /* ====================================================================== Function: startRHConv -Purpose : Start a relative humidity conversion +Purpose : Start a relative humidity conversion Input : - fastmode true to enable fast conversion - heater true to enable heater Output : true if succeded, false otherwise @@ -242,64 +250,63 @@ ====================================================================== */ uint8_t TH02::startRHConv(bool fastmode, bool heater) { - // init configuration register to start and no temperature (so RH) - uint8_t config = TH02_CONFIG_START; - - // set fast mode and heater if asked - if (fastmode) config |= TH02_CONFIG_FAST; - if (heater) config |= TH02_CONFIG_HEAT; - - // write to configuration register - return ( setConfig( config ) ); + // init configuration register to start and no temperature (so RH) + uint8_t config = TH02_CONFIG_START; + + // set fast mode and heater if asked + if (fastmode) config |= TH02_CONFIG_FAST; + if (heater) config |= TH02_CONFIG_HEAT; + + // write to configuration register + return ( setConfig( config ) ); } /* ====================================================================== Function: waitEndConversion -Purpose : wait for a temperature or RH conversion is done -Input : -Output : delay in ms the process took. +Purpose : wait for a temperature or RH conversion is done +Input : +Output : delay in ms the process took. Comments: if return >= TH02_CONVERSION_TIME_OUT, time out occured ====================================================================== */ uint8_t TH02::waitEndConversion(void) { - // okay this is basic approach not so accurate - // but avoid using long and millis() - uint8_t time_out = 0; - - // loop until conversion done or duration >= time out - while (isConverting() && time_out <= TH02_CONVERSION_TIME_OUT ) - { - ++time_out; - wait_ms(1); - } - - // return approx time of conversion - return (time_out); + // okay this is basic approach not so accurate + // but avoid using long and millis() + uint8_t time_out = 0; + + // loop until conversion done or duration >= time out + while (isConverting() && (time_out <= TH02_CONVERSION_TIME_OUT) ) { + ++time_out; + wait_ms(2); + } + + // return approx time of conversion + return (time_out); } /* ====================================================================== Function: roundInt -Purpose : round a float value to int +Purpose : round a float value to int Input : float value -Output : int value rounded -Comments: +Output : int value rounded +Comments: ====================================================================== */ int16_t TH02::roundInt(float value) -{ +{ - // check positive number and do round - if (value >= 0.0f) - value = floor(value + 0.5f); - else - value = ceil(value - 0.5f); - - // return int value - return (static_cast<int16_t>(value)); + // check positive number and do round + if (value >= 0.0f) + value = floor(value + 0.5f); + else + value = ceil(value - 0.5f); + + // return int value + return (static_cast<int16_t>(value)); } /* to avoid math library may I need to test something like that -float TH02::showDecimals(float x, int numDecimals) +float TH02::showDecimals(float x, int numDecimals) { int y=x; double z=x-y; @@ -310,9 +317,10 @@ } */ + /* ====================================================================== Function: getConversionValue -Purpose : return the last converted value to int * 10 to have 1 digit prec. +Purpose : return the last converted value to int * 10 to have 1 digit prec. Input : float value Output : value rounded but multiplied per 10 or TH02_UNDEFINED_VALUE on err Comments: - temperature and rh raw values (*100) are stored for raw purpose @@ -320,157 +328,152 @@ a temperature or humidity conversion ====================================================================== */ int16_t TH02::getConversionValue(void) -{ char cMaChaine[3]; -int iError; - int32_t result=0 ; - uint8_t config; - int16_t ret = TH02_UNDEFINED_VALUE; - - // Prepare reading address of ADC data result - if ( writeCommand(TH02_DATAh, false) == 0 ) - { +{ + char cMaChaine[4]; + int iError; + int32_t result=0 ; + uint8_t config; + int16_t ret = TH02_UNDEFINED_VALUE; + + // Prepare reading address of ADC data result + /*if ( writeCommand(TH02_DATAh, false) == 0 ) // no stop + {*/ // Read 2 bytes adc data result MSB and LSB from TH02 //Wire.requestFrom( (uint8_t) _address, (uint8_t) 2); - - -iError= m_I2C.read (_address,cMaChaine,2,false); + writeCommand(TH02_DATAh, false); - + // read of two register + (void) m_I2C.start(); + iError=m_I2C.write(_address+1);// send adress of i2c slave read mode + if (iError==1) { + cMaChaine[0]= m_I2C.read(1);// read first byte with ack + cMaChaine[1]=m_I2C.read(0);// read first byte without ack + + m_I2C.stop();// rperform stop + - // we got 2 bytes ? - // if (Wire.available() == 2) - if (iError == 0 ) - { - // convert number - // result = Wire.read() << 8; - // result |= Wire.read(); -result=(cMaChaine[0]<<8 )|cMaChaine[1]; - // Get configuration to know what was asked last time - if (getConfig(&config)==0) - { - // last conversion was temperature ? - if( config & TH02_CONFIG_TEMP) - { - result >>= 2; // remove 2 unused LSB bits - result *= 100; // multiply per 100 to have int value with 2 decimal - result /= 32; // now apply datasheet formula - if(result >= 5000) - { - result -= 5000; - } - else - { - result -= 5000; - result = -result; - } - - // now result contain temperature * 100 - // so 2134 is 21.34 C - - // Save raw value - _last_temp = result; + //iError= m_I2C.read (_address,cMaChaine,4,false);// send stop at end + // printf (" \n\r lecture I2C: %02x %02x",cMaChaine[0],cMaChaine[1]); + //} + result=(cMaChaine[0]<<8 )|cMaChaine[1]; + // Get configuration to know what was asked last time + + if (getConfig(&config)==0) { + // last conversion was temperature ? + if( config & TH02_CONFIG_TEMP) { + result >>= 2; // remove 2 unused LSB bits + result *= 100; // multiply per 100 to have int value with 2 decimal + result /= 32; // now apply datasheet formula + if(result >= 5000) { + result -= 5000; + } else { + result -= 5000; + result = -result; + } + + // now result contain temperature * 100 + // so 2134 is 21.34 C + + // Save raw value + _last_temp = result; + } + // it was RH conversion + else { + result >>= 4; // remove 4 unused LSB bits + result *= 100; // multiply per 100 to have int value with 2 decimal + result /= 16; // now apply datasheet formula + result -= 2400; + + // now result contain humidity * 100 + // so 4567 is 45.67 % RH + _last_rh = result; + } + + // remember result value is multiplied by 10 to avoid float calculation later + // so humidity of 45.6% is 456 and temp of 21.3 C is 213 + ret = roundInt(result/10.0f); } - // it was RH conversion - else - { - result >>= 4; // remove 4 unused LSB bits - result *= 100; // multiply per 100 to have int value with 2 decimal - result /= 16; // now apply datasheet formula - result -= 2400; - - // now result contain humidity * 100 - // so 4567 is 45.67 % RH - _last_rh = result; - } + } + + else{ + + m_I2C.stop();// rperform stop + } + return ret; +} - // remember result value is multiplied by 10 to avoid float calculation later - // so humidity of 45.6% is 456 and temp of 21.3 C is 213 - ret = roundInt(result/10.0f); - } - } // if got 2 bytes from m_I2C + - // Ok now we have finished with m_I2C, release - //Wire.endTransmission(); - - } // if write command TH02_DATAh -(void) m_I2C.stop(); - return ret; -} /* ====================================================================== Function: getConpensatedRH -Purpose : return the compensated calulated humidity +Purpose : return the compensated calulated humidity Input : true if we want to round value to 1 digit precision, else 2 Output : the compensed RH value (rounded or not) -Comments: +Comments: ====================================================================== */ int16_t TH02::getConpensatedRH(bool round) { - float rhvalue ; - float rhlinear ; - int16_t ret = TH02_UNDEFINED_VALUE; + float rhvalue ; + float rhlinear ; + int16_t ret = TH02_UNDEFINED_VALUE; - // did we had a previous measure RH - if (_last_rh != TH02_UNINITIALIZED_RH) - { - // now we're float restore real value RH value - rhvalue = (float) _last_rh / 100.0 ; - - // apply linear compensation - rhlinear = rhvalue - ((rhvalue*rhvalue) * TH02_A2 + rhvalue * TH02_A1 + TH02_A0); + // did we had a previous measure RH + if (_last_rh != TH02_UNINITIALIZED_RH) { + // now we're float restore real value RH value + rhvalue = (float) _last_rh / 100.0 ; + + // apply linear compensation + rhlinear = rhvalue - ((rhvalue*rhvalue) * TH02_A2 + rhvalue * TH02_A1 + TH02_A0); + + // correct value + rhvalue = rhlinear; - // correct value - rhvalue = rhlinear; - - // do we have a initialized temperature value ? - if (_last_temp != TH02_UNINITIALIZED_TEMP ) - { - // Apply Temperature compensation - // remember last temp was stored * 100 - rhvalue += ((_last_temp/100.0) - 30.0) * (rhlinear * TH02_Q1 + TH02_Q0); + // do we have a initialized temperature value ? + if (_last_temp != TH02_UNINITIALIZED_TEMP ) { + // Apply Temperature compensation + // remember last temp was stored * 100 + rhvalue += ((_last_temp/100.0) - 30.0) * (rhlinear * TH02_Q1 + TH02_Q0); + } + + // now get back * 100 to have int with 2 digit precision + rhvalue *= 100; + + // do we need to round to 1 digit ? + if (round) { + // remember result value is multiplied by 10 to avoid float calculation later + // so humidity of 45.6% is 456 + ret = roundInt(rhvalue/10.0f); + } else { + ret = (int16_t) rhvalue; + } } - - // now get back * 100 to have int with 2 digit precision - rhvalue *= 100; - - // do we need to round to 1 digit ? - if (round) - { - // remember result value is multiplied by 10 to avoid float calculation later - // so humidity of 45.6% is 456 - ret = roundInt(rhvalue/10.0f); - } - else - { - ret = (int16_t) rhvalue; - } - } - - return ret; + + return ret; } /* ====================================================================== Function: getLastRawRH -Purpose : return the raw humidity * 100 -Input : +Purpose : return the raw humidity * 100 +Input : Output : int value (ie 4123 for 41.23%) -Comments: +Comments: ====================================================================== */ int32_t TH02::getLastRawRH(void) { - return _last_rh; + return _last_rh; } /* ====================================================================== Function: getLastRawTemp -Purpose : return the raw temperature value * 100 -Input : +Purpose : return the raw temperature value * 100 +Input : Output : int value (ie 2124 for 21.24 C) -Comments: +Comments: ====================================================================== */ -int32_t TH02::getLastRawTemp(void) +int32_t TH02::getLastRawTemp(void) { - return _last_temp; + return _last_temp; }