Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: sensor: hs300x: Add driver for Renesas HS300x sensors
Adds support for Renesas HS3001 and HS3003 temperature/humidity sensors connected via an I2C bus. Signed-off-by: Ian Morris <ian.d.morris@outlook.com>
- Loading branch information
1 parent
e734028
commit a322208
Showing
7 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
zephyr_library() | ||
|
||
zephyr_library_sources(hs300x.c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* | ||
* Copyright (c) 2023 Ian Morris | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT renesas_hs300x | ||
|
||
#include <zephyr/device.h> | ||
#include <zephyr/drivers/i2c.h> | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/drivers/sensor.h> | ||
#include <zephyr/sys/__assert.h> | ||
#include <zephyr/logging/log.h> | ||
#include <zephyr/sys/byteorder.h> | ||
|
||
#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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters