Skip to content

Commit 3920294

Browse files
clementlglcfriedt
authored andcommitted
drivers: sensor: add support for OMRON 2SMPB_02E pressure sensor
Support for the OMRON 2SMPB_02E digital barometric pressure sensor. Signed-off-by: Clément Laigle <[email protected]>
1 parent df4f704 commit 3920294

File tree

6 files changed

+260
-0
lines changed

6 files changed

+260
-0
lines changed
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
* Copyright (c) 2025 CATIE
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT omron_2smpb_02e
8+
9+
#include <zephyr/drivers/i2c.h>
10+
#include <zephyr/drivers/sensor.h>
11+
#include <zephyr/logging/log.h>
12+
13+
LOG_MODULE_REGISTER(O2SMPB_02E, CONFIG_SENSOR_LOG_LEVEL);
14+
15+
/*
16+
* Calibration coefficients for the Omron 2SMPB-02E sensor.
17+
*
18+
* These coefficients are used in the sensor's compensation algorithm to
19+
* convert raw temperature and pressure readings into calibrated values.
20+
* The values are derived from the sensor's datasheet.
21+
*
22+
* Reference: Omron 2SMPB-02E Application Note / Datasheet.
23+
*/
24+
#define COEFFICIENT_A1_A -6.3E-03
25+
#define COEFFICIENT_A1_S 4.3E-04
26+
#define COEFFICIENT_A2_A -1.9E-11
27+
#define COEFFICIENT_A2_S 1.2E-10
28+
#define COEFFICIENT_BT1_A 1.0E-01
29+
#define COEFFICIENT_BT1_S 9.1E-02
30+
#define COEFFICIENT_BT2_A 1.2E-08
31+
#define COEFFICIENT_BT2_S 1.2E-06
32+
#define COEFFICIENT_BP1_A 3.3E-02
33+
#define COEFFICIENT_BP1_S 1.9E-02
34+
#define COEFFICIENT_B11_A 2.1E-07
35+
#define COEFFICIENT_B11_S 1.4E-07
36+
#define COEFFICIENT_BP2_A -6.3E-10
37+
#define COEFFICIENT_BP2_S 3.5E-10
38+
#define COEFFICIENT_B12_A 2.9E-13
39+
#define COEFFICIENT_B12_S 7.6E-13
40+
#define COEFFICIENT_B21_A 2.1E-15
41+
#define COEFFICIENT_B21_S 1.2E-14
42+
#define COEFFICIENT_BP3_A 1.3E-16
43+
#define COEFFICIENT_BP3_S 7.9E-17
44+
45+
#define U20TOS32(x) (-(x & 0x00080000) + (x & 0xFFF7FFFF))
46+
#define U16TOS16(x) (-(x & 0x8000) | (x & 0x7FFF))
47+
48+
#define O2SMPB_02_REG_TEMP_TXD0 0xFC
49+
#define O2SMPB_02_REG_TEMP_TXD1 0xFB
50+
#define O2SMPB_02_REG_TEMP_TXD2 0xFA
51+
#define O2SMPB_02_REG_PRESS_TXD0 0xF9
52+
#define O2SMPB_02_REG_PRESS_TXD1 0xF8
53+
#define O2SMPB_02_REG_PRESS_TXD2 0xF7
54+
#define O2SMPB_02_REG_RESET 0xE0
55+
#define O2SMPB_02_REG_CTRL_MEAS 0xF4
56+
#define O2SMPB_02_REG_CHIP_ID 0xD1
57+
#define O2SMPB_02_REG_COE_b00_1 0xA0
58+
59+
#define CALC_COEFF(A, S, OTP) ((A) + ((S) * (OTP) / 32767.0))
60+
61+
struct o2smpb_02e_config {
62+
struct i2c_dt_spec i2c;
63+
};
64+
65+
struct o2smpb_02e_data {
66+
int32_t b00;
67+
int32_t a0;
68+
float bt1;
69+
float bp1;
70+
float bt2;
71+
float b11;
72+
float bp2;
73+
float b12;
74+
float b21;
75+
float bp3;
76+
float a1;
77+
float a2;
78+
int32_t dt;
79+
int32_t dp;
80+
};
81+
82+
static int o2smpb_02e_read_coefficients(const struct device *dev)
83+
{
84+
struct o2smpb_02e_data *data = dev->data;
85+
const struct o2smpb_02e_config *config = dev->config;
86+
uint8_t buffer[25];
87+
88+
if (i2c_burst_read_dt(&config->i2c, O2SMPB_02_REG_COE_b00_1, buffer, sizeof(buffer)) < 0) {
89+
LOG_ERR("Failed to read coefficients");
90+
return -EIO;
91+
}
92+
93+
/* K = OTP / 16 */
94+
data->a0 =
95+
(int32_t)U20TOS32((buffer[18] << 12 | buffer[19] << 4 | (buffer[24] & 0x0F))) >> 4;
96+
data->b00 =
97+
(int32_t)U20TOS32((buffer[0] << 12 | buffer[1] << 4 | (buffer[24] & 0xF0) >> 4)) >>
98+
4;
99+
100+
/* K = A + (S * OTP) / 32767 */
101+
int16_t bt1 = U16TOS16((buffer[2] << 8 | buffer[3]));
102+
int16_t bp1 = U16TOS16((buffer[6] << 8 | buffer[7]));
103+
int16_t bt2 = U16TOS16((buffer[4] << 8 | buffer[5]));
104+
int16_t b11 = U16TOS16((buffer[8] << 8 | buffer[9]));
105+
int16_t bp2 = U16TOS16((buffer[10] << 8 | buffer[11]));
106+
int16_t b12 = U16TOS16((buffer[12] << 8 | buffer[13]));
107+
int16_t b21 = U16TOS16((buffer[14] << 8 | buffer[15]));
108+
int16_t bp3 = U16TOS16((buffer[16] << 8 | buffer[17]));
109+
int16_t a1 = U16TOS16((buffer[20] << 8 | buffer[21]));
110+
int16_t a2 = U16TOS16((buffer[22] << 8 | buffer[23]));
111+
112+
data->bt1 = CALC_COEFF(COEFFICIENT_BT1_A, COEFFICIENT_BT1_S, bt1);
113+
data->bp1 = CALC_COEFF(COEFFICIENT_BP1_A, COEFFICIENT_BP1_S, bp1);
114+
data->bt2 = CALC_COEFF(COEFFICIENT_BT2_A, COEFFICIENT_BT2_S, bt2);
115+
data->b11 = CALC_COEFF(COEFFICIENT_B11_A, COEFFICIENT_B11_S, b11);
116+
data->bp2 = CALC_COEFF(COEFFICIENT_BP2_A, COEFFICIENT_BP2_S, bp2);
117+
data->b12 = CALC_COEFF(COEFFICIENT_B12_A, COEFFICIENT_B12_S, b12);
118+
data->b21 = CALC_COEFF(COEFFICIENT_B21_A, COEFFICIENT_B21_S, b21);
119+
data->bp3 = CALC_COEFF(COEFFICIENT_BP3_A, COEFFICIENT_BP3_S, bp3);
120+
data->a1 = CALC_COEFF(COEFFICIENT_A1_A, COEFFICIENT_A1_S, a1);
121+
data->a2 = CALC_COEFF(COEFFICIENT_A2_A, COEFFICIENT_A2_S, a2);
122+
123+
return 0;
124+
}
125+
126+
static int o2smpb_02e_sample_fetch(const struct device *dev, enum sensor_channel chan)
127+
{
128+
struct o2smpb_02e_data *data = dev->data;
129+
const struct o2smpb_02e_config *config = dev->config;
130+
131+
uint8_t buffer[3];
132+
133+
/* Force mode */
134+
if (i2c_reg_write_byte_dt(&config->i2c, O2SMPB_02_REG_CTRL_MEAS,
135+
(uint8_t)(0x101 << 5 | 0x101 << 2 | 0x1)) < 0) {
136+
LOG_ERR("Could not set sensor to force mode");
137+
return -EIO;
138+
}
139+
140+
k_sleep(K_MSEC(500));
141+
142+
if (i2c_burst_read_dt(&config->i2c, O2SMPB_02_REG_TEMP_TXD2, buffer, sizeof(buffer)) < 0) {
143+
LOG_ERR("Could not read sensor data");
144+
return -EIO;
145+
}
146+
147+
data->dt = (buffer[0] << 16 | buffer[1] << 8 | buffer[2]) - (0x1 << 23);
148+
149+
if (i2c_burst_read_dt(&config->i2c, O2SMPB_02_REG_PRESS_TXD2, buffer, sizeof(buffer)) < 0) {
150+
LOG_ERR("Could not read sensor data");
151+
return -EIO;
152+
}
153+
154+
data->dp = (buffer[0] << 16 | buffer[1] << 8 | buffer[2]) - (0x1 << 23);
155+
156+
return 0;
157+
}
158+
159+
static int o2smpb_02e_channel_get(const struct device *dev, enum sensor_channel chan,
160+
struct sensor_value *val)
161+
{
162+
struct o2smpb_02e_data *data = dev->data;
163+
164+
switch (chan) {
165+
case SENSOR_CHAN_AMBIENT_TEMP:
166+
float temp =
167+
(data->a0) + ((data->a1) + (data->a2) * (float)data->dt) * (float)data->dt;
168+
temp /= 256.0f;
169+
170+
sensor_value_from_float(val, temp);
171+
break;
172+
case SENSOR_CHAN_PRESS:
173+
float tr =
174+
(data->a0) + ((data->a1) + (data->a2) * (float)data->dt) * (float)data->dt;
175+
176+
float press = data->b00 + data->bt1 * tr + data->bp1 * (float)data->dp +
177+
data->b11 * (float)data->dp * tr + data->bt2 * tr * tr +
178+
data->bp2 * (float)data->dp * (float)data->dp +
179+
data->b12 * (float)data->dp * tr * tr +
180+
data->b21 * (float)data->dp * (float)data->dp * tr +
181+
data->bp3 * (float)data->dp * (float)data->dp * (float)data->dp;
182+
press /= 1000.0f;
183+
184+
sensor_value_from_float(val, press);
185+
break;
186+
default:
187+
return -ENOTSUP;
188+
}
189+
190+
return 0;
191+
}
192+
193+
static int o2smpb_02e_init(const struct device *dev)
194+
{
195+
const struct o2smpb_02e_config *config = dev->config;
196+
uint8_t chip_id;
197+
198+
/* Reset the sensor */
199+
i2c_reg_write_byte_dt(&config->i2c, O2SMPB_02_REG_RESET, 0xE6);
200+
201+
k_sleep(K_MSEC(10));
202+
203+
/* Read CHIP ID register to make sure the device is present */
204+
i2c_reg_read_byte_dt(&config->i2c, O2SMPB_02_REG_CHIP_ID, &chip_id);
205+
206+
if (chip_id != 0x5C) {
207+
LOG_ERR("Invalid chip ID");
208+
return -EIO;
209+
}
210+
211+
if (o2smpb_02e_read_coefficients(dev) < 0) {
212+
LOG_ERR("Failed to read calibration coefficients");
213+
return -EIO;
214+
}
215+
216+
return 0;
217+
}
218+
219+
static DEVICE_API(sensor, o2smpb_02e_api_funcs) = {
220+
.sample_fetch = o2smpb_02e_sample_fetch,
221+
.channel_get = o2smpb_02e_channel_get,
222+
};
223+
224+
#define O2SMPB_02E_INIT(n) \
225+
static const struct o2smpb_02e_config o2smpb_02e_config_##n = { \
226+
.i2c = I2C_DT_SPEC_INST_GET(n), \
227+
}; \
228+
static struct o2smpb_02e_data o2smpb_02e_data_##n; \
229+
SENSOR_DEVICE_DT_INST_DEFINE(n, o2smpb_02e_init, NULL, &o2smpb_02e_data_##n, \
230+
&o2smpb_02e_config_##n, POST_KERNEL, \
231+
CONFIG_SENSOR_INIT_PRIORITY, &o2smpb_02e_api_funcs);
232+
233+
DT_INST_FOREACH_STATUS_OKAY(O2SMPB_02E_INIT)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2025 CATIE
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
6+
zephyr_library_sources(2smpb_02e.c)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Copyright (c) 2025 CATIE
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config 2SMPB_02E
5+
bool "OMRON 2SMPB_02E digital barometric pressure sensor"
6+
default y
7+
depends on DT_HAS_OMRON_2SMPB_02E_ENABLED
8+
select I2C
9+
help
10+
Enable driver for OMRON O2SMPB_02E digital barometric pressure sensor.

drivers/sensor/omron/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# zephyr-keep-sorted-start
5+
add_subdirectory_ifdef(CONFIG_2SMPB_02E 2smpb_02e)
56
add_subdirectory_ifdef(CONFIG_D6F d6f)
67
# zephyr-keep-sorted-stop

drivers/sensor/omron/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
# zephyr-keep-sorted-start
5+
source "drivers/sensor/omron/2smpb_02e/Kconfig"
56
source "drivers/sensor/omron/d6f/Kconfig"
67
# zephyr-keep-sorted-stop
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2025 CATIE
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
Omron 2SMPB-02E digital barometric pressure sensor.
6+
7+
compatible: "omron,2smpb-02e"
8+
9+
include: [sensor-device.yaml, i2c-device.yaml]

0 commit comments

Comments
 (0)