diff --git a/doc/releases/release-notes-4.0.rst b/doc/releases/release-notes-4.0.rst index 4c288f4f125..a6655191571 100644 --- a/doc/releases/release-notes-4.0.rst +++ b/doc/releases/release-notes-4.0.rst @@ -287,6 +287,11 @@ Drivers and Sensors :dtcompatible:`jedec,jc-42.4-temp` compatible string instead to the ``microchip,mcp9808`` string. + * WE + + * Added Würth Elektronik HIDS-2525020210002 + :dtcompatible:`we,wsen-hids-2525020210002` humidity sensor driver. + * Serial * LiteX: Renamed the ``compatible`` from ``litex,uart0`` to :dtcompatible:`litex,uart`. diff --git a/drivers/sensor/wsen/CMakeLists.txt b/drivers/sensor/wsen/CMakeLists.txt index eadffcbb2bf..fc72c7754bd 100644 --- a/drivers/sensor/wsen/CMakeLists.txt +++ b/drivers/sensor/wsen/CMakeLists.txt @@ -1,5 +1,7 @@ # Copyright (c) 2024 Analog Devices, Inc. +# Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +add_subdirectory_ifdef(CONFIG_WSEN_HIDS_2525020210002 wsen_hids_2525020210002) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/Kconfig b/drivers/sensor/wsen/Kconfig index eadffcbb2bf..39d727f9f4f 100644 --- a/drivers/sensor/wsen/Kconfig +++ b/drivers/sensor/wsen/Kconfig @@ -1,5 +1,7 @@ # Copyright (c) 2024 Analog Devices, Inc. +# Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +source "drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt b/drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt new file mode 100644 index 00000000000..3e881a897c0 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(wsen_hids_2525020210002.c) diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig b/drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig new file mode 100644 index 00000000000..249232a0a13 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +config WSEN_HIDS_2525020210002 + bool "WSEN-HIDS-2525020210002 humidity sensor" + default y + depends on DT_HAS_WE_WSEN_HIDS_2525020210002_ENABLED + select I2C + select HAS_WESENSORS + help + Enable driver for the WSEN-HIDS-2525020210002 I2C-based humidity sensor. diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c new file mode 100644 index 00000000000..eb2157d3a57 --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.c @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT we_wsen_hids_2525020210002 + +#include + +#include +#include +#include + +#include "wsen_hids_2525020210002.h" + +LOG_MODULE_REGISTER(WSEN_HIDS_2525020210002, CONFIG_SENSOR_LOG_LEVEL); + +static const hids_measureCmd_t precision_cmds[] = {HIDS_MEASURE_LPM, HIDS_MEASURE_MPM, + HIDS_MEASURE_HPM}; + +static const hids_measureCmd_t heater_cmds[] = {HIDS_HEATER_200_MW_01_S, HIDS_HEATER_200_MW_100_MS, + HIDS_HEATER_110_MW_01_S, HIDS_HEATER_110_MW_100_MS, + HIDS_HEATER_20_MW_01_S, HIDS_HEATER_20_MW_100_MS}; + +static int hids_2525020210002_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct hids_2525020210002_data *data = dev->data; + + hids_measureCmd_t cmd; + + int32_t raw_temperature; + int32_t raw_humidity; + + switch (chan) { + case SENSOR_CHAN_ALL: + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_HUMIDITY: + break; + default: + LOG_ERR("Fetching is not supported on channel %d.", chan); + return -ENOTSUP; + } + + if (data->sensor_precision == hids_2525020210002_precision_High && + data->sensor_heater != hids_2525020210002_heater_Off) { + cmd = heater_cmds[data->sensor_heater - 1]; + } else { + cmd = precision_cmds[data->sensor_precision]; + } + + if (HIDS_Sensor_Measure_Raw(&data->sensor_interface, cmd, &raw_temperature, + &raw_humidity) != WE_SUCCESS) { + LOG_ERR("Failed to fetch data sample"); + return -EIO; + } + + switch (chan) { + case SENSOR_CHAN_ALL: + data->temperature = raw_temperature; + data->humidity = raw_humidity; + break; + case SENSOR_CHAN_AMBIENT_TEMP: + data->temperature = raw_temperature; + break; + case SENSOR_CHAN_HUMIDITY: + data->humidity = raw_humidity; + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int hids_2525020210002_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct hids_2525020210002_data *data = dev->data; + + switch (chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + val->val1 = data->temperature / 1000; + val->val2 = ((int32_t)data->temperature % 1000) * (1000000 / 1000); + break; + case SENSOR_CHAN_HUMIDITY: + val->val1 = data->humidity / 1000; + val->val2 = ((int32_t)data->humidity % 1000) * (1000000 / 1000); + break; + default: + LOG_ERR("Channel not supported %d", chan); + return -ENOTSUP; + } + + return 0; +} + +/* Set precision configuration. */ +static int hids_2525020210002_precision_set(const struct device *dev, + const struct sensor_value *precision) +{ + struct hids_2525020210002_data *data = dev->data; + + if (precision->val1 < hids_2525020210002_precision_Low || + precision->val1 > hids_2525020210002_precision_High || precision->val2 != 0) { + LOG_ERR("Bad precision configuration %d", precision->val1); + return -EINVAL; + } + + data->sensor_precision = (hids_2525020210002_precision_t)precision->val1; + + return 0; +} + +/* Set heater option. */ +static int hids_2525020210002_heater_set(const struct device *dev, + const struct sensor_value *heater) +{ + struct hids_2525020210002_data *data = dev->data; + + if (heater->val1 < hids_2525020210002_heater_Off || + heater->val1 > hids_2525020210002_heater_On_20mW_100ms || heater->val2 != 0) { + LOG_ERR("Bad heater option %d", heater->val1); + return -EINVAL; + } + + data->sensor_heater = (hids_2525020210002_heater_t)heater->val1; + + return 0; +} + +static int hids_2525020210002_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + + if (chan != SENSOR_CHAN_ALL) { + LOG_WRN("attr_set() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + switch ((int)attr) { + case SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION: + return hids_2525020210002_precision_set(dev, val); + case SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER: + return hids_2525020210002_heater_set(dev, val); + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static int hids_2525020210002_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + struct hids_2525020210002_data *data = dev->data; + + if (chan != SENSOR_CHAN_ALL) { + LOG_WRN("attr_get() is not supported on channel %d.", chan); + return -ENOTSUP; + } + + if (val == NULL) { + LOG_WRN("address of passed value is NULL."); + return -EFAULT; + } + + switch ((int)attr) { + case SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION: + val->val1 = data->sensor_precision; + val->val2 = 0; + break; + case SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER: + val->val1 = data->sensor_heater; + val->val2 = 0; + break; + default: + LOG_ERR("Operation not supported."); + return -ENOTSUP; + } + + return 0; +} + +static const struct sensor_driver_api hids_2525020210002_driver_api = { + .attr_set = hids_2525020210002_attr_set, + .attr_get = hids_2525020210002_attr_get, + .sample_fetch = hids_2525020210002_sample_fetch, + .channel_get = hids_2525020210002_channel_get, +}; + +static int hids_2525020210002_init(const struct device *dev) +{ + const struct hids_2525020210002_config *const config = dev->config; + struct hids_2525020210002_data *data = dev->data; + struct sensor_value precision, heater; + + /* Initialize WE sensor interface */ + HIDS_Get_Default_Interface(&data->sensor_interface); + data->sensor_interface.interfaceType = WE_i2c; + if (!i2c_is_ready_dt(&config->bus_cfg.i2c)) { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + data->sensor_interface.handle = (void *)&config->bus_cfg.i2c; + + /* First communication test - check device ID */ + if (HIDS_Sensor_Init(&data->sensor_interface) != WE_SUCCESS) { + LOG_ERR("Failed to read device ID."); + return -EIO; + } + + precision.val1 = config->precision; + precision.val2 = 0; + + if (hids_2525020210002_precision_set(dev, &precision) < 0) { + LOG_ERR("Failed to set precision configuration."); + return -EIO; + } + + heater.val1 = config->heater; + heater.val2 = 0; + + if (hids_2525020210002_heater_set(dev, &heater) < 0) { + LOG_ERR("Failed to set heater option."); + return -EIO; + } + + return 0; +} + +/* + * Main instantiation macro. + */ +#define HIDS_2525020210002_DEFINE(inst) \ + static struct hids_2525020210002_data hids_2525020210002_data_##inst; \ + static const struct hids_2525020210002_config hids_2525020210002_config_##inst = { \ + .bus_cfg = {.i2c = I2C_DT_SPEC_INST_GET(inst)}, \ + .precision = (hids_2525020210002_precision_t)(DT_INST_ENUM_IDX(inst, precision)), \ + .heater = (hids_2525020210002_heater_t)(DT_INST_ENUM_IDX(inst, heater)), \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, hids_2525020210002_init, NULL, \ + &hids_2525020210002_data_##inst, \ + &hids_2525020210002_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &hids_2525020210002_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(HIDS_2525020210002_DEFINE) diff --git a/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h new file mode 100644 index 00000000000..64fba2d4d2a --- /dev/null +++ b/drivers/sensor/wsen/wsen_hids_2525020210002/wsen_hids_2525020210002.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_WSEN_HIDS_2525020210002_H_ +#define ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_WSEN_HIDS_2525020210002_H_ + +#include +#include + +#include + +#include "WSEN_HIDS_2525020210002_hal.h" + +#include +#include + +struct hids_2525020210002_data { + /* WE sensor interface configuration */ + WE_sensorInterface_t sensor_interface; + + /* Last humidity sample */ + int32_t humidity; + + /* Last temperature sample */ + int32_t temperature; + + hids_2525020210002_precision_t sensor_precision; + + hids_2525020210002_heater_t sensor_heater; +}; + +struct hids_2525020210002_config { + union { + const struct i2c_dt_spec i2c; + } bus_cfg; + + const hids_2525020210002_precision_t precision; + + const hids_2525020210002_heater_t heater; +}; + +#endif /* ZEPHYR_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_WSEN_HIDS_2525020210002_H_ */ diff --git a/dts/bindings/sensor/we,wsen-hids-2525020210002.yaml b/dts/bindings/sensor/we,wsen-hids-2525020210002.yaml new file mode 100644 index 00000000000..dc975787108 --- /dev/null +++ b/dts/bindings/sensor/we,wsen-hids-2525020210002.yaml @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG +# SPDX-License-Identifier: Apache-2.0 + +description: | + Würth Elektronik WSEN-HIDS-2525020210002 humidity sensor + +compatible: "we,wsen-hids-2525020210002" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + + precision: + type: string + default: "mid" + enum: + - "low" + - "mid" + - "high" + description: | + Sensor measurement precision for temperature and humidity. + Supported precision options are low, mid or high. + Defaults to mid, which is a good compromise between + current usage and precision. + + heater: + type: string + default: "OFF" + enum: + - "OFF" + - "ON_200MW_1S" + - "ON_200MW_100MS" + - "ON_110MW_1S" + - "ON_110MW_100MS" + - "ON_20MW_1S" + - "ON_20MW_100MS" + description: | + Activate the heater when fetching a sample for the specified amount of time. + This is only possible when the precison is set to high. + Defaults to OFF, since this option is valid for high precision + and the default precision is mid. diff --git a/include/zephyr/drivers/sensor/wsen_hids_2525020210002.h b/include/zephyr/drivers/sensor/wsen_hids_2525020210002.h new file mode 100644 index 00000000000..f140e22cdc3 --- /dev/null +++ b/include/zephyr/drivers/sensor/wsen_hids_2525020210002.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Würth Elektronik eiSos GmbH & Co. KG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Extended public API for WSEN-HIDS-2525020210002 Sensor + * + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_attribute_wsen_hids_2525020210002 { + SENSOR_ATTR_WSEN_HIDS_2525020210002_PRECISION = SENSOR_ATTR_PRIV_START, + SENSOR_ATTR_WSEN_HIDS_2525020210002_HEATER +}; + +typedef enum { + hids_2525020210002_precision_Low = 0x0, + hids_2525020210002_precision_Medium = 0x1, + hids_2525020210002_precision_High = 0x2 +} hids_2525020210002_precision_t; + +typedef enum { + hids_2525020210002_heater_Off = 0x0, + hids_2525020210002_heater_On_200mW_1s = 0x1, + hids_2525020210002_heater_On_200mW_100ms = 0x2, + hids_2525020210002_heater_On_110mW_1s = 0x3, + hids_2525020210002_heater_On_110mW_100ms = 0x4, + hids_2525020210002_heater_On_20mW_1s = 0x5, + hids_2525020210002_heater_On_20mW_100ms = 0x6, +} hids_2525020210002_heater_t; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_WSEN_HIDS_2525020210002_H_ */ diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index a63c1a32496..cb59ee4ecd3 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1109,3 +1109,9 @@ apds_9306: apds9306@92 { resolution = <13>; frequency = <2000>; }; + +test_i2c_wsen_hids_2525020210002: wsen_hids_2525020210002@99 { + compatible = "we,wsen-hids-2525020210002"; + reg = <0x99>; + precision = "high"; +};