Skip to content

Commit 6db870d

Browse files
committed
drivers: sensor: STS4x Add driver
This adds support for Sensirion's STS4x temperature sensor. Signed-off-by: Jan Faeh <[email protected]>
1 parent e1389fa commit 6db870d

File tree

7 files changed

+216
-0
lines changed

7 files changed

+216
-0
lines changed

drivers/sensor/sensirion/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ add_subdirectory_ifdef(CONFIG_SGP40 sgp40)
66
add_subdirectory_ifdef(CONFIG_SHT3XD sht3xd)
77
add_subdirectory_ifdef(CONFIG_SHT4X sht4x)
88
add_subdirectory_ifdef(CONFIG_SHTCX shtcx)
9+
add_subdirectory_ifdef(CONFIG_STS4X sts4x)
910
# zephyr-keep-sorted-stop

drivers/sensor/sensirion/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ source "drivers/sensor/sensirion/sgp40/Kconfig"
66
source "drivers/sensor/sensirion/sht3xd/Kconfig"
77
source "drivers/sensor/sensirion/sht4x/Kconfig"
88
source "drivers/sensor/sensirion/shtcx/Kconfig"
9+
source "drivers/sensor/sensirion/sts4x/Kconfig"
910
# zephyr-keep-sorted-stop
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
zephyr_library()
4+
5+
zephyr_library_sources(sts4x.c)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Drivers configuration options for Sensirion STS4x
2+
3+
# Copyright (c) 2024 Jan Fäh
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
config STS4X
7+
bool "STS4x Temperature Sensor"
8+
default y
9+
depends on DT_HAS_SENSIRION_STS4X_ENABLED
10+
select I2C
11+
select CRC
12+
help
13+
Enable driver for the Sensirion STS4x temperature sensors.
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright (c) 2024 Jan Fäh
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT sensirion_sts4x
8+
9+
#include <zephyr/device.h>
10+
#include <zephyr/kernel.h>
11+
#include <zephyr/drivers/sensor.h>
12+
#include <zephyr/drivers/i2c.h>
13+
#include <zephyr/logging/log.h>
14+
#include <zephyr/sys/__assert.h>
15+
#include <zephyr/sys/byteorder.h>
16+
#include <zephyr/sys/crc.h>
17+
#include <zephyr/devicetree.h>
18+
19+
LOG_MODULE_REGISTER(STS4X, CONFIG_SENSOR_LOG_LEVEL);
20+
21+
#define STS4X_CMD_RESET 0x94
22+
23+
#define STS4X_RESET_TIME 1
24+
25+
#define STS4X_CRC_POLY 0x31
26+
#define STS4X_CRC_INIT 0xFF
27+
28+
#define STS4X_MAX_TEMP 175
29+
#define STS4X_MIN_TEMP -45
30+
31+
struct sts4x_config {
32+
struct i2c_dt_spec bus;
33+
uint8_t repeatability;
34+
};
35+
36+
struct sts4x_data {
37+
uint16_t temp_sample;
38+
};
39+
40+
static const uint8_t measure_cmds[3] = {0xE0, 0xF6, 0xFD};
41+
static const uint16_t measure_time_us[3] = {1600, 4500, 8300};
42+
43+
static int sts4x_crc_check(uint16_t value, uint8_t sensor_crc)
44+
{
45+
uint8_t buf[2];
46+
47+
sys_put_be16(value, buf);
48+
49+
uint8_t calculated_crc = crc8(buf, 2, STS4X_CRC_POLY, STS4X_CRC_INIT, false);
50+
51+
if (calculated_crc == sensor_crc) {
52+
return 0;
53+
}
54+
55+
return -EIO;
56+
}
57+
58+
static int sts4x_write_command(const struct device *dev, uint8_t cmd)
59+
{
60+
const struct sts4x_config *cfg = dev->config;
61+
uint8_t tx_buf = cmd;
62+
63+
return i2c_write_dt(&cfg->bus, &tx_buf, 1);
64+
}
65+
66+
static int sts4x_read_sample(const struct device *dev, uint16_t *temp_sample)
67+
{
68+
const struct sts4x_config *cfg = dev->config;
69+
uint8_t rx_buf[3];
70+
int ret;
71+
72+
ret = i2c_read_dt(&cfg->bus, rx_buf, sizeof(rx_buf));
73+
if (ret < 0) {
74+
LOG_ERR("Failed to read data.");
75+
return ret;
76+
}
77+
78+
*temp_sample = sys_get_be16(rx_buf);
79+
ret = sts4x_crc_check(*temp_sample, rx_buf[2]);
80+
if (ret < 0) {
81+
LOG_ERR("Invalid CRC.");
82+
return ret;
83+
}
84+
85+
return 0;
86+
}
87+
88+
static int sts4x_sample_fetch(const struct device *dev, enum sensor_channel chan)
89+
{
90+
struct sts4x_data *data = dev->data;
91+
const struct sts4x_config *cfg = dev->config;
92+
int ret;
93+
94+
if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP) {
95+
ret = sts4x_write_command(dev, measure_cmds[cfg->repeatability]);
96+
if (ret < 0) {
97+
LOG_ERR("Failed to write measure command.");
98+
return ret;
99+
}
100+
101+
k_usleep(measure_time_us[cfg->repeatability]);
102+
103+
ret = sts4x_read_sample(dev, &data->temp_sample);
104+
if (ret < 0) {
105+
LOG_ERR("Failed to get temperature data.");
106+
return ret;
107+
}
108+
109+
return 0;
110+
} else {
111+
return -ENOTSUP;
112+
}
113+
}
114+
115+
static int sts4x_channel_get(const struct device *dev, enum sensor_channel chan,
116+
struct sensor_value *val)
117+
{
118+
const struct sts4x_data *data = dev->data;
119+
120+
if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
121+
int64_t temp;
122+
123+
temp = data->temp_sample * STS4X_MAX_TEMP;
124+
val->val1 = (int32_t)(temp / 0xFFFF) + STS4X_MIN_TEMP;
125+
val->val2 = ((temp % 0xFFFF) * 1000000) / 0xFFFF;
126+
} else {
127+
return -ENOTSUP;
128+
}
129+
return 0;
130+
}
131+
132+
static int sts4x_init(const struct device *dev)
133+
{
134+
const struct sts4x_config *cfg = dev->config;
135+
int ret;
136+
137+
if (!i2c_is_ready_dt(&cfg->bus)) {
138+
LOG_ERR("Device not ready.");
139+
return -ENODEV;
140+
}
141+
142+
ret = sts4x_write_command(dev, STS4X_CMD_RESET);
143+
if (ret < 0) {
144+
LOG_ERR("Failed to reset the device.");
145+
return ret;
146+
}
147+
148+
k_msleep(STS4X_RESET_TIME);
149+
150+
return 0;
151+
}
152+
153+
static const struct sensor_driver_api sts4x_api_funcs = {
154+
.sample_fetch = sts4x_sample_fetch,
155+
.channel_get = sts4x_channel_get,
156+
};
157+
158+
#define STS4X_INIT(inst) \
159+
static struct sts4x_data sts4x_data_##inst; \
160+
static const struct sts4x_config sts4x_config_##inst = { \
161+
.bus = I2C_DT_SPEC_INST_GET(inst), \
162+
.repeatability = DT_INST_PROP(inst, repeatability), \
163+
}; \
164+
SENSOR_DEVICE_DT_INST_DEFINE(inst, sts4x_init, NULL, &sts4x_data_##inst, \
165+
&sts4x_config_##inst, POST_KERNEL, \
166+
CONFIG_SENSOR_INIT_PRIORITY, &sts4x_api_funcs);
167+
168+
DT_INST_FOREACH_STATUS_OKAY(STS4X_INIT)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2024, Jan Fäh
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Sensirion STS4x temperature sensor
5+
6+
compatible: "sensirion,sts4x"
7+
8+
include: [sensor-device.yaml, i2c-device.yaml]
9+
10+
properties:
11+
repeatability:
12+
type: int
13+
required: true
14+
description: |
15+
Repeatability of the T Measurement
16+
0 = low -> 1.6 ms
17+
1 = med -> 4.5 ms
18+
2 = high -> 8.3 ms
19+
enum:
20+
- 0
21+
- 1
22+
- 2

tests/drivers/build_all/sensor/i2c.dtsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,3 +1125,9 @@ test_i2c_ilps22qs: ilps22qs@9c {
11251125
avg = <LPS2xDF_DT_AVG_128_SAMPLES>;
11261126
fs = <ILPS22QS_DT_FS_MODE_1_1260>;
11271127
};
1128+
1129+
test_i2c_sts4x: sts4x@9d {
1130+
compatible = "sensirion,sts4x";
1131+
reg = <0x99>;
1132+
repeatability = <2>;
1133+
};

0 commit comments

Comments
 (0)