diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index a50b1c55657ef60..156aa6b074068ea 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -46,6 +46,7 @@ add_subdirectory_ifdef(CONFIG_HAS_STMEMSC stmemsc) add_subdirectory_ifdef(CONFIG_HM330X hm330x) add_subdirectory_ifdef(CONFIG_HMC5883L hmc5883l) add_subdirectory_ifdef(CONFIG_HP206C hp206c) +add_subdirectory_ifdef(CONFIG_HS300X hs300x) add_subdirectory_ifdef(CONFIG_HTS221 hts221) add_subdirectory_ifdef(CONFIG_I3G4250D i3g4250d) add_subdirectory_ifdef(CONFIG_ICM42605 icm42605) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 585bc7dc2db4fa9..e858bfdc5ce8572 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -101,6 +101,7 @@ source "drivers/sensor/grow_r502a/Kconfig" source "drivers/sensor/hm330x/Kconfig" source "drivers/sensor/hmc5883l/Kconfig" source "drivers/sensor/hp206c/Kconfig" +source "drivers/sensor/hs300x/Kconfig" source "drivers/sensor/hts221/Kconfig" source "drivers/sensor/i3g4250d/Kconfig" source "drivers/sensor/icm42605/Kconfig" diff --git a/drivers/sensor/hs300x/CMakeLists.txt b/drivers/sensor/hs300x/CMakeLists.txt new file mode 100644 index 000000000000000..f937e6bb6f11b3e --- /dev/null +++ b/drivers/sensor/hs300x/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(hs300x.c) diff --git a/drivers/sensor/hs300x/Kconfig b/drivers/sensor/hs300x/Kconfig new file mode 100644 index 000000000000000..53060cb5c217efd --- /dev/null +++ b/drivers/sensor/hs300x/Kconfig @@ -0,0 +1,12 @@ +# Renesas HS300x temperature and humidity sensor configuration options + +# Copyright (c) 2023 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +config HS300X + bool "HS300x Temperature and Humidity Sensor" + default y + depends on DT_HAS_RENESAS_HS300X_ENABLED + select I2C + help + Enable driver for HS300x temperature and humidity sensors. diff --git a/drivers/sensor/hs300x/hs300x.c b/drivers/sensor/hs300x/hs300x.c new file mode 100644 index 000000000000000..9faabbb1e352092 --- /dev/null +++ b/drivers/sensor/hs300x/hs300x.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_hs300x + +#include +#include +#include +#include +#include +#include +#include + +#define HS300X_STATUS_MASK (BIT(0) | BIT(1)) + +LOG_MODULE_REGISTER(HS300X, CONFIG_SENSOR_LOG_LEVEL); + +struct hs300x_config { + struct i2c_dt_spec bus; +}; + +struct hs300x_data { + int16_t t_sample; + uint16_t rh_sample; +}; + +static int hs300x_read_sample(const struct device *dev, uint16_t *t_sample, uint16_t *rh_sample) +{ + const struct hs300x_config *cfg = dev->config; + uint8_t rx_buf[4]; + int rc; + + rc = i2c_read_dt(&cfg->bus, rx_buf, sizeof(rx_buf)); + if (rc < 0) { + LOG_ERR("Failed to read data from device."); + return rc; + } + + if ((rx_buf[3] & HS300X_STATUS_MASK) != 0) { + LOG_ERR("Stale data"); + return -EIO; + } + + *rh_sample = sys_get_be16(rx_buf); + *t_sample = sys_get_be16(&rx_buf[2]); + + /* Remove status bits (only present in temperature value)*/ + *t_sample >>= 2; + + return 0; +} + +static int hs300x_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct hs300x_data *data = dev->data; + const struct hs300x_config *cfg = dev->config; + int rc; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP && + chan != SENSOR_CHAN_HUMIDITY) { + return -ENOTSUP; + } + + /* + * Initiate a measurement simply by sending 7-bit address followed + * by an eighth bit set to 0 (write) and NO data. + */ + rc = i2c_write_dt(&cfg->bus, NULL, 0); + if (rc < 0) { + LOG_ERR("Failed to start measurement."); + return rc; + } + + /* + * According to datasheet maximum time to make temperature and humidity + * measurements is 33ms, add a little safety margin... + */ + k_msleep(50); + + rc = hs300x_read_sample(dev, &data->t_sample, &data->rh_sample); + if (rc < 0) { + LOG_ERR("Failed to fetch data."); + return rc; + } + + return 0; +} + +static void hs300x_temp_convert(struct sensor_value *val, int16_t raw) +{ + int32_t micro_c; + + /* + * Convert to micro Celsius. See datasheet "Calculating Humidity and + * Temperature Output" section for more details on processing sample data. + */ + micro_c = (((int64_t)raw * 165000000) / 16383) - 40000000; + + val->val1 = micro_c / 1000000; + val->val2 = micro_c % 1000000; +} + +static void hs300x_rh_convert(struct sensor_value *val, uint16_t raw) +{ + int32_t micro_rh; + + /* + * Convert to micro %RH. See datasheet "Calculating Humidity and + * Temperature Output" section for more details on processing sample data. + */ + micro_rh = ((uint64_t)raw * 100000000) / 16383; + + val->val1 = micro_rh / 1000000; + val->val2 = micro_rh % 1000000; +} + +static int hs300x_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct hs300x_data *data = dev->data; + + if (chan == SENSOR_CHAN_AMBIENT_TEMP) { + hs300x_temp_convert(val, data->t_sample); + } else if (chan == SENSOR_CHAN_HUMIDITY) { + hs300x_rh_convert(val, data->rh_sample); + } else { + return -ENOTSUP; + } + + return 0; +} + +static int hs300x_init(const struct device *dev) +{ + const struct hs300x_config *cfg = dev->config; + + if (!i2c_is_ready_dt(&cfg->bus)) { + LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name); + return -ENODEV; + } + + return 0; +} + +static const struct sensor_driver_api hs300x_driver_api = {.sample_fetch = hs300x_sample_fetch, + .channel_get = hs300x_channel_get}; + +#define DEFINE_HS300X(n) \ + static struct hs300x_data hs300x_data_##n; \ + \ + static const struct hs300x_config hs300x_config_##n = {.bus = I2C_DT_SPEC_INST_GET(n)}; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, hs300x_init, NULL, &hs300x_data_##n, &hs300x_config_##n, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &hs300x_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_HS300X) diff --git a/dts/bindings/sensor/renesas,hs300x.yaml b/dts/bindings/sensor/renesas,hs300x.yaml new file mode 100644 index 000000000000000..cd24b67da74db1c --- /dev/null +++ b/dts/bindings/sensor/renesas,hs300x.yaml @@ -0,0 +1,10 @@ +# +# Copyright (c) 2023 Ian Morris +# +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas HS300x humidity and temperature sensor + +compatible: "renesas,hs300x" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index ae04cc4411258a6..ca79b2e45068bbe 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -793,3 +793,8 @@ test_i2c_adxl367: adxl367@77 { reg = <0x77>; odr = <4>; }; + +test_i2c_hs300x: hs300x@78 { + compatible = "renesas,hs300x"; + reg = <0x78>; +};