philippe laurent
/
TH02_humidity_temp
corrected TH02 sample program
Revision 0:f1951c6c9187, committed 2017-03-17
- Comitter:
- superphil06
- Date:
- Fri Mar 17 10:13:49 2017 +0000
- Commit message:
- TH02_sample_program
Changed in this revision
diff -r 000000000000 -r f1951c6c9187 .hg_archival.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hg_archival.txt Fri Mar 17 10:13:49 2017 +0000 @@ -0,0 +1,5 @@ +repo: be9eabdeb9adf48cf15c1b93c9fd876fef657389 +node: 6e55b3b06458b51257b897bdbc17440831c79ef0 +branch: default +latesttag: null +latesttagdistance: 5
diff -r 000000000000 -r f1951c6c9187 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Mar 17 10:13:49 2017 +0000 @@ -0,0 +1,41 @@ +#include "mbed.h" +#include "th02.h" + + + +DigitalOut myled(LED1); + + +TH02 MyTH02 (p28,p27,TH02_I2C_ADDR<<1);// connect hsensor on RX2 TX2 + + +int main() { + int iTemp,iTime,iTempbrute,iRH,iRHbrute; + printf ("\n start reading TH02"); + //MyTH02.startTempConv(true,true); + + + + while(1) { + MyTH02.startTempConv(true,true); + iTime= MyTH02.waitEndConversion();// wait until onversion is done + printf ("\n time=%d",iTime); + iTempbrute= MyTH02.getConversionValue(); + iTemp=MyTH02.getLastRawTemp(); + printf ("\n temp value=%d %d",iTemp,iTempbrute ); + + MyTH02.startRHConv(true,true); + iTime= MyTH02.waitEndConversion();// wait until onversion is done + printf ("\n time=%d",iTime); + iRHbrute= MyTH02.getConversionValue(); + iRH=MyTH02.getLastRawRH(); + printf ("\n RH value=%d %d",iRH,iRHbrute ); + + + wait_ms(1000); + + + + + } +}
diff -r 000000000000 -r f1951c6c9187 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Mar 17 10:13:49 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e1686b8d5b90 \ No newline at end of file
diff -r 000000000000 -r f1951c6c9187 th02.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th02.cpp Fri Mar 17 10:13:49 2017 +0000 @@ -0,0 +1,476 @@ +// ********************************************************************************** +// Driver definition for HopeRF TH02 temperature and humidity sensor +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// http://creativecommons.org/licenses/by-sa/4.0/ +// +// For any explanation see TH02 sensor information at +// http://www.hoperf.com/sensor/app/TH02.htm +// +// Code based on following datasheet +// http://www.hoperf.com/upload/sensor/TH02_V1.1.pdf +// +// Written by Charles-Henri Hallard (http://hallard.me) +// +// History : V1.00 2014-07-14 - First release +// V1.10 2015-04-13 - changed to Wire library instead of m_I2C +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** +#include "th02.h" +#include "mbed.h" +#include "math.h" + +// 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 +} + +TH02::~TH02() +{ + +} + + + +/* ====================================================================== +Function: writeCommand +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: +====================================================================== */ +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; +} + +/* ====================================================================== +Function: writeRegister +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: +====================================================================== */ +uint8_t TH02::writeRegister(uint8_t reg, uint8_t value) +{ 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){ + + 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; +} + +/* ====================================================================== +Function: readRegister +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: +====================================================================== */ +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); + + 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; +} + +/* ====================================================================== +Function: getId +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)); +} + +/* ====================================================================== +Function: getStatus +Purpose : Get device status register +Input : pointer where the return value will be filled +Output : Arduino Wire library return code (0 if ok) +Comments: +====================================================================== */ +uint8_t TH02::getStatus(uint8_t * pvalue) +{ + return (readRegister(TH02_STATUS, pvalue)); +} + +/* ====================================================================== +Function: isConverting +Purpose : Indicate if a temperature or humidity conversion is in progress +Input : - +Output : true if conversion in progress false otherwise +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; +} + +/* ====================================================================== +Function: getConfig +Purpose : Get device configuration register +Input : pointer where the return value will be filled +Output : Arduino Wire library return code (0 if ok) +Comments: +====================================================================== */ +uint8_t TH02::getConfig(uint8_t * pvalue) +{ + return (readRegister(TH02_CONFIG, pvalue)); +} + +/* ====================================================================== +Function: setConfig +Purpose : Set device configuration register +Input : value to set +Output : true if succeded, false otherwise +Comments: +====================================================================== */ +uint8_t TH02::setConfig(uint8_t config) +{ + return (writeRegister(TH02_CONFIG, config)); +} + +/* ====================================================================== +Function: startTempConv +Purpose : Start a temperature conversion +Input : - fastmode true to enable fast conversion + - heater true to enable heater +Output : true if succeded, false otherwise +Comments: if heater enabled, it will not be auto disabled +====================================================================== */ +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 ) ); +} + +/* ====================================================================== +Function: startRHConv +Purpose : Start a relative humidity conversion +Input : - fastmode true to enable fast conversion + - heater true to enable heater +Output : true if succeded, false otherwise +Comments: if heater enabled, it will not be auto disabled +====================================================================== */ +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 ) ); +} + +/* ====================================================================== +Function: waitEndConversion +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); +} + +/* ====================================================================== +Function: roundInt +Purpose : round a float value to int +Input : float value +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)); +} + +/* to avoid math library may I need to test something + like that +float TH02::showDecimals(float x, int numDecimals) +{ + int y=x; + double z=x-y; + double m=pow(10,numDecimals); + double q=z*m; + double r=round(q); + return static_cast<double>(y)+(1.0/m)*r; +} +*/ + +/* ====================================================================== +Function: getConversionValue +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 + - the configuration register is checked to see if last conv was + 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 ) + { + // 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); + + + + + // 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; + } + // 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); + } + } // 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 +Input : true if we want to round value to 1 digit precision, else 2 +Output : the compensed RH value (rounded or not) +Comments: +====================================================================== */ +int16_t TH02::getConpensatedRH(bool round) +{ + 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); + + // 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); + } + + // 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; +} + +/* ====================================================================== +Function: getLastRawRH +Purpose : return the raw humidity * 100 +Input : +Output : int value (ie 4123 for 41.23%) +Comments: +====================================================================== */ +int32_t TH02::getLastRawRH(void) +{ + return _last_rh; +} + +/* ====================================================================== +Function: getLastRawTemp +Purpose : return the raw temperature value * 100 +Input : +Output : int value (ie 2124 for 21.24 C) +Comments: +====================================================================== */ +int32_t TH02::getLastRawTemp(void) +{ + return _last_temp; +}
diff -r 000000000000 -r f1951c6c9187 th02.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/th02.h Fri Mar 17 10:13:49 2017 +0000 @@ -0,0 +1,122 @@ +// ********************************************************************************** +// Driver definition for HopeRF TH02 temperature and humidity sensor +// ********************************************************************************** +// Creative Commons Attrib Share-Alike License +// You are free to use/extend this library but please abide with the CC-BY-SA license: +// http://creativecommons.org/licenses/by-sa/4.0/ +// +// For any explanation see TH02 sensor information at +// http://www.hoperf.com/sensor/app/TH02.htm +// +// Code based on following datasheet +// http://www.hoperf.com/upload/sensor/TH02_V1.1.pdf +// +// Written by Charles-Henri Hallard (http://hallard.me) +//ported to mbed env by Philippe LAURENT (IUT de NICE France) +// +// History : V1.00 2014-07-14 - First release +// V1.10 2015-04-13 - changed to Wire library instead of I2C +// +// All text above must be included in any redistribution. +// +// ********************************************************************************** +#ifndef TH02_H +#define TH02_H + +#include <mbed.h> // + +// TH02 I2C Device address +#define TH02_I2C_ADDR 0x40 + +// TH02 Registers addresses +#define TH02_STATUS 0 +#define TH02_DATAh 1 +#define TH02_DATAl 2 +#define TH02_CONFIG 3 +#define TH02_ID 17 + +// TH02 custom error code return function +#define TH02_I2C_ERR 0xFF + +// Unititialized values (arbitrary) +#define TH02_UNINITIALIZED_TEMP 55555 // int32_t internal value +#define TH02_UNINITIALIZED_RH 1111 // int32_t internal value +#define TH02_UNDEFINED_VALUE 12345 // int16_t returned value + +// we decide error if conversion is >= 50ms +#define TH02_CONVERSION_TIME_OUT 50 + +// Bit definition of TH02 registers values +#define TH02_STATUS_RDY 0x01 + +#define TH02_CONFIG_START 0x01 +#define TH02_CONFIG_HEAT 0x02 +#define TH02_CONFIG_TEMP 0x10 +#define TH02_CONFIG_HUMI 0x00 +#define TH02_CONFIG_FAST 0x20 + +// THO2 Linearization Coefficients +#define TH02_A0 -4.7844 +#define TH02_A1 0.4008 +#define TH02_A2 -0.00393 + +// TH02 Temperature compensation Linearization Coefficients +#define TH02_Q0 0.1973 +#define TH02_Q1 0.00237 + + + + + +class TH02 { + public: + TH02(uint8_t address); + uint8_t getId(uint8_t * pvalue); + uint8_t getId(void); + uint8_t getStatus(uint8_t * pvalue); + bool isConverting(void); + uint8_t waitEndConversion(void); + uint8_t getConfig(uint8_t * pvalue); + uint8_t setConfig(uint8_t config); + uint8_t startTempConv(bool fastmode = false, bool heater = false); + uint8_t startRHConv(bool fastmode = false, bool heater = false); + int16_t roundInt(float value); + int16_t getConversionValue(void); + int16_t getConpensatedRH(bool round); + int32_t getLastRawRH(void); + int32_t getLastRawTemp(void); + +/** + * TH02 constructor + * + * @param sda I2C data pin + * @param scl I2C clock pin + * @param address I2C slave sensor address + + */ + TH02(PinName sda, PinName scl, uint8_t address); + + /** + * MFRC522 destructor + */ + ~TH02(); + + + + private: +I2C m_I2C; + uint8_t writeCommand(uint8_t command, bool release=true); + uint8_t writeRegister(uint8_t reg, uint8_t value); + uint8_t readRegister(uint8_t reg, uint8_t * value); + + int32_t _last_temp; // Last measured temperature (for linearization) + int32_t _last_rh; // Last measured RH + uint8_t _address; // I2C Module Address + + + +}; + + + +#endif \ No newline at end of file