From 1a69a1eae8f750e1ee8148285a7cc29a38fcd7c8 Mon Sep 17 00:00:00 2001 From: Johann F Date: Mon, 24 Nov 2014 00:16:29 +0100 Subject: [PATCH] add hdc1000 sensor driver --- drivers/hdc1000/Makefile | 1 + drivers/hdc1000/hdc1000.c | 167 ++++++++++++++++++++++++++++++++++++++ drivers/include/hdc1000.h | 133 ++++++++++++++++++++++++++++++ 3 files changed, 301 insertions(+) create mode 100644 drivers/hdc1000/Makefile create mode 100644 drivers/hdc1000/hdc1000.c create mode 100644 drivers/include/hdc1000.h diff --git a/drivers/hdc1000/Makefile b/drivers/hdc1000/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/hdc1000/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/hdc1000/hdc1000.c b/drivers/hdc1000/hdc1000.c new file mode 100644 index 0000000000..1ab96924f2 --- /dev/null +++ b/drivers/hdc1000/hdc1000.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2014 PHYTEC Messtechnik GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + */ + +/** + * @ingroup drivers_hdc1000 + * @{ + * + * @file + * @brief Driver for the TI HDC1000 Humidity and Temperature Sensor. + * + * @author Johann Fischer + * + * @} + */ + +#include +#include +#include "periph/i2c.h" +#include "hdc1000.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief Register Map + */ +#define HDC1000_TEMPERATURE 0x00 +#define HDC1000_HUMIDITY 0x01 +#define HDC1000_CONFG 0x02 +#define HDCD1000_SID1 0xFB +#define HDCD1000_SID2 0xFC +#define HDCD1000_SID3 0xFD +#define HDC1000_MANUFACTURER_ID 0xFE +#define HDC1000_DEVICE_ID 0xFF + +/** + * @brief Configuration Register Description + */ +#define HDC1000_CONFG_RST (1 << 15) +#define HDC1000_CONFG_HEAT (1 << 13) +#define HDC1000_CONFG_SEQ_MOD (1 << 12) +#define HDC1000_CONFG_BTST_LOW (1 << 11) +#define HDC1000_CONFG_TRES_MSK (1 << 10) +#define HDC1000_CONFG_TRES_11 (1 << 10) +#define HDC1000_CONFG_TRES_14 0 +#define HDC1000_CONFG_HRES_MSK (1 << 9 | 1 << 8) +#define HDC1000_CONFG_HRES_14 0 +#define HDC1000_CONFG_HRES_11 (1 << 8) +#define HDC1000_CONFG_HRES_8 (1 << 9) + +/** + * @brief Manufacturer and Device ID + */ +#define HDC1000_MID_VALUE 0x5449 +#define HDC1000_DID_VALUE 0x1000 + +#define I2C_SPEED I2C_SPEED_FAST + +int hdc1000_test(hdc1000_t *dev) +{ + char reg[2]; + uint16_t tmp; + + if (i2c_read_regs(dev->i2c, dev->addr, HDC1000_MANUFACTURER_ID, reg, 2) != 2) { + return -1; + } + tmp = ((uint16_t)reg[0] << 8) | reg[1]; + if (tmp != HDC1000_MID_VALUE) { + return -1; + } + + return 0; +} + +int hdc1000_init(hdc1000_t *dev, i2c_t i2c, uint8_t address) +{ + char reg[2]; + + /* write device descriptor */ + dev->i2c = i2c; + dev->addr = address; + dev->initialized = false; + + /* initialize the I2C bus */ + if (i2c_init_master(i2c, I2C_SPEED) < 0) { + return -1; + } + + if (hdc1000_test(dev)) { + return -2; + } + + /* set 14 bit resolution for both sensors and sequence mode */ + uint16_t tmp = HDC1000_CONFG_SEQ_MOD; + reg[0] = (uint8_t)(tmp >> 8); + reg[1] = (uint8_t)tmp; + + if (i2c_write_regs(dev->i2c, dev->addr, HDC1000_CONFG, reg, 2) != 2) { + return -3; + } + dev->initialized = true; + + return 0; +} + +int hdc1000_reset(hdc1000_t *dev) +{ + char reg[2]; + uint16_t tmp = HDC1000_CONFG_RST; + reg[0] = (uint8_t)(tmp >> 8); + reg[1] = (uint8_t)tmp; + dev->initialized = false; + + if (i2c_write_regs(dev->i2c, dev->addr, HDC1000_CONFG, reg, 2) != 2) { + return -1; + } + return 0; +} + +int hdc1000_startmeasure(hdc1000_t *dev) +{ + if (dev->initialized == false) { + return -1; + } + /* Trigger the measurements by executing a write access + * to the address 0x00 (HDC1000_TEMPERATURE). + * Conversion Time is 6.50ms by 14 bit resolution. + */ + if (i2c_write_bytes(dev->i2c, dev->addr, HDC1000_TEMPERATURE, 1) != 1) { + return -1; + } + return 0; +} + +int hdc1000_read(hdc1000_t *dev, uint16_t *rawtemp, uint16_t *rawhum) +{ + char buf[4]; + + if (dev->initialized == false) { + return -1; + } + if (i2c_read_bytes(dev->i2c, dev->addr, buf, 4) != 4) { + return -1; + } + /* Register bytes are sent MSB first. */ + *rawtemp = ((uint16_t)buf[0] << 8) | buf[1]; + *rawhum = ((uint16_t)buf[2] << 8) | buf[3]; + + return 0; +} + +void hdc1000_convert(uint16_t rawtemp, uint16_t rawhum, int *temp, int *hum) +{ + /* calculate temperature*100 [°C] */ + *temp = (int)((((int32_t)rawtemp * 16500) >> 16) - 4000); + DEBUG("hdc1000 : T: %d\n", *temp); + + /* calculate relative humidity*100 [%RH] */ + *hum = (int)(((int32_t)rawhum * 10000) >> 16); + DEBUG("hdc1000 : RH: %d\n", *hum); +} diff --git a/drivers/include/hdc1000.h b/drivers/include/hdc1000.h new file mode 100644 index 0000000000..d971a1a1b1 --- /dev/null +++ b/drivers/include/hdc1000.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2014 PHYTEC Messtechnik GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_hdc1000 HDC1000 Humidity and Temperature Sensor + * @ingroup drivers + * @brief Driver for the Texas Instruments HDC1000 + * Humidity and Temperature Sensor. + * The driver will initialize the sensor for best + * resolution (14 bit). Currently the driver doesn't use the heater. + * Temperature and humidity are acquired in sequence. + * The sensor is always in sleep mode. The measurement must + * be started by a write access to the address 0x00 + * (HDC1000_TEMPERATURE). After completing the measurement + * the sensor will return to sleep mode. Typical + * Conversion Time by 14 bit resolution is 6.50ms. + * + * @{ + * + * @file + * @brief Interface definition for the HDC1000 sensor driver. + * + * @author Johann Fischer + */ + +#ifndef HDC1000_H +#define HDC1000_H + +#include +#include +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef HDC1000_I2C_ADDRESS +#define HDC1000_I2C_ADDRESS 0x41 +#endif + +#ifndef HDC1000_CONVERSION_TIME +#define HDC1000_CONVERSION_TIME 6500 +#endif + +/** + * @brief Device descriptor for HDC1000 sensors. + */ +typedef struct { + i2c_t i2c; /**< I2C device the sensor is connected to */ + uint8_t addr; /**< the sensor's slave address on the I2C bus */ + bool initialized; /**< sensor status, true if sensor is initialized */ +} hdc1000_t; + +/** + * @brief HDC1000 sensor test. + * This function looks for Manufacturer ID of the HDC1000 sensor. + * + * @param[in] dev device descriptor of sensor + * + * @return 0 on success + * @return -1 on error + */ +int hdc1000_test(hdc1000_t *dev); + +/** + * @brief Initialise the HDC1000 sensor driver. + * 14 bit resolution, heater off, temperature and humidity + * are acquired in sequence. + * + * @param[out] dev device descriptor of sensor to initialize + * @param[in] i2c I2C bus the sensor is connected to + * @param[in] address sensor's I2C slave address + * + * @return 0 on success + * @return -1 if initialization of I2C bus failed + * @return -2 if sensor test failed + * @return -3 if sensor configuration failed + */ +int hdc1000_init(hdc1000_t *dev, i2c_t i2c, uint8_t address); + +/** + * @brief Reset the HDC1000 sensor. After that sensor should be reinitialized. + * + * @param[out] dev device descriptor of sensor to reset + * + * @return 0 on success + * @return -1 on error + */ +int hdc1000_reset(hdc1000_t *dev); + +/** + * @brief Trigger the measurements. + * Conversion Time by 14 bit resolution is 6.50ms. + * + * @param[in] dev device descriptor of sensor + * + * @return 0 on success + * @return -1 on error + */ +int hdc1000_startmeasure(hdc1000_t *dev); + +/** + * @brief Read sensor's data. + * + * @param[in] dev device descriptor of sensor + * + * @return 0 on success + * @return -1 on error + */ +int hdc1000_read(hdc1000_t *dev, uint16_t *rawtemp, uint16_t *rawhum); + +/** + * @brief Convert raw sensor values to temperature and humidity. + * + * @param[in] rawtemp raw temperature value + * @param[in] rawhum raw humidity value + * @param[out] temp converted temperature*100 + * @param[out] hum converted humidity*100 + */ +void hdc1000_convert(uint16_t rawtemp, uint16_t rawhum, int *temp, int *hum); + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */