From d85b67236876ab37f3989ef459f0ec20495cc7c7 Mon Sep 17 00:00:00 2001 From: Christian Hirsch Date: Mon, 23 Mar 2020 13:52:10 +0100 Subject: [PATCH] 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 --- drivers/sensor/ens210/Kconfig | 26 ++++++ drivers/sensor/ens210/ens210.c | 152 +++++++++++++++++++++++++-------- drivers/sensor/ens210/ens210.h | 22 +++++ 3 files changed, 166 insertions(+), 34 deletions(-) diff --git a/drivers/sensor/ens210/Kconfig b/drivers/sensor/ens210/Kconfig index fa02e15beb3..cc844524c82 100644 --- a/drivers/sensor/ens210/Kconfig +++ b/drivers/sensor/ens210/Kconfig @@ -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 diff --git a/drivers/sensor/ens210/ens210.c b/drivers/sensor/ens210/ens210.c index bb3b14f2465..1dfe961e865 100644 --- a/drivers/sensor/ens210/ens210.c +++ b/drivers/sensor/ens210/ens210.c @@ -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; } diff --git a/drivers/sensor/ens210/ens210.h b/drivers/sensor/ens210/ens210.h index 49f1a659a25..188e5475c1e 100644 --- a/drivers/sensor/ens210/ens210.h +++ b/drivers/sensor/ens210/ens210.h @@ -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