drivers: sensor: ccs811: support update of environmental conditions

Accurate estimate of gas presence requires temperature and humidity
data.  Add API to update these values.

Signed-off-by: Peter A. Bigot <pab@pabigot.com>
This commit is contained in:
Peter A. Bigot 2018-11-23 03:58:51 -06:00 committed by Maureen Helm
commit c90a738d8c
3 changed files with 89 additions and 0 deletions

View file

@ -86,6 +86,7 @@ int ccs811_baseline_fetch(struct device *dev)
if (rc <= 0) {
rc = baseline;
}
return rc;
}
@ -104,6 +105,74 @@ int ccs811_baseline_update(struct device *dev,
return rc;
}
int ccs811_envdata_update(struct device *dev,
const struct sensor_value *temperature,
const struct sensor_value *humidity)
{
struct ccs811_data *drv_data = dev->driver_data;
int rc;
u8_t buf[5] = { CCS811_REG_ENV_DATA };
/*
* Environment data are represented in a broken whole/fraction
* system that specified a 9-bit fractional part to represent
* milli-units. Since 1000 is greater than 512, the device
* actually only pays attention to the top bit, treating it as
* indicating 0.5. So we only write the first octet (7-bit
* while plus 1-bit half).
*
* Humidity is simple: scale it by two and round to the
* nearest half. Assume the fractional part is not
* negative.
*/
if (humidity) {
int value = 2 * humidity->val1;
value += (250000 + humidity->val2) / 500000;
if (value < 0) {
value = 0;
} else if (value > (2 * 100)) {
value = 2 * 100;
}
LOG_DBG("HUM %d.%06d becomes %d",
humidity->val1, humidity->val2, value);
buf[1] = value;
} else {
buf[1] = 2 * 50;
}
/*
* Temperature is offset from -25 Cel. Values below minimum
* store as zero. Default is 25 Cel. Again we round to the
* nearest half, complicated by Zephyr's signed representation
* of the fractional part.
*/
if (temperature) {
int value = 2 * temperature->val1;
if (temperature->val2 < 0) {
value += (250000 + temperature->val2) / 500000;
} else {
value += (-250000 + temperature->val2) / 500000;
}
if (value < (2 * -25)) {
value = 0;
} else {
value += 2 * 25;
}
LOG_DBG("TEMP %d.%06d becomes %d",
temperature->val1, temperature->val2, value);
buf[3] = value;
} else {
buf[3] = 2 * (25 + 25);
}
set_wake(drv_data, true);
rc = i2c_write(drv_data->i2c, buf, sizeof(buf), DT_INST_0_AMS_CCS811_BASE_ADDRESS);
set_wake(drv_data, false);
return rc;
}
static int ccs811_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct ccs811_data *drv_data = dev->driver_data;

View file

@ -17,6 +17,7 @@
#define CCS811_REG_MEAS_MODE 0x01
#define CCS811_REG_ALG_RESULT_DATA 0x02
#define CCS811_REG_RAW_DATA 0x03
#define CCS811_REG_ENV_DATA 0x05
#define CCS811_REG_THRESHOLDS 0x10
#define CCS811_REG_BASELINE 0x11
#define CCS811_REG_HW_ID 0x20

View file

@ -20,6 +20,7 @@ extern "C" {
#endif
#include <device.h>
#include <drivers/sensor.h>
/**
* @brief Fetch the current value of the BASELINE register.
@ -51,6 +52,24 @@ int ccs811_baseline_fetch(struct device *dev);
*/
int ccs811_baseline_update(struct device *dev, u16_t baseline);
/**
* @brief Update the ENV_DATA register.
*
* Accurate calculation of gas levels requires accurate environment
* data. Measurements are only accurate to 0.5 Cel and 0.5 %RH.
*
* @param dev Pointer to the sensor device
*
* @param temperature the current temperature at the sensor
*
* @param humidity the current humidity at the sensor
*
* @return 0 if successful, negative errno code if failure.
*/
int ccs811_envdata_update(struct device *dev,
const struct sensor_value *temperature,
const struct sensor_value *humidity);
#ifdef __cplusplus
}
#endif