drivers: sensor: ENS210: add single shot mode

Add possibility to change the measurement modes
of the temperature and humidity measurements to
continuous or single-shot mode or switch them off.

Signed-off-by: Christian Hirsch <christian.hirsch@tuwien.ac.at>
This commit is contained in:
Christian Hirsch 2020-03-23 13:52:10 +01:00 committed by Ioannis Glaropoulos
commit d85b672368
3 changed files with 166 additions and 34 deletions

View file

@ -10,6 +10,32 @@ menuconfig ENS210
Enable driver for ENS210 Digital Temperature and Humidity sensor.
if ENS210
choice
prompt "Temperature measurement mode"
default ENS210_TEMPERATURE_CONTINUOUS
help
Enable/disable temperature measurements and set measurement mode.
config ENS210_TEMPERATURE_OFF
bool "Disable temperature measurements"
config ENS210_TEMPERATURE_SINGLE
bool "Enable temperature measurements in single shot mode"
config ENS210_TEMPERATURE_CONTINUOUS
bool "Enable temperature measurements in continuous mode"
endchoice
choice
prompt "Humidity measurement mode"
default ENS210_HUMIDITY_CONTINUOUS
help
Enable/disable relative humidity measurements and set measurement mode.
config ENS210_HUMIDITY_OFF
bool "Disable relative humidity measurements"
config ENS210_HUMIDITY_SINGLE
bool "Enable relative humidity measurements in single shot mode"
config ENS210_HUMIDITY_CONTINUOUS
bool "Enable relative humidity measurements in continuous mode"
endchoice
config ENS210_CRC_CHECK
bool "Enable CRC Check"
default y

View file

