/* * 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 drivers_hih6130 * @{ * * @file * @brief Device driver implementation for Honeywell HumidIcon Digital * Humidity/Temperature Sensors: HIH-6130/6131 Series * * @author Joakim NohlgÄrd * * @} */ #include #include #include "hih6130.h" #include "periph/i2c.h" #include "xtimer.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 */ #define MEASUREMENT_DELAY (50LU * US_PER_MS) /** @brief Trigger a new measurement on the sensor */ static inline int hih6130_measurement_request(const hih6130_t *dev) { i2c_acquire(dev->i2c); /* An empty write request triggers a new measurement */ if (i2c_write_bytes(dev->i2c, dev->addr, 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(const 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, &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(const 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; } xtimer_usleep(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; }