SHTx Temperature and Humidity Sensor (Part 3)
PlainSHT1x contains a set of additional functions which perform advanced tasks such as checking power supply voltage:
uint8_t PlainSHT1x::Battery() { uint8_t regContent = ReadRegister(); return ((regContent >> 6) & 0x01); };
… changing the resolution of measurements:
void PlainSHT1x::Resolution(uint8_t state) { _resolution = state; uint8_t regContent = ReadRegister(); if (state) { regContent |= (1 << 0); } else { regContent &= ~(1 << 0); } WriteRegister(regContent); }; uint8_t PlainSHT1x::Resolution() { uint8_t regContent = ReadRegister(); _resolution = ((regContent >> 0) & 0x01); return(_resolution); };
… turning the heating element ON and OFF for conditioning the sensor
uint8_t PlainSHT1x::Heater(uint8_t state) { _heater = state; uint8_t regContent = ReadRegister(); if (state) { regContent |= (1 << 2); } else { regContent &= ~(1 << 2); } WriteRegister(regContent); return(_heater); }; uint8_t PlainSHT1x::Heater(void) { uint8_t regContent = ReadRegister(); _heater = ((regContent >> 2) & 0x01); return(_heater); };
More interesting are the functions which perform physical measurements. One function gets thermal OR humidity measurements
uint16_t PlainSHT1x::GetSingleADCData(uint8_t dataType) /* Get one single adc value for temperature or humidity */ { if (_errorCode != ERR_NONE) { return(0); /* exit and propagate error */ } /* Init transmission with sensor */ StartTransmit(); /* Query data */ WriteByte(dataType); if (_errorCode != ERR_NONE) { return(0); /* exit and propagate error */ } /* Wait for convertion completion */ uint16_t timeOut = 1000; do { _delay_ms(1.0); timeOut -= 1; if(timeOut == 0) { _errorCode = ERR_CVT_FAILURE; break; } } while (GetPinLevel(_pinData)); if (_errorCode != ERR_NONE) { return(0); /* exit and propagate error */ } /* Read and store two data bytes (MSB-LSB) */ uint8_t MSB = ReadByte(ACK_YES); uint8_t LSB = ReadByte(ACK_YES); uint8_t readCRC = ReadByte(ACK_NO); uint16_t data = ((MSB << 8) | LSB); return(data); };
While the GetData() function manages the collection of raw data and calculates additional information such as linear RH%, compensated RH% and dew point:
void PlainSHTx::GetData(void) /* Get combined data */ { /* Reset error code */ ErrorCode(ERR_NONE); /* Get and compute temperature */ uint32_t tempADC = GetSingleADCData(CMD_GET_TEMPERATURE); if (_errorCode != ERR_NONE) { return; /* Exit and propagate error */ } /* Convert adc data in C (5V)*/ if (_resolution == RES_HIGH) { tempADC &= 0x3FFF; /* Apply 14 bits mask */ _temperature = ((tempADC * 0.01) - 40.1); } else { tempADC &= 0xFFF; /* Apply 12 bits mask */ _temperature = ((tempADC * 0.04) - 40.1); } /* Get and compute relative humidity */ uint32_t relHumADC = GetSingleADCData(CMD_GET_REL_HUMIDITY); if (_errorCode != ERR_NONE) { return; /* Exit and propagate error */ } /* Convert adc data in rh% */ if (_resolution == RES_HIGH) { relHumADC &= 0xFFF; /* Apply 12 bits mask */ _relHumidityLin = ((-1.5955E-6 * (relHumADC * relHumADC)) + (0.0367 * relHumADC) - 2.0468); } else { /* Default is high */ relHumADC &= 0xFF; /* Apply 8 bits mask */ _relHumidityLin = ((-4.0845E-4 * (relHumADC * relHumADC)) + (0.5872 * relHumADC) - 2.0468); } /* Compute compensated relative humidity */ if (_resolution == RES_HIGH) { _relHumidityTempCompensated = (_temperature - 25.0) * (0.01 + (0.00008 * relHumADC)) + _relHumidityLin;; } else { _relHumidityTempCompensated = (_temperature - 25.0) * (0.01 + (0.00128 * relHumADC)) + _relHumidityLin;; } /* Keep result within bounds */ if (_relHumidityTempCompensated > 100.0) { _relHumidityTempCompensated = 100.0; } if (_relHumidityTempCompensated < 0.1) { _relHumidityTempCompensated = 0.1; } /* Compute dew point */ if (_temperature > 0) { double H = ((log10(_relHumidityTempCompensated) - 2.0) / 0.4343) + ((17.62 * _temperature) / (243.12 +_temperature)); _dewPoint = ((243.12 * H) / (17.62 - H)); } else { double H = ((log10(_relHumidityTempCompensated) - 2.0) / 0.4343) + ((22.46 * _temperature) / (272.62 +_temperature)); _dewPoint = ((272.62 * H) / (22.46 - H)); } };
Note: In case of error, the resulting temperatures are set to an aberrant -300°C value, while RH% are set to a negative %.
Each measurement can be extracted using public functions:
double PlainSHT1x::Temperature(void) { if (_errorCode != ERR_NONE) { return(-300.0); } return(_temperature); }; double PlainSHT1x::DewPoint(void) { if (_errorCode != ERR_NONE) { return(-300.0); } return(_dewPoint); }; double PlainSHT1x::RelHumidityTempCompensated(void) { if (_errorCode != ERR_NONE) { return(-1.0); } return(_relHumidityTempCompensated); }; double PlainSHT1x::RelHumidityLinear(void) { if (_errorCode != ERR_NONE) { return(-1.0); } return(_relHumidityLin); };
As usual, these functions are embedded in a clean nicely working library available on request