diff --git a/Makefile.dep b/Makefile.dep index 2a4721a645..cdf9a4744b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -330,3 +330,7 @@ endif ifneq (,$(filter newlib,$(USEMODULE))) USEMODULE += uart_stdio endif + +ifneq (,$(filter hih6130,$(USEMODULE))) + USEMODULE += vtimer +endif diff --git a/drivers/hih6130/Makefile b/drivers/hih6130/Makefile new file mode 100644 index 0000000000..85e928e184 --- /dev/null +++ b/drivers/hih6130/Makefile @@ -0,0 +1,3 @@ +MODULE = hih6130 + +include $(RIOTBASE)/Makefile.base diff --git a/drivers/hih6130/hih6130.c b/drivers/hih6130/hih6130.c new file mode 100644 index 0000000000..8050e74305 --- /dev/null +++ b/drivers/hih6130/hih6130.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2015 Eistec AB + * + * 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 driver_hih6130 + * @{ + * + * @file + * @brief Device driver implementation for Honeywell HumidIcon Digital + * Humidity/Temperature Sensors: HIH-6130/6131 Series + * + * @author Joakim Gebart + * + * @} + */ + +#include +#include + +#include "hih6130.h" +#include "periph/i2c.h" +#include "timex.h" +#include "vtimer.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/* Humidity is stored in the first 2 bytes of data */ +#define HIH6130_HUMIDITY_DATA_LENGTH (2) +/* Humidity + temperature data is 4 bytes long */ +#define HIH6130_FULL_DATA_LENGTH (4) +/* Bit mask for the status bits in the first byte transferred */ +#define HIH6130_STATUS_MASK (0xc0) +/* Bit mask for the humidity data */ +#define HIH6130_HUMIDITY_MASK (0x3fff) +/* Temperature data is left adjusted within the word */ +#define HIH6130_TEMPERATURE_SHIFT (2) + +enum { + HIH6130_STATUS_OK = 0x00, + /** + * stale data: data that has already been fetched since the last measurement + * cycle, or data fetched before the first measurement has been completed. + */ + HIH6130_STATUS_STALE_DATA = 0x40, + HIH6130_STATUS_COMMAND_MODE = 0x80, + HIH6130_STATUS_DIAGNOSTIC = 0xc0, +}; + +/** @brief Delay between requesting a measurement and data becoming ready */ +static const timex_t measurement_delay = { + .seconds = 0, .microseconds = 50 * MS_IN_USEC, }; + +/** @brief Trigger a new measurement on the sensor */ +static inline int hih6130_measurement_request(hih6130_t *dev) +{ + i2c_acquire(dev->i2c); + + /* An empty write request triggers a new measurement */ + if (i2c_write_bytes(dev->i2c, dev->addr, (char *)NULL, 0) < 0) { + i2c_release(dev->i2c); + return -1; + } + + i2c_release(dev->i2c); + + return 0; +} + +void hih6130_init(hih6130_t *dev, i2c_t i2c, uint8_t address) +{ + /* write device descriptor */ + dev->i2c = i2c; + dev->addr = address; +} + +static inline int hih6130_get_humidity_temperature_raw(hih6130_t *dev, uint16_t *humidity_raw, uint16_t *temperature_raw) +{ + int status; + uint8_t buf[HIH6130_FULL_DATA_LENGTH]; + + i2c_acquire(dev->i2c); + + if (i2c_read_bytes(dev->i2c, dev->addr, (char*)&buf[0], sizeof(buf)) != sizeof(buf)) { + i2c_release(dev->i2c); + return -1; + } + + i2c_release(dev->i2c); + + /* data is in big-endian format, with status bits in the first byte. */ + switch (buf[0] & HIH6130_STATUS_MASK) { + case HIH6130_STATUS_OK: + status = 0; + break; + case HIH6130_STATUS_STALE_DATA: + status = 1; + break; + default: + return -2; + } + + *humidity_raw = ((buf[0] << 8) | buf[1]) & HIH6130_HUMIDITY_MASK; + *temperature_raw = (((buf[2] << 8) | buf[3]) >> HIH6130_TEMPERATURE_SHIFT); + + return status; +} + +int hih6130_get_humidity_temperature_float(hih6130_t *dev, + float *relative_humidity_percent, float *temperature_celsius) +{ + uint16_t hum_raw, temp_raw; + int status; + + if (hih6130_measurement_request(dev) != 0) { + return -1; + } + + vtimer_sleep(measurement_delay); + + status = hih6130_get_humidity_temperature_raw(dev, &hum_raw, &temp_raw); + + if (status < 0) { + return -1; + } + + if (relative_humidity_percent != NULL) { + *relative_humidity_percent = hum_raw * (100.f / 16383.f); + } + if (temperature_celsius != NULL) { + *temperature_celsius = temp_raw * (165.f / 16383.f) - 40.f; + } + + return status; +} diff --git a/drivers/include/hih6130.h b/drivers/include/hih6130.h new file mode 100644 index 0000000000..92c7780f03 --- /dev/null +++ b/drivers/include/hih6130.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 Eistec AB + * + * 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 driver_hih6130 HIH6130 humidity and temperature sensor + * @ingroup drivers + * @brief Device driver for Honeywell HumidIcon Digital + * Humidity/Temperature Sensors: HIH-6130/6131 Series + * @{ + * + * @file + * @brief Device driver for Honeywell HumidIcon Digital + * Humidity/Temperature Sensors: HIH-6130/6131 Series + * + * @author Joakim Gebart + */ + +#ifndef HIH6130_H_ +#define HIH6130_H_ + +#include + +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Device descriptor for HIH6130/HIH6131 sensors + */ +typedef struct { + i2c_t i2c; /**< I2C device the sensor is connected to */ + uint8_t addr; /**< the slave address of the sensor on the I2C bus */ +} hih6130_t; + +/** + * @brief Initialize a sensor + * + * @param[out] dev device descriptor of sensor to initialize + * @param[in] i2c I2C bus the sensor is connected to + * @param[in] address I2C slave address of the sensor + */ +void hih6130_init(hih6130_t *dev, i2c_t i2c, uint8_t address); + +/** + * @brief Read humidity and temperature from sensor and convert to floating-point + * + * @param[in] dev Sensor device descriptor + * @param[out] relative_humidity_percent Measured relative humidity in percent + * @param[out] temperature_celsius Measured temperature in degrees Celsius + * + * @return 0 on success + * @return -1 on error + * @return 1 if data is stale + */ +int hih6130_get_humidity_temperature_float(hih6130_t *dev, + float *relative_humidity_percent, float *temperature_celsius); + +#ifdef __cplusplus +} +#endif + +#endif /* HIH6130_H_ */ +/** @} */