@ -36,6 +36,46 @@ static u32_t ens210_crc7(u32_t bitstream)
}
#endif /* CONFIG_ENS210_CRC_CHECK */
#if defined(CONFIG_ENS210_TEMPERATURE_SINGLE) \
|| defined(CONFIG_ENS210_HUMIDITY_SINGLE)
static int ens210_measure(struct device *i2c_dev, enum sensor_channel chan)
{
u8_t buf;
int ret;
const struct ens210_sens_start sense_start = {
.t_start = ENS210_T_START && (chan == SENSOR_CHAN_ALL
|| chan == SENSOR_CHAN_AMBIENT_TEMP),
.h_start = ENS210_H_START && (chan == SENSOR_CHAN_ALL
|| chan == SENSOR_CHAN_HUMIDITY)
};
/* Start measuring */
ret = i2c_reg_write_byte(i2c_dev,
DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_SENS_START, *(u8_t *)&sense_start);
if (ret < 0) {
LOG_ERR("Failed to set SENS_START to 0x%x",
*(u8_t *)&sense_start);
return -EIO;
}
/* Wait for measurement to be completed */
do {
k_sleep(K_MSEC(2));
ret = i2c_reg_read_byte(i2c_dev,
DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_SENS_START, &buf);
if (ret < 0) {
LOG_ERR("Failed to read SENS_STAT");
}
} while (buf & *(u8_t *)&sense_start);
return ret;
}
#endif /* Single shot mode */
static int ens210_sample_fetch(struct device *dev, enum sensor_channel chan)
{
struct ens210_data *drv_data = dev->driver_data;
@ -46,7 +86,18 @@ static int ens210_sample_fetch(struct device *dev, enum sensor_channel chan)
u32_t temp_valid, humidity_valid;
#endif /* CONFIG_ENS210_CRC_CHECK */
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL
|| chan == SENSOR_CHAN_AMBIENT_TEMP
|| chan == SENSOR_CHAN_HUMIDITY);
#if defined(CONFIG_ENS210_TEMPERATURE_SINGLE) \
|| defined(CONFIG_ENS210_HUMIDITY_SINGLE)
ret = ens210_measure(drv_data->i2c, chan);
if (ret < 0) {
LOG_ERR("Failed to measure");
return ret;
}
#endif /* Single shot mode */
for (cnt = 0; cnt <= CONFIG_ENS210_MAX_READ_RETRIES; cnt++) {
ret = i2c_burst_read(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
@ -56,35 +107,47 @@ static int ens210_sample_fetch(struct device *dev, enum sensor_channel chan)
continue;
}
if (!data[0].valid) {
LOG_WRN("Temperature not valid");
continue;
}
/* Get temperature value */
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP) {
if (!data[1].valid) {
LOG_WRN("Humidity not valid");
continue;
}
if (!data[0].valid) {
LOG_WRN("Temperature not valid");
continue;
}
#ifdef CONFIG_ENS210_CRC_CHECK
temp_valid = data[0].val |
(data[0].valid << (sizeof(data[0].val) * 8));
humidity_valid = data[1].val |
(data[1].valid << (sizeof(data[1].val) * 8));
temp_valid = data[0].val |
(data[0].valid << (sizeof(data[0].val) * 8));
if (ens210_crc7(temp_valid) != data[0].crc7) {
LOG_WRN("Temperature CRC error");
continue;
}
if (ens210_crc7(humidity_valid) != data[1].crc7) {
LOG_WRN("Humidity CRC error");
continue;
}
if (ens210_crc7(temp_valid) != data[0].crc7) {
LOG_WRN("Temperature CRC error");
continue;
}
#endif /* CONFIG_ENS210_CRC_CHECK */
drv_data->temp = data[0];
drv_data->humidity = data[1];
drv_data->temp = data[0];
}
/* Get humidity value */
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_HUMIDITY) {
if (!data[1].valid) {
LOG_WRN("Humidity not valid");
continue;
}
#ifdef CONFIG_ENS210_CRC_CHECK
humidity_valid = data[1].val |
(data[1].valid << (sizeof(data[1].val) * 8));
if (ens210_crc7(humidity_valid) != data[1].crc7) {
LOG_WRN("Humidity CRC error");
continue;
}
#endif /* CONFIG_ENS210_CRC_CHECK */
drv_data->humidity = data[1];
}
return 0;
}
@ -125,7 +188,10 @@ static int ens210_channel_get(struct device *dev,
static int ens210_sys_reset(struct device *i2c_dev)
{
const struct ens210_sys_ctrl sys_ctrl = {.low_power = 0, .reset = 1};
const struct ens210_sys_ctrl sys_ctrl = {
.low_power = 0,
.reset = 1
};
int ret;
ret = i2c_reg_write_byte(i2c_dev, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
@ -136,9 +202,12 @@ static int ens210_sys_reset(struct device *i2c_dev)
return ret;
}
static int ens210_sys_enable(struct device *i2c_dev)
static int ens210_sys_enable(struct device *i2c_dev, u8_t low_power)
{
const struct ens210_sys_ctrl sys_ctrl = {.low_power = 0, .reset = 0};
const struct ens210_sys_ctrl sys_ctrl = {
.low_power = low_power,
.reset = 0
};
int ret;
ret = i2c_reg_write_byte(i2c_dev, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
@ -173,7 +242,7 @@ static int ens210_wait_boot(struct device *i2c_dev)
ens210_sys_reset(i2c_dev);
}
ens210_sys_enable(i2c_dev);
ens210_sys_enable(i2c_dev, 0);
k_sleep(K_MSEC(2));
}
@ -196,13 +265,18 @@ static int ens210_init(struct device *dev)
{
struct ens210_data *drv_data = dev->driver_data;
const struct ens210_sens_run sense_run = {
.t_run = 1,
.h_run = 1
.t_run = ENS210_T_RUN,
.h_run = ENS210_H_RUN
};
#if defined(CONFIG_ENS210_TEMPERATURE_CONTINUOUS) \
|| defined(CONFIG_ENS210_HUMIDITY_CONTINUOUS)
const struct ens210_sens_start sense_start = {
.t_start = 1,
.h_start = 1
.t_start = ENS210_T_RUN,
.h_start = ENS210_H_RUN
};
#endif
int ret;
u16_t part_id;
@ -219,7 +293,9 @@ static int ens210_init(struct device *dev)
return -EIO;
}
/* Check Hardware ID. This is only possible after device is ready */
/* Check Hardware ID. This is only possible after device is ready
* and active
*/
ret = i2c_burst_read(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_PART_ID, (u8_t *)&part_id,
sizeof(part_id));
@ -234,7 +310,12 @@ static int ens210_init(struct device *dev)
return -EIO;
}
/* Set continuous measurement */
/* Enable low power mode */
if ((ENS210_T_RUN | ENS210_H_RUN) == 0) {
ens210_sys_enable(drv_data->i2c, 1);
}
/* Set measurement mode*/
ret = i2c_reg_write_byte(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_SENS_RUN, *(u8_t *)&sense_run);
if (ret < 0) {
@ -243,6 +324,8 @@ static int ens210_init(struct device *dev)
return -EIO;
}
#if defined(CONFIG_ENS210_TEMPERATURE_CONTINUOUS) \
|| defined(CONFIG_ENS210_HUMIDITY_CONTINUOUS)
/* Start measuring */
ret = i2c_reg_write_byte(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_SENS_START, *(u8_t *)&sense_start);
@ -251,6 +334,7 @@ static int ens210_init(struct device *dev)
*(u8_t *)&sense_start);
return -EIO;
}
#endif
return 0;
}

View file

@ -25,6 +25,28 @@
#define ENS210_PART_ID 0x0210
#if defined CONFIG_ENS210_TEMPERATURE_OFF
#define ENS210_T_RUN 0
#define ENS210_T_START 0
#elif defined CONFIG_ENS210_TEMPERATURE_SINGLE
#define ENS210_T_RUN 0
#define ENS210_T_START 1
#elif defined CONFIG_ENS210_TEMPERATURE_CONTINUOUS
#define ENS210_T_RUN 1
#define ENS210_T_START 1
#endif
#if defined CONFIG_ENS210_HUMIDITY_OFF
#define ENS210_H_RUN 0
#define ENS210_H_START 0
#elif defined CONFIG_ENS210_HUMIDITY_SINGLE
#define ENS210_H_RUN 0
#define ENS210_H_START 1
#elif defined CONFIG_ENS210_HUMIDITY_CONTINUOUS
#define ENS210_H_RUN 1
#define ENS210_H_START 1
#endif
/*
* Polynomial
* 0b 1000 1001 ~ x^7+x^3+x^0