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. Enable driver for ENS210 Digital Temperature and Humidity sensor.
if ENS210 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 config ENS210_CRC_CHECK
bool "Enable CRC Check" bool "Enable CRC Check"
default y default y

View file

@ -36,6 +36,46 @@ static u32_t ens210_crc7(u32_t bitstream)
} }
#endif /* CONFIG_ENS210_CRC_CHECK */ #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) static int ens210_sample_fetch(struct device *dev, enum sensor_channel chan)
{ {
struct ens210_data *drv_data = dev->driver_data; 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; u32_t temp_valid, humidity_valid;
#endif /* CONFIG_ENS210_CRC_CHECK */ #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++) { for (cnt = 0; cnt <= CONFIG_ENS210_MAX_READ_RETRIES; cnt++) {
ret = i2c_burst_read(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS, 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; continue;
} }
if (!data[0].valid) { /* Get temperature value */
LOG_WRN("Temperature not valid"); if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP) {
continue;
}
if (!data[1].valid) { if (!data[0].valid) {
LOG_WRN("Humidity not valid"); LOG_WRN("Temperature not valid");
continue; continue;
} }
#ifdef CONFIG_ENS210_CRC_CHECK #ifdef CONFIG_ENS210_CRC_CHECK
temp_valid = data[0].val | temp_valid = data[0].val |
(data[0].valid << (sizeof(data[0].val) * 8)); (data[0].valid << (sizeof(data[0].val) * 8));
humidity_valid = data[1].val |
(data[1].valid << (sizeof(data[1].val) * 8));
if (ens210_crc7(temp_valid) != data[0].crc7) { if (ens210_crc7(temp_valid) != data[0].crc7) {
LOG_WRN("Temperature CRC error"); LOG_WRN("Temperature CRC error");
continue; continue;
} }
if (ens210_crc7(humidity_valid) != data[1].crc7) {
LOG_WRN("Humidity CRC error");
continue;
}
#endif /* CONFIG_ENS210_CRC_CHECK */ #endif /* CONFIG_ENS210_CRC_CHECK */
drv_data->temp = data[0]; drv_data->temp = data[0];
drv_data->humidity = data[1]; }
/* 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; return 0;
} }
@ -125,7 +188,10 @@ static int ens210_channel_get(struct device *dev,
static int ens210_sys_reset(struct device *i2c_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; int ret;
ret = i2c_reg_write_byte(i2c_dev, DT_INST_0_AMS_ENS210_BASE_ADDRESS, 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; 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; int ret;
ret = i2c_reg_write_byte(i2c_dev, DT_INST_0_AMS_ENS210_BASE_ADDRESS, 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_reset(i2c_dev);
} }
ens210_sys_enable(i2c_dev); ens210_sys_enable(i2c_dev, 0);
k_sleep(K_MSEC(2)); k_sleep(K_MSEC(2));
} }
@ -196,13 +265,18 @@ static int ens210_init(struct device *dev)
{ {
struct ens210_data *drv_data = dev->driver_data; struct ens210_data *drv_data = dev->driver_data;
const struct ens210_sens_run sense_run = { const struct ens210_sens_run sense_run = {
.t_run = 1, .t_run = ENS210_T_RUN,
.h_run = 1 .h_run = ENS210_H_RUN
}; };
#if defined(CONFIG_ENS210_TEMPERATURE_CONTINUOUS) \
|| defined(CONFIG_ENS210_HUMIDITY_CONTINUOUS)
const struct ens210_sens_start sense_start = { const struct ens210_sens_start sense_start = {
.t_start = 1, .t_start = ENS210_T_RUN,
.h_start = 1 .h_start = ENS210_H_RUN
}; };
#endif
int ret; int ret;
u16_t part_id; u16_t part_id;
@ -219,7 +293,9 @@ static int ens210_init(struct device *dev)
return -EIO; 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, ret = i2c_burst_read(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_PART_ID, (u8_t *)&part_id, ENS210_REG_PART_ID, (u8_t *)&part_id,
sizeof(part_id)); sizeof(part_id));
@ -234,7 +310,12 @@ static int ens210_init(struct device *dev)
return -EIO; 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, ret = i2c_reg_write_byte(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_SENS_RUN, *(u8_t *)&sense_run); ENS210_REG_SENS_RUN, *(u8_t *)&sense_run);
if (ret < 0) { if (ret < 0) {
@ -243,6 +324,8 @@ static int ens210_init(struct device *dev)
return -EIO; return -EIO;
} }
#if defined(CONFIG_ENS210_TEMPERATURE_CONTINUOUS) \
|| defined(CONFIG_ENS210_HUMIDITY_CONTINUOUS)
/* Start measuring */ /* Start measuring */
ret = i2c_reg_write_byte(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS, ret = i2c_reg_write_byte(drv_data->i2c, DT_INST_0_AMS_ENS210_BASE_ADDRESS,
ENS210_REG_SENS_START, *(u8_t *)&sense_start); ENS210_REG_SENS_START, *(u8_t *)&sense_start);
@ -251,6 +334,7 @@ static int ens210_init(struct device *dev)
*(u8_t *)&sense_start); *(u8_t *)&sense_start);
return -EIO; return -EIO;
} }
#endif
return 0; return 0;
} }

View file

@ -25,6 +25,28 @@
#define ENS210_PART_ID 0x0210 #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 * Polynomial
* 0b 1000 1001 ~ x^7+x^3+x^0 * 0b 1000 1001 ~ x^7+x^3+x^0