IOT Greenhouse

Dependencies:   HC_SR04_Ultrasonic_Library PixelArrayBuffer Servo TSL2561 mbed-rtos mbed

Revision:
0:7ebf4813882d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/th02.cpp	Tue May 01 13:59:00 2018 +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;
+}