mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
140 lines
3.6 KiB
C
140 lines
3.6 KiB
C
/*
|
|
* 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 <joakim.nohlgard@eistec.se>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#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) < 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), 0) < 0) {
|
|
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(const hih6130_t *dev,
|
|
int32_t *humidity_milli_percent, int32_t *temperature_milli_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 (humidity_milli_percent != NULL) {
|
|
*humidity_milli_percent= (int32_t)hum_raw * 100000 / 16383;
|
|
}
|
|
|
|
if (temperature_milli_celsius != NULL) {
|
|
*temperature_milli_celsius = (int32_t)temp_raw * 165000 / 16383 - 40000;
|
|
}
|
|
|
|
return status;
|
|
}
|