drivers: sensor: SHT4X Added support
This adds support for Sensirion's SHT4X temperature and humidity sensor. Signed-off-by: Leonard Pollak <leonardp@tr-host.de>
This commit is contained in:
parent
0d7cb32c58
commit
2d0fd2554a
10 changed files with 400 additions and 0 deletions
|
@ -73,6 +73,7 @@ add_subdirectory_ifdef(CONFIG_SBS_GAUGE sbs_gauge)
|
||||||
add_subdirectory_ifdef(CONFIG_SGP40 sgp40)
|
add_subdirectory_ifdef(CONFIG_SGP40 sgp40)
|
||||||
add_subdirectory_ifdef(CONFIG_SHTCX shtcx)
|
add_subdirectory_ifdef(CONFIG_SHTCX shtcx)
|
||||||
add_subdirectory_ifdef(CONFIG_SHT3XD sht3xd)
|
add_subdirectory_ifdef(CONFIG_SHT3XD sht3xd)
|
||||||
|
add_subdirectory_ifdef(CONFIG_SHT4X sht4x)
|
||||||
add_subdirectory_ifdef(CONFIG_SI7006 si7006)
|
add_subdirectory_ifdef(CONFIG_SI7006 si7006)
|
||||||
add_subdirectory_ifdef(CONFIG_SI7055 si7055)
|
add_subdirectory_ifdef(CONFIG_SI7055 si7055)
|
||||||
add_subdirectory_ifdef(CONFIG_SI7060 si7060)
|
add_subdirectory_ifdef(CONFIG_SI7060 si7060)
|
||||||
|
|
|
@ -186,6 +186,8 @@ source "drivers/sensor/shtcx/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/sht3xd/Kconfig"
|
source "drivers/sensor/sht3xd/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/sensor/sht4x/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/si7006/Kconfig"
|
source "drivers/sensor/si7006/Kconfig"
|
||||||
|
|
||||||
source "drivers/sensor/si7055/Kconfig"
|
source "drivers/sensor/si7055/Kconfig"
|
||||||
|
|
5
drivers/sensor/sht4x/CMakeLists.txt
Normal file
5
drivers/sensor/sht4x/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
zephyr_library()
|
||||||
|
|
||||||
|
zephyr_library_sources(sht4x.c)
|
10
drivers/sensor/sht4x/Kconfig
Normal file
10
drivers/sensor/sht4x/Kconfig
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# SHT4x temperature and humidity sensor configuration options
|
||||||
|
|
||||||
|
# Copyright (c) 2021 Leonard Pollak
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config SHT4X
|
||||||
|
bool "SHT4x Temperature and Humidity Sensor"
|
||||||
|
depends on I2C
|
||||||
|
help
|
||||||
|
Enable driver for SHT4x temperature and humidity sensors.
|
229
drivers/sensor/sht4x/sht4x.c
Normal file
229
drivers/sensor/sht4x/sht4x.c
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Leonard Pollak
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT sensirion_sht4x
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/i2c.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
#include <sys/__assert.h>
|
||||||
|
#include <logging/log.h>
|
||||||
|
#include <sys/byteorder.h>
|
||||||
|
#include <sys/crc.h>
|
||||||
|
|
||||||
|
#include <drivers/sensor/sht4x.h>
|
||||||
|
#include "sht4x.h"
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(SHT4X, CONFIG_SENSOR_LOG_LEVEL);
|
||||||
|
|
||||||
|
static uint8_t sht4x_compute_crc(uint16_t value)
|
||||||
|
{
|
||||||
|
uint8_t buf[2];
|
||||||
|
|
||||||
|
sys_put_be16(value, buf);
|
||||||
|
|
||||||
|
return crc8(buf, 2, SHT4X_CRC_POLY, SHT4X_CRC_INIT, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht4x_write_command(const struct device *dev, uint8_t cmd)
|
||||||
|
{
|
||||||
|
const struct sht4x_config *cfg = dev->config;
|
||||||
|
uint8_t tx_buf[1] = { cmd };
|
||||||
|
|
||||||
|
return i2c_write(cfg->bus, tx_buf, sizeof(tx_buf), cfg->i2c_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht4x_read_sample(const struct device *dev,
|
||||||
|
uint16_t *t_sample,
|
||||||
|
uint16_t *rh_sample)
|
||||||
|
{
|
||||||
|
const struct sht4x_config *cfg = dev->config;
|
||||||
|
uint8_t rx_buf[6];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = i2c_read(cfg->bus, rx_buf, sizeof(rx_buf), cfg->i2c_addr);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to read data from device.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*t_sample = sys_get_be16(rx_buf);
|
||||||
|
if (sht4x_compute_crc(*t_sample) != rx_buf[2]) {
|
||||||
|
LOG_ERR("Invalid CRC for T.");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
*rh_sample = sys_get_be16(&rx_buf[3]);
|
||||||
|
if (sht4x_compute_crc(*rh_sample) != rx_buf[5]) {
|
||||||
|
LOG_ERR("Invalid CRC for RH.");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public API for handling the heater */
|
||||||
|
int sht4x_fetch_with_heater(const struct device *dev)
|
||||||
|
{
|
||||||
|
struct sht4x_data *data = dev->data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = sht4x_write_command(dev,
|
||||||
|
heater_cmd[data->heater_power][data->heater_duration]);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to start measurement.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_MSEC(heater_wait_ms[data->heater_duration]));
|
||||||
|
|
||||||
|
rc = sht4x_read_sample(dev, &data->t_sample, &data->rh_sample);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to fetch data.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht4x_sample_fetch(const struct device *dev,
|
||||||
|
enum sensor_channel chan)
|
||||||
|
{
|
||||||
|
const struct sht4x_config *cfg = dev->config;
|
||||||
|
struct sht4x_data *data = dev->data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (chan != SENSOR_CHAN_ALL &&
|
||||||
|
chan != SENSOR_CHAN_AMBIENT_TEMP &&
|
||||||
|
chan != SENSOR_CHAN_HUMIDITY) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sht4x_write_command(dev, measure_cmd[cfg->repeatability]);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to start measurement.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_USEC(measure_wait_us[cfg->repeatability]));
|
||||||
|
|
||||||
|
rc = sht4x_read_sample(dev, &data->t_sample, &data->rh_sample);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to fetch data.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht4x_channel_get(const struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
struct sensor_value *val)
|
||||||
|
{
|
||||||
|
const struct sht4x_data *data = dev->data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See datasheet "Conversion of Signal Output" section
|
||||||
|
* for more details on processing sample data.
|
||||||
|
*/
|
||||||
|
if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
|
||||||
|
int64_t tmp;
|
||||||
|
|
||||||
|
tmp = data->t_sample * 175;
|
||||||
|
val->val1 = (int32_t)(tmp / 0xFFFF) - 45;
|
||||||
|
val->val2 = ((tmp % 0xFFFF) * 1000000) / 0xFFFF;
|
||||||
|
} else if (chan == SENSOR_CHAN_HUMIDITY) {
|
||||||
|
uint64_t tmp;
|
||||||
|
|
||||||
|
tmp = data->rh_sample * 125U;
|
||||||
|
val->val1 = (uint32_t)(tmp / 0xFFFF) - 6U;
|
||||||
|
val->val2 = (tmp % 0xFFFF) * 15625U / 1024U;
|
||||||
|
} else {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht4x_attr_set(const struct device *dev,
|
||||||
|
enum sensor_channel chan,
|
||||||
|
enum sensor_attribute attr,
|
||||||
|
const struct sensor_value *val)
|
||||||
|
{
|
||||||
|
struct sht4x_data *data = dev->data;
|
||||||
|
|
||||||
|
if (val->val1 < 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((enum sensor_attribute_sht4x)attr) {
|
||||||
|
case SENSOR_ATTR_SHT4X_HEATER_POWER:
|
||||||
|
if (val->val1 > SHT4X_HEATER_POWER_IDX_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
data->heater_power = val->val1;
|
||||||
|
break;
|
||||||
|
case SENSOR_ATTR_SHT4X_HEATER_DURATION:
|
||||||
|
if (val->val1 > SHT4X_HEATER_DURATION_IDX_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
data->heater_duration = val->val1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sht4x_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct sht4x_config *cfg = dev->config;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!device_is_ready(cfg->bus)) {
|
||||||
|
LOG_ERR("Device not ready.");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sht4x_write_command(dev, SHT4X_CMD_RESET);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to reset the device.");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(K_MSEC(SHT4X_RESET_WAIT_MS));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const struct sensor_driver_api sht4x_api = {
|
||||||
|
.sample_fetch = sht4x_sample_fetch,
|
||||||
|
.channel_get = sht4x_channel_get,
|
||||||
|
.attr_set = sht4x_attr_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SHT4X_INIT(n) \
|
||||||
|
static struct sht4x_data sht4x_data_##n; \
|
||||||
|
\
|
||||||
|
static const struct sht4x_config sht4x_config_##n = { \
|
||||||
|
.bus = DEVICE_DT_GET(DT_INST_BUS(n)), \
|
||||||
|
.i2c_addr = DT_INST_REG_ADDR(n), \
|
||||||
|
.repeatability = DT_INST_PROP(n, repeatability) \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(n, \
|
||||||
|
sht4x_init, \
|
||||||
|
NULL, \
|
||||||
|
&sht4x_data_##n, \
|
||||||
|
&sht4x_config_##n, \
|
||||||
|
POST_KERNEL, \
|
||||||
|
CONFIG_SENSOR_INIT_PRIORITY, \
|
||||||
|
&sht4x_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(SHT4X_INIT)
|
71
drivers/sensor/sht4x/sht4x.h
Normal file
71
drivers/sensor/sht4x/sht4x.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021 Leonard Pollak
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_SENSOR_SHT4X_SHT4X_H_
|
||||||
|
#define ZEPHYR_DRIVERS_SENSOR_SHT4X_SHT4X_H_
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
|
||||||
|
#define SHT4X_CMD_READ_SERIAL 0x89
|
||||||
|
#define SHT4X_CMD_RESET 0x94
|
||||||
|
|
||||||
|
#define SHT4X_RESET_WAIT_MS 1
|
||||||
|
|
||||||
|
#define SHT4X_HEATER_POWER_IDX_MAX 3
|
||||||
|
#define SHT4X_HEATER_DURATION_IDX_MAX 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CRC parameters were taken from the
|
||||||
|
* "Checksum Calculation" section of the datasheet.
|
||||||
|
*/
|
||||||
|
#define SHT4X_CRC_POLY 0x31
|
||||||
|
#define SHT4X_CRC_INIT 0xFF
|
||||||
|
|
||||||
|
struct sht4x_config {
|
||||||
|
const struct device *bus;
|
||||||
|
uint8_t i2c_addr;
|
||||||
|
uint8_t repeatability;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sht4x_data {
|
||||||
|
uint16_t t_sample;
|
||||||
|
uint16_t rh_sample;
|
||||||
|
uint8_t heater_power;
|
||||||
|
uint8_t heater_duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t measure_cmd[3] = {
|
||||||
|
0xE0, 0xF6, 0xFD
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint16_t measure_wait_us[3] = {
|
||||||
|
1700, 4500, 8200
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* heater specifics
|
||||||
|
*
|
||||||
|
* power:
|
||||||
|
* High power heater pulse -> ~200 mW @3.3V
|
||||||
|
* Medium power heater pulse -> ~110 mW @3.3V
|
||||||
|
* Low power heater pulse -> ~20 mW @3.3V
|
||||||
|
*
|
||||||
|
* duration:
|
||||||
|
* Long heater pulse -> 1.1s
|
||||||
|
* Short heater pulse -> 0.11s
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const int8_t heater_cmd[SHT4X_HEATER_POWER_IDX_MAX][SHT4X_HEATER_DURATION_IDX_MAX] = {
|
||||||
|
{ 0x39, 0x32 },
|
||||||
|
{ 0x2F, 0x24 },
|
||||||
|
{ 0x1E, 0x15 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint32_t heater_wait_ms[SHT4X_HEATER_DURATION_IDX_MAX] = {
|
||||||
|
1000, 100
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_SENSOR_SHT4X_SHT4X_H_ */
|
24
dts/bindings/sensor/sensirion,sht4x.yaml
Normal file
24
dts/bindings/sensor/sensirion,sht4x.yaml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2021, Leonard Pollak
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: Sensirion SHT4x humidity and temperature sensor
|
||||||
|
|
||||||
|
compatible: "sensirion,sht4x"
|
||||||
|
|
||||||
|
include: i2c-device.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
repeatability:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
Repeatability of the T/RH Measurement
|
||||||
|
0 = low -> 1.7 ms
|
||||||
|
1 = med -> 4.5 ms
|
||||||
|
2 = high -> 8.2 ms
|
||||||
|
enum:
|
||||||
|
- 0
|
||||||
|
- 1
|
||||||
|
- 2
|
50
include/drivers/sensor/sht4x.h
Normal file
50
include/drivers/sensor/sht4x.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Leonard Pollak
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Extended public API for Sensirion's SHT4X T/RH sensors
|
||||||
|
*
|
||||||
|
* This exposes an API to the on-chip heater which is specific to
|
||||||
|
* the application/environment and cannot be expressed within the
|
||||||
|
* sensor driver abstraction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_SHT4X_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_SHT4X_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <drivers/sensor.h>
|
||||||
|
|
||||||
|
/* Maximum teperature above which the heater should not be used */
|
||||||
|
#define SHT4X_HEATER_MAX_TEMP 65
|
||||||
|
|
||||||
|
enum sensor_attribute_sht4x {
|
||||||
|
/* Heater Power: 0, 1, 2 -> high, med, low */
|
||||||
|
SENSOR_ATTR_SHT4X_HEATER_POWER = SENSOR_ATTR_PRIV_START,
|
||||||
|
/* Heater Duration: 0, 1 -> long, short */
|
||||||
|
SENSOR_ATTR_SHT4X_HEATER_DURATION
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fetches data using the on-chip heater.
|
||||||
|
*
|
||||||
|
* Measurement is always done with "high" repeatability.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the sensor device
|
||||||
|
*
|
||||||
|
* @return 0 if successful, negative errno code if failure.
|
||||||
|
*/
|
||||||
|
int sht4x_fetch_with_heater(const struct device *dev);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_SHT4X_H_ */
|
|
@ -244,6 +244,13 @@ test_i2c_sht3xd: sht3xd@23 {
|
||||||
alert-gpios = <&test_gpio 0 0>;
|
alert-gpios = <&test_gpio 0 0>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
test_i2c_sht4xd: sht4x@44 {
|
||||||
|
compatible = "sensirion,sht4x";
|
||||||
|
reg = <0x44>;
|
||||||
|
label = "SHT4X";
|
||||||
|
repeatability = <2>;
|
||||||
|
};
|
||||||
|
|
||||||
test_i2c_shtc3: SHTC3@70 {
|
test_i2c_shtc3: SHTC3@70 {
|
||||||
compatible = "sensirion,shtcx";
|
compatible = "sensirion,shtcx";
|
||||||
label = "SHTC3";
|
label = "SHTC3";
|
||||||
|
|
|
@ -75,6 +75,7 @@ CONFIG_OPT3001=y
|
||||||
CONFIG_SBS_GAUGE=y
|
CONFIG_SBS_GAUGE=y
|
||||||
CONFIG_SGP40=y
|
CONFIG_SGP40=y
|
||||||
CONFIG_SHT3XD=y
|
CONFIG_SHT3XD=y
|
||||||
|
CONFIG_SHT4X=y
|
||||||
CONFIG_SHTCX=y
|
CONFIG_SHTCX=y
|
||||||
CONFIG_SI7006=y
|
CONFIG_SI7006=y
|
||||||
CONFIG_SI7055=y
|
CONFIG_SI7055=y
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue