TI HDC1000 Temperature and Humidity Sensor
Diff: HDC1000.cpp
- Revision:
- 0:1db0d0071723
- Child:
- 1:f2c04c5b28ab
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HDC1000.cpp Mon Apr 17 02:49:07 2017 +0000 @@ -0,0 +1,349 @@ +#include "mbed.h" +#include "HDC1000.h" + +#define REG_TEMPERATURE 0x00 +#define REG_HUMIDITY 0x01 +#define REG_CONFIGURATION 0x02 +#define REG_ID_FIRST_WORD 0xFB +#define REG_ID_SECOND_WORD 0xFC +#define REG_ID_LAST_BYTE 0xFD +#define REG_MANUFACTURE_ID 0xFE +#define REG_DEVICE_ID 0xFF + +/* Bit field of Configuration register */ +/* bit[15] RST Sowtware Rest Bit 0: Normal 1: Reset + * bit[14:13] (Reserved) must be 00 + * bit[12] MODE 0:Aquire Temp/Hum separately(16bit each) 1:Aquire both Temp/Hum same time (32bit) + * bit[11] BTST Battery Test(?) 0:VDD > 2.8V 1:VDD < 2.8V + * bit[10] TRES Temperature Resolution 0:14bit 1:11bit + * bit[9:8] HRES Humidity Resolution 00:14bit 01:11bit 10:8bit + * bit[7:0] (Reserved) must be 00000000 + */ +#define BIT_RESET 0x8000 +#define BIT_MODE 0x1000 +#define BIT_BTST 0x0800 +#define BIT_TRES 0x0400 +#define BIT_HRES14 0x0000 +#define BIT_HRES11 0x0100 +#define BIT_HRES08 0x0200 + +HDC1000::HDC1000(PinName sda, PinName scl, PinName rdy, int addr) : m_i2c(sda, scl), m_rdy(rdy), m_addr(addr<<1) { +// HDC1000::HDC1000(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr<<1) { + // activate the peripheral + +} + +HDC1000::~HDC1000(void) +{ +} + +void HDC1000::reset(void) +{ + uint16_t conf = 0x8000 ; + setConfig(conf) ; +} + +float HDC1000::readTemperature(void) +{ + uint16_t utemp, uhum ; + int32_t ltemp ; + int mode ; + float ftemp ; + + mode = getMode() ; + switch(mode) { + case 0: /* temp or hum can be acquired */ + utemp = getTemperature() ; + break ; + case 1: /* temp and hum can be acquired */ + getData(&utemp, &uhum) ; + break ; + default: + printf("Error: unexpected mode %d\n",mode) ; + break ; + } + // note: the data sheet suggests to use 0x10000 for denominator + // but to allow 100% I chose 0xFFFF instead, I may be wrong + printf("utemp = 0x%04X ", utemp) ; + ltemp = (utemp >> 2) & 0x3FFF ; + + ftemp = ((float)(ltemp)/ (float)0x3FFF)*165.0 - 40.0 ; + return( ftemp ) ; +} + +float HDC1000::readHumidity(void) +{ + uint16_t utemp, uhume ; + int mode ; + int32_t lhume ; + float fhum ; + + mode = getMode() ; + switch(mode) { + case 0: /* temp or hum can be acquired */ + uhume = getHumidity() ; + break ; + case 1: /* temp and hum can be acquired */ + getData(&utemp, &uhume) ; + break ; + default: + printf("Error: unexpected mode %d\n",mode) ; + break ; + } + // note: the data sheet suggests to use 0x10000 for denominator + // but to allow 100% I chose 0xFFFF instead, I may be wrong + printf("uhume = 0x%04X\n", uhume) ; + lhume = (uhume>>2) & 0x3FFF ; + + fhum = ((float)(lhume) / (float)0x3FFF) * 100.0 ; + return( fhum ) ; +} + +void HDC1000::readData(float *ftemp, float *fhume) +{ + uint16_t utemp, uhume ; + getData(&utemp, &uhume) ; + printf("utemp: 0x%04X, uhume: 0x%04X\n", utemp, uhume) ; + utemp = (utemp >> 2) & 0x3FFF ; + uhume = (uhume >> 2) & 0x3FFF ; + *ftemp = ((float)(utemp)/ (float)0x3FFF)*165.0 - 40.0 ; + *fhume = ((float)(uhume) / (float)0x3FFF) * 100.0 ; +} +/* for mode 0 */ +uint16_t HDC1000::getTemperature(void) +{ + uint16_t temp ; + uint8_t data[2] ; + float delay ; + data[0] = REG_TEMPERATURE ; + data[1] = (m_addr << 1) | 0x01 ; + m_i2c.write(m_addr, (const char*)data, 2, true); + while(m_rdy == 1) { } /* wait for rdy */ + +// delay = getTDelay() ; +// wait_us(1000 * delay) ; + + m_i2c.read(m_addr, (char *)data, 2); + temp = (data[0] << 8) | data[1] ; + return( temp ) ; +} + +uint16_t HDC1000::getHumidity(void) +{ + uint16_t hume ; + uint8_t data[2] ; + float delay ; +// readRegs(REG_HUMIDITY, data, 2) ; + data[0] = REG_HUMIDITY ; + data[1] = (m_addr << 1) | 0x01 ; + m_i2c.write(m_addr, (const char*)data, 2, true); + + while(m_rdy == 1) { } /* wait for rdy */ +// delay = getHDelay() ; +// wait_us(1000 * delay) ; +// wait(0.1) ; + + m_i2c.read(m_addr, (char *)data, 2); + hume = (data[0] << 8) | data[1] ; + return( hume ) ; +} + +/* for mode 1 */ +void HDC1000::getData(uint16_t *temp, uint16_t *hume) +{ + float delay ; + uint8_t data[4] = { 0, 0, 0, 0 } ; + int mode ; + + mode = getMode() ; + if (mode == 0) { + *temp = getTemperature() ; + *hume = getHumidity() ; + } else { /* mode == 1 */ + data[0] = REG_TEMPERATURE ; + data[1] = (m_addr << 1) | 0x01 ; + m_i2c.write(m_addr,(const char *)data, 2, false); + + while(m_rdy == 1) { } /* wait for rdy */ +// delay = getTDelay() + getHDelay() ; +// wait_us(1000 * delay) ; + +// m_i2c.write(m_addr,(const char *)data, 1, true); +// while(m_rdy == 1) { } /* wait for rdy */ + m_i2c.read(m_addr, (char *)data, 4); + *temp = (data[0] << 8) | data[1] ; + *hume = (data[2] << 8) | data[3] ; + } +} + +void HDC1000::setConfig(uint16_t conf) +{ + uint8_t data[3] ; + data[0] = REG_CONFIGURATION ; + data[1] = (conf >> 8) & 0xFF ; + data[2] = conf & 0xFF ; + writeRegs(data, 3) ; +} + +uint16_t HDC1000::getConfig(void) +{ + uint8_t data[2] ; + uint16_t conf ; + readRegs(REG_CONFIGURATION, data, 2) ; + conf = (data[0] << 8) | data[1] ; + return( conf ) ; +} + +void HDC1000::setMode(int mode) +{ + uint16_t conf ; + conf = getConfig() ; + if (mode) { + conf |= BIT_MODE ; + } else { + conf ^= BIT_MODE ; + } + setConfig( conf ) ; +} + +int HDC1000::getMode(void) +{ + uint16_t conf ; + int mode ; + conf = getConfig() ; + if (conf & BIT_MODE) { + mode = 1 ; + } else { + mode = 0 ; + } + return( mode ) ; +} + +void HDC1000::setTres(int tres) +{ + uint16_t conf ; + conf = getConfig() ; + if (tres) { + conf |= BIT_TRES ; + } else { + conf ^= BIT_TRES ; + } +} + +int HDC1000::getTres(void) +{ + uint16_t conf ; + int tres ; + conf = getConfig() ; + if (conf & BIT_TRES) { + tres = 1 ; + } else { + tres = 0 ; + } + return( tres ) ; +} + +void HDC1000::setHres(int hres) +{ + uint16_t conf ; + conf = getConfig() ; + conf ^= (BIT_HRES11 | BIT_HRES08) ; + conf |= ((hres & 0x03) << 8) ; +} + +int HDC1000::getHres(void) +{ + uint16_t conf ; + int hres ; + conf = getConfig() ; + hres = (conf >> 8)&0x03 ; + return( hres ) ; +} + +void HDC1000::getSerialID(uint8_t data[]) +{ + uint8_t udata[2] ; + readRegs(REG_ID_FIRST_WORD, &data[0], 2) ; + readRegs(REG_ID_SECOND_WORD, &data[2], 2) ; + readRegs(REG_ID_LAST_BYTE, udata, 2) ; + data[4] = udata[0] ; +} + +uint16_t HDC1000::getManufactureID(void) /* 0x5449 : Texas Instruments */ +{ + uint8_t data[2] ; + uint16_t id ; + readRegs(REG_MANUFACTURE_ID, data, 2) ; + id = (data[0] << 8) | data[1] ; + return( id ) ; +} + +uint16_t HDC1000::getDeviceID(void) /* 0x1000 */ +{ + uint8_t data[2] ; + uint16_t id ; + readRegs(REG_DEVICE_ID, data, 2) ; + id = (data[0] << 8) | data[1] ; + return( id ) ; +} + +float HDC1000::getTDelay(void) +{ + int tres ; + float tdelay ; + + tres = getTres() ; + switch(tres) { + case 0: /* 14bit */ + tdelay = 6.35 ; + break ; + case 1: /* 11bit */ + tdelay = 3.65 ; + break ; + default: + tdelay = 6.35 ; + break ; + } + return(tdelay) ; +} + +float HDC1000::getHDelay(void) +{ + int hres ; + float hdelay ; + + hres = getHres() ; + switch(hres) { + case 0: /* 14bit */ + hdelay = 6.5 ; + break ; + case 1: /* 11bit */ + hdelay = 3.85 ; + break ; + case 2: /* 8bit */ + hdelay = 2.5 ; + break ; + default: + hdelay = 6.5 ; /* let's use the longest value */ + break ; + } + return(hdelay) ; +} + +float HDC1000::getDelay(void) +{ + float tdelay, hdelay ; + tdelay = getTDelay() ; + hdelay = getHDelay() ; + return( tdelay + hdelay ) ; +} + +void HDC1000::readRegs(int addr, uint8_t * data, int len) { + char t[1] = {addr}; + m_i2c.write(m_addr, t, 1, true); + m_i2c.read(m_addr, (char *)data, len) ; +} + +void HDC1000::writeRegs(uint8_t * data, int len) { + m_i2c.write(m_addr, (char *)data, len); +}