Quick sample to return float temp in C.

Dependents:   mbed-IBooth-ETH

Fork of htu21d by Kevin Braun

htu21d.cpp

Committer:
loopsva
Date:
2014-05-22
Revision:
2:8fbe84ed61e6
Parent:
1:d3ed713f8354
Child:
3:396c0b63392e

File content as of revision 2:8fbe84ed61e6:

/**
HTU21D / HPP828E031 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

double theTempIs = 0.0;
double theHumIs = 0.0;

//--------------------------------------------------------------------------------------------------------------------------------------//
//Contstructor

htu21d::htu21d(PinName sda, PinName scl) : _i2c(sda, scl) {
    _i2c.frequency(400000);
}

htu21d::htu21d(PinName sda, PinName scl, int i2cFrequency) : _i2c(sda, scl) {
    _i2c.frequency(i2cFrequency);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
//Destructor

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
        htu21d::getSNReg();                 //go load up the s/n registers
    }

#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
    _i2c.stop();
#ifdef RTOS_H
        MutexI2cWait.unlock();
#endif

    if(htu21 == 0) return 0;    //HTU21T not responding
    do {
        htu21cnt++;
#ifdef RTOS_H
        MutexI2cWait.lock();
#endif
        _i2c.start();
        htu21 = _i2c.write(HTU21Di2cREAD);
        if(htu21 == 1) {
            htu21data = _i2c.read(1) << 8;
            htu21data |= _i2c.read(0) & 0xFC;
            _i2c.stop();
        }
#ifdef RTOS_H
        MutexI2cWait.unlock();                  //free up the I2C bus
        Thread::wait(1);                        //allow other RTOS functions to sneak in
#else
        wait_us(1000);
#endif
    } while((htu21cnt < 100) && (htu21 == 0));  //htu21cnt takes 55 to get temp, 16 for humidity (at 1mS loops)
        
    if(htu21 == 0) return 0;    //HTU21D ACK response timed out
    return(htu21data);          //return 14 bit value
}

//--------------------------------------------------------------------------------------------------------------------------------------//
//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);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
//Get the HTU21D serial number registers. Returns 64 bit register.
//should return 0x4854 00xx xxxx 32xx

void htu21d::getSNReg() {

#ifdef RTOS_H
    MutexI2cWait.lock();
#endif

    //get 16 bit SNC register, 8 bit SNC-CRC, 16 bit SNA register, 8 bit SNA-CRC
    int htu21 = 0;
    _i2c.start();
    htu21 = _i2c.write(HTU21Di2cWRITE);     //i2c, 1 = ack
    if(htu21 == 1) {
        _i2c.write(HTU21SNAC1);
        _i2c.write(HTU21SNAC2);
        _i2c.start();
        htu21 = _i2c.write(HTU21Di2cREAD);
        HTU21sn.HTU21D_snc = _i2c.read(1) << 8;
        HTU21sn.HTU21D_snc |= _i2c.read(1);
        HTU21sn.HTU21D_crcc = _i2c.read(1);
        HTU21sn.HTU21D_sna = _i2c.read(1) << 8;
        HTU21sn.HTU21D_sna |= _i2c.read(1);
        HTU21sn.HTU21D_crca = _i2c.read(0);
        _i2c.stop();
    }
    
    //get 32 bit SNB register, 32 bit SNB-CRC - regs are intermixed
    htu21 = 0;
    _i2c.start();
    htu21 = _i2c.write(HTU21Di2cWRITE);     //i2c, 1 = ack
    if(htu21 == 1) {
        _i2c.write(HTU21SNB1);
        _i2c.write(HTU21SNB2);
        _i2c.start();
        htu21 = _i2c.write(HTU21Di2cREAD);
        HTU21sn.HTU21D_snb = _i2c.read(1) << 24;
        HTU21sn.HTU21D_crcb = _i2c.read(1) << 24;
        HTU21sn.HTU21D_snb |= _i2c.read(1) << 16;
        HTU21sn.HTU21D_crcb |= _i2c.read(1) << 16;
        HTU21sn.HTU21D_snb |= _i2c.read(1) << 8;
        HTU21sn.HTU21D_crcb |= _i2c.read(1) << 8;
        HTU21sn.HTU21D_snb |= _i2c.read(1);
        HTU21sn.HTU21D_crcb |= _i2c.read(0);
        _i2c.stop();
    }
    
#ifdef RTOS_H
    MutexI2cWait.unlock();
#endif

}