Library for the Measurement Specialties' HTU21D Humidity and Temperature sensor. Code includes device's heater on/off control, serial number access, dew point calculations and RTOS hooks. To date, code tested on GR-PEACH, K64F and KL25Z boards with and w/o RTOS, SDFlash and USB serial Rx interrupts.

Dependents:   BLE_soil_humidity

Library for the Measurement Specialties / Honeywell HTU21D Humidity and Temperature sensor. Code includes device's heater on/off control, serial number access, dew point calculations and RTOS hooks. To date, code tested on K64F and KL25Z boards with and without RTOS, SDFileSystem and USB serial Rx interrupts.

The HTU21D's serial number is an odd cookie. There are two 16 bit registers and a 32 bit register are combined to generate the serial number. Some of the serial number bit fields are fixed for all devices and some change from part to part.

Files at this revision

API Documentation at this revision

Comitter:
loopsva
Date:
Wed May 14 00:31:30 2014 +0000
Child:
1:d3ed713f8354
Commit message:
Convert to library

Changed in this revision

htu21d.cpp Show annotated file Show diff for this revision Revisions of this file
htu21d.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htu21d.cpp	Wed May 14 00:31:30 2014 +0000
@@ -0,0 +1,234 @@
+/**
+HTU21D driver for mbed.  Includes RTOS hooks if RTOS is detected during compile
+Author: Kevin Braun
+**/
+#include "htu21d.h"
+
+#ifdef RTOS_H
+extern Mutex MutexI2cWait;
+#endif
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Contstructor
+
+htu21d::htu21d(PinName sda, PinName scl) : _i2c(sda, scl) {
+//    _i2c = new I2C(sda, scl);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//De-contstructor
+
+htu21d::~htu21d() {
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Perform a soft reset on the HTU21D. REturn of 1 = ok, 0 = timeout.
+
+int htu21d::softReset() {
+    
+#ifdef RTOS_H
+    MutexI2cWait.lock();
+#endif
+
+    int htu21 = 0;
+    _i2c.start();
+    htu21 = _i2c.write(HTU21Di2cWRITE);     //i2c, 1 = ack
+    if(htu21 == 1) {
+        _i2c.write(HTU21DRESET);            //soft reset, must wait 15mS
+        _i2c.stop();
+    }
+    wait_ms(16);                            //must wait a least 15mS for reset to finish
+    
+#ifdef RTOS_H
+    MutexI2cWait.unlock();
+#endif
+
+    return(htu21);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Get the HTU21D user register. Returns 8 bit register.
+
+uint8_t htu21d::getUserReg() {
+    
+#ifdef RTOS_H
+    MutexI2cWait.lock();
+#endif
+
+    int htu21 = 0;
+    uint8_t htu21data = 0;
+    _i2c.start();
+    htu21 = _i2c.write(HTU21Di2cWRITE);     //i2c, 1 = ack
+    if(htu21 == 1) {
+        _i2c.write(HTU21DREADUSER);
+        _i2c.start();
+        htu21 = _i2c.write(HTU21Di2cREAD);
+        htu21data = _i2c.read(0);
+        _i2c.stop();
+    }
+    
+#ifdef RTOS_H
+    MutexI2cWait.unlock();
+#endif
+
+    return(htu21data);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Turn ON the heater the HTU21D user register. 
+
+int htu21d::heaterOn() {
+    uint8_t htu21data = htu21d::getUserReg();
+    htu21data |= HTU21DHEATER;
+    
+#ifdef RTOS_H
+    MutexI2cWait.lock();
+#endif
+
+    int htu21 = 0;
+    _i2c.start();
+    htu21 = _i2c.write(HTU21Di2cWRITE);     //i2c, 1 = ack
+    if(htu21 == 1) {
+        _i2c.write(HTU21DWRITEUSER);
+        htu21 = _i2c.write(htu21data);
+        _i2c.stop();
+    }
+    
+#ifdef RTOS_H
+    MutexI2cWait.unlock();
+#endif
+
+    return(htu21);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Turn OFF the heater the HTU21D user register. 
+
+int htu21d::heaterOff() {
+    uint8_t htu21data = htu21d::getUserReg();
+    htu21data &= ~HTU21DHEATER;
+    
+#ifdef RTOS_H
+    MutexI2cWait.lock();
+#endif
+
+    int htu21 = 0;
+    _i2c.start();
+    htu21 = _i2c.write(HTU21Di2cWRITE);     //i2c, 1 = ack
+    if(htu21 == 1) {
+        _i2c.write(HTU21DWRITEUSER);
+        htu21 = _i2c.write(htu21data);
+        _i2c.stop();
+    }
+    
+#ifdef RTOS_H
+    MutexI2cWait.unlock();
+#endif
+
+    return(htu21);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Get the status of the heater the HTU21D user register. 0 = off, 4 = on.
+
+uint8_t htu21d::getHeater() {
+    uint8_t htu21data = htu21d::getUserReg();
+    htu21data &= HTU21DHEATER;
+    return(htu21data);
+}
+    
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//generic routine to get temp or humidity from HTU21D. 
+//Returns 14 bits of data (anded 0xFFFC) or 0000 if i2c timeout occurs.
+//After a read temp or humidity command, HTU21D responds with NACKs until data is ready.
+//NOTE: Use non-hold commands
+
+uint16_t htu21d::getData(uint8_t reg) {
+    int htu21 = 0;              //ACK flag
+    int htu21cnt = 0;           //number of NACKs before ACK or timeout 
+    uint16_t htu21data = 0;     //returned data
+
+#ifdef RTOS_H
+    MutexI2cWait.lock();
+#endif
+
+    _i2c.start();
+    htu21 = _i2c.write(HTU21Di2cWRITE);
+    _i2c.write(reg);            //read temp, no hold
+    if(htu21 == 0) return 0;    //HTU21T not responding
+    do {
+        htu21cnt++;
+        _i2c.start();
+        htu21 = _i2c.write(HTU21Di2cREAD);
+        if(htu21 == 1) {
+            htu21data = _i2c.read(1) << 8;
+            htu21data |= _i2c.read(0) & 0xFC;
+            _i2c.stop();
+        }
+        wait_us(50);
+    } while((htu21cnt < 1000) && (htu21 == 0)); //htu21cnt takes 510 to get temp, 160 for humidity
+ 
+#ifdef RTOS_H
+    MutexI2cWait.unlock();
+#endif
+
+    if(htu21 == 0) return 0;    //HTU21D ACK response timed out
+    return(htu21data);          //return 14 bit value
+}
+
+double theTempIs = 0.0;
+double theHumIs = 0.0;
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get temperature from HTU21D in degrees C. Returns with 255.0 if HTU21D had timed out.
+
+float htu21d::getTemp() {
+    uint16_t getData = htu21d::getData(HTU21DtempNOHOLD);
+    if (getData == 0) return(255.0);                        //return with error
+    double tempData = (double)getData / 65536.0;
+    theTempIs = -46.85 + (175.72 * tempData);
+    return(theTempIs);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//get humidity from HTU21D in percentage. Returns with 255.0 if HTU21D had timed out.
+
+float htu21d::getHum() {
+    uint16_t getData = htu21d::getData(HTU21DhumNOHOLD);
+    if (getData == 0) return(255.0);                        //return with error
+    double tempData = (double)getData / 65536.0;
+    theHumIs = -6.0 + (125.0 * tempData);
+    return(theHumIs);
+}
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+//Calculate the Dew Point from getTemp and getHum. User must first execute both getTemp and getHum for an accurate result.
+//Calculations come from DHT library
+/*  Copyright (C) Wim De Roeve
+ *                based on DHT22 sensor library by HO WING KIT
+ *                Arduino DHT11 library
+*/
+
+float htu21d::getDewPt() {
+    // dewPoint function NOAA
+    // reference: http://wahiduddin.net/calc/density_algorithms.htm    
+    double A0= 373.15/(273.15 + (double)theTempIs);
+    double SUM = -7.90298 * (A0-1);
+    SUM += 5.02808 * log10(A0);
+    SUM += -1.3816e-7 * (pow(10, (11.344*(1-1/A0)))-1) ;
+    SUM += 8.1328e-3 * (pow(10,(-3.49149*(A0-1)))-1) ;
+    SUM += log10(1013.246);
+    double VP = pow(10, SUM-3) * theHumIs;
+    double T = log(VP/0.61078);   // temp var
+    return (241.88 * T) / (17.558-T);
+}
+
+float htu21d::getDewPtFast() {
+    // delta max = 0.6544 wrt dewPoint()
+    // 5x faster than dewPoint()
+    // reference: http://en.wikipedia.org/wiki/Dew_point
+    double h21DtzA = 17.271;
+    double h21DtzB = 237.7;
+    double h21DtzC = (h21DtzA * theTempIs) / (h21DtzB + theTempIs) + log(theHumIs/100);
+    double h21DtzD = (h21DtzB * h21DtzC) / (h21DtzA - h21DtzC);
+    return (h21DtzD);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htu21d.h	Wed May 14 00:31:30 2014 +0000
@@ -0,0 +1,131 @@
+/**
+ */
+
+#ifndef HTU21D_H
+#define HTU21D_H
+
+#include "mbed.h"
+
+//Defines for HTU21D
+#define HTU21Di2cWRITE      0x80
+#define HTU21Di2cREAD       0x81
+
+#define HTU21DWRITEUSER     0xE6
+#define HTU21DREADUSER      0xE7
+#define HTU21DtempNOHOLD    0xF3
+#define HTU21DhumNOHOLD     0xF5
+#define HTU21DRESET         0xFE
+
+#define HTU21DHEATER        0x04
+
+
+/**
+ * Honeywell HTU21D digital humidity and temperature sensor.
+ */
+class htu21d {
+
+public:
+    /**
+     * Constructor.
+     *
+     * @param sda and scl, mbed I2C interface pins.
+     */
+    htu21d(PinName sda, PinName scl);
+    /**
+     * De-constructor.
+     *
+     * @param --none--.
+     */
+    ~htu21d();
+    /**
+     * Get HTU21D Temperature.
+     * 
+     * @param --none--.
+     *
+     * @return success / failure of HTU21D i2c access. 1 = ok, 0 = error.
+    */
+    int softReset();
+    /**
+     * Get HTU21D user register.
+     * 
+     * @param --none--.
+     *
+     * @return success / failure of HTU21D i2c access. 1 = ok, 0 = error.
+    */
+    uint8_t getUserReg();
+    /**
+     * Turn ON the heater in the HTU21D.
+     * 
+     * @param --none--.
+     *
+     * @return success / failure of HTU21D i2c access. 1 = ok, 0 = error.
+    */
+    int heaterOn();
+    /**
+     * Turn OFF the heater in the HTU21D.
+     * 
+     * @param --none--.
+     *
+     * @return --none--.
+    */
+    int heaterOff();
+    /**
+     * Get heater on/off status in the HTU21D.
+     * 
+     * @param --none--.
+     *
+     * @return 4 = on, 0 = 0ff.
+    */
+    uint8_t getHeater();
+    /**
+     * Do a reset on the HTU21D.
+     * 
+     * @param --none--.
+     *
+     * @return float of Temperature in degrees C.  255.0 if error.
+    */
+    float getTemp();
+    /**
+     * Get HTU21D Humidity.
+     * 
+     * @param --none--.
+     *
+     * @return float of Humidity in percentage.  255.0 if error.
+    */
+    float getHum();
+    /**
+     * Claculate the Dew Point.
+     * 
+     * @param MUST run getTemp and getHum first!!
+     *
+     * @return float of Dew Point.
+    */
+    float getDewPt();
+    /**
+     * Claculate the Dew Point. 5x faster than getDewPt().
+     * 
+     * @param MUST run getTemp and getHum first!!
+     *
+     * @return float of Dew Point.
+    */
+    float getDewPtFast();
+
+ 
+
+private:
+    I2C _i2c;
+    /**
+     * I2C access for getting raw Temperature and Humidity data.
+     * 
+     * @param 8 bit HTU21D register to get data from. Must use non-blocking regs.
+     *
+     * @return 16 bit raw i2c data, ANDed to 14 bits 0xFFFC. 0000 if error.
+    */
+    uint16_t getData(uint8_t reg);
+    double theTempIs;
+    double theHumIs;
+    float getTrash();
+
+};
+
+#endif