-
Notifications
You must be signed in to change notification settings - Fork 8.1k
driver: sensor: Add Omron 2SMPB-02E digital barometric pressure sensor #96284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or 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,233 @@ | ||
/* | ||
* Copyright (c) 2025 CATIE | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT omron_2smpb_02e | ||
|
||
#include <zephyr/drivers/i2c.h> | ||
#include <zephyr/drivers/sensor.h> | ||
#include <zephyr/logging/log.h> | ||
|
||
LOG_MODULE_REGISTER(O2SMPB_02E, CONFIG_SENSOR_LOG_LEVEL); | ||
|
||
/* | ||
* Calibration coefficients for the Omron 2SMPB-02E sensor. | ||
* | ||
* These coefficients are used in the sensor's compensation algorithm to | ||
* convert raw temperature and pressure readings into calibrated values. | ||
* The values are derived from the sensor's datasheet. | ||
* | ||
* Reference: Omron 2SMPB-02E Application Note / Datasheet. | ||
*/ | ||
#define COEFFICIENT_A1_A -6.3E-03 | ||
#define COEFFICIENT_A1_S 4.3E-04 | ||
#define COEFFICIENT_A2_A -1.9E-11 | ||
#define COEFFICIENT_A2_S 1.2E-10 | ||
#define COEFFICIENT_BT1_A 1.0E-01 | ||
#define COEFFICIENT_BT1_S 9.1E-02 | ||
#define COEFFICIENT_BT2_A 1.2E-08 | ||
#define COEFFICIENT_BT2_S 1.2E-06 | ||
#define COEFFICIENT_BP1_A 3.3E-02 | ||
#define COEFFICIENT_BP1_S 1.9E-02 | ||
#define COEFFICIENT_B11_A 2.1E-07 | ||
#define COEFFICIENT_B11_S 1.4E-07 | ||
#define COEFFICIENT_BP2_A -6.3E-10 | ||
#define COEFFICIENT_BP2_S 3.5E-10 | ||
#define COEFFICIENT_B12_A 2.9E-13 | ||
#define COEFFICIENT_B12_S 7.6E-13 | ||
#define COEFFICIENT_B21_A 2.1E-15 | ||
#define COEFFICIENT_B21_S 1.2E-14 | ||
#define COEFFICIENT_BP3_A 1.3E-16 | ||
#define COEFFICIENT_BP3_S 7.9E-17 | ||
|
||
#define U20TOS32(x) (-(x & 0x00080000) + (x & 0xFFF7FFFF)) | ||
#define U16TOS16(x) (-(x & 0x8000) | (x & 0x7FFF)) | ||
|
||
#define O2SMPB_02_REG_TEMP_TXD0 0xFC | ||
#define O2SMPB_02_REG_TEMP_TXD1 0xFB | ||
#define O2SMPB_02_REG_TEMP_TXD2 0xFA | ||
#define O2SMPB_02_REG_PRESS_TXD0 0xF9 | ||
#define O2SMPB_02_REG_PRESS_TXD1 0xF8 | ||
#define O2SMPB_02_REG_PRESS_TXD2 0xF7 | ||
#define O2SMPB_02_REG_RESET 0xE0 | ||
#define O2SMPB_02_REG_CTRL_MEAS 0xF4 | ||
#define O2SMPB_02_REG_CHIP_ID 0xD1 | ||
#define O2SMPB_02_REG_COE_b00_1 0xA0 | ||
|
||
#define CALC_COEFF(A, S, OTP) ((A) + ((S) * (OTP) / 32767.0)) | ||
|
||
struct o2smpb_02e_config { | ||
struct i2c_dt_spec i2c; | ||
}; | ||
|
||
struct o2smpb_02e_data { | ||
int32_t b00; | ||
int32_t a0; | ||
float bt1; | ||
float bp1; | ||
float bt2; | ||
float b11; | ||
float bp2; | ||
float b12; | ||
float b21; | ||
float bp3; | ||
float a1; | ||
float a2; | ||
int32_t dt; | ||
int32_t dp; | ||
}; | ||
|
||
static int o2smpb_02e_read_coefficients(const struct device *dev) | ||
{ | ||
struct o2smpb_02e_data *data = dev->data; | ||
const struct o2smpb_02e_config *config = dev->config; | ||
uint8_t buffer[25]; | ||
|
||
if (i2c_burst_read_dt(&config->i2c, O2SMPB_02_REG_COE_b00_1, buffer, sizeof(buffer)) < 0) { | ||
LOG_ERR("Failed to read coefficients"); | ||
return -EIO; | ||
} | ||
|
||
/* K = OTP / 16 */ | ||
data->a0 = | ||
(int32_t)U20TOS32((buffer[18] << 12 | buffer[19] << 4 | (buffer[24] & 0x0F))) >> 4; | ||
data->b00 = | ||
(int32_t)U20TOS32((buffer[0] << 12 | buffer[1] << 4 | (buffer[24] & 0xF0) >> 4)) >> | ||
4; | ||
|
||
/* K = A + (S * OTP) / 32767 */ | ||
int16_t bt1 = U16TOS16((buffer[2] << 8 | buffer[3])); | ||
int16_t bp1 = U16TOS16((buffer[6] << 8 | buffer[7])); | ||
int16_t bt2 = U16TOS16((buffer[4] << 8 | buffer[5])); | ||
int16_t b11 = U16TOS16((buffer[8] << 8 | buffer[9])); | ||
int16_t bp2 = U16TOS16((buffer[10] << 8 | buffer[11])); | ||
int16_t b12 = U16TOS16((buffer[12] << 8 | buffer[13])); | ||
int16_t b21 = U16TOS16((buffer[14] << 8 | buffer[15])); | ||
int16_t bp3 = U16TOS16((buffer[16] << 8 | buffer[17])); | ||
int16_t a1 = U16TOS16((buffer[20] << 8 | buffer[21])); | ||
int16_t a2 = U16TOS16((buffer[22] << 8 | buffer[23])); | ||
|
||
data->bt1 = CALC_COEFF(COEFFICIENT_BT1_A, COEFFICIENT_BT1_S, bt1); | ||
data->bp1 = CALC_COEFF(COEFFICIENT_BP1_A, COEFFICIENT_BP1_S, bp1); | ||
data->bt2 = CALC_COEFF(COEFFICIENT_BT2_A, COEFFICIENT_BT2_S, bt2); | ||
data->b11 = CALC_COEFF(COEFFICIENT_B11_A, COEFFICIENT_B11_S, b11); | ||
data->bp2 = CALC_COEFF(COEFFICIENT_BP2_A, COEFFICIENT_BP2_S, bp2); | ||
data->b12 = CALC_COEFF(COEFFICIENT_B12_A, COEFFICIENT_B12_S, b12); | ||
data->b21 = CALC_COEFF(COEFFICIENT_B21_A, COEFFICIENT_B21_S, b21); | ||
data->bp3 = CALC_COEFF(COEFFICIENT_BP3_A, COEFFICIENT_BP3_S, bp3); | ||
data->a1 = CALC_COEFF(COEFFICIENT_A1_A, COEFFICIENT_A1_S, a1); | ||
data->a2 = CALC_COEFF(COEFFICIENT_A2_A, COEFFICIENT_A2_S, a2); | ||
|
||
return 0; | ||
} | ||
|
||
static int o2smpb_02e_sample_fetch(const struct device *dev, enum sensor_channel chan) | ||
{ | ||
struct o2smpb_02e_data *data = dev->data; | ||
const struct o2smpb_02e_config *config = dev->config; | ||
|
||
uint8_t buffer[3]; | ||
|
||
/* Force mode */ | ||
if (i2c_reg_write_byte_dt(&config->i2c, O2SMPB_02_REG_CTRL_MEAS, | ||
(uint8_t)(0x101 << 5 | 0x101 << 2 | 0x1)) < 0) { | ||
LOG_ERR("Could not set sensor to force mode"); | ||
return -EIO; | ||
} | ||
|
||
k_sleep(K_MSEC(500)); | ||
|
||
if (i2c_burst_read_dt(&config->i2c, O2SMPB_02_REG_TEMP_TXD2, buffer, sizeof(buffer)) < 0) { | ||
LOG_ERR("Could not read sensor data"); | ||
return -EIO; | ||
} | ||
|
||
data->dt = (buffer[0] << 16 | buffer[1] << 8 | buffer[2]) - (0x1 << 23); | ||
|
||
if (i2c_burst_read_dt(&config->i2c, O2SMPB_02_REG_PRESS_TXD2, buffer, sizeof(buffer)) < 0) { | ||
LOG_ERR("Could not read sensor data"); | ||
return -EIO; | ||
} | ||
|
||
data->dp = (buffer[0] << 16 | buffer[1] << 8 | buffer[2]) - (0x1 << 23); | ||
|
||
return 0; | ||
} | ||
|
||
static int o2smpb_02e_channel_get(const struct device *dev, enum sensor_channel chan, | ||
struct sensor_value *val) | ||
{ | ||
struct o2smpb_02e_data *data = dev->data; | ||
|
||
switch (chan) { | ||
case SENSOR_CHAN_AMBIENT_TEMP: | ||
float temp = | ||
(data->a0) + ((data->a1) + (data->a2) * (float)data->dt) * (float)data->dt; | ||
temp /= 256.0f; | ||
|
||
sensor_value_from_float(val, temp); | ||
break; | ||
case SENSOR_CHAN_PRESS: | ||
float tr = | ||
(data->a0) + ((data->a1) + (data->a2) * (float)data->dt) * (float)data->dt; | ||
|
||
float press = data->b00 + data->bt1 * tr + data->bp1 * (float)data->dp + | ||
data->b11 * (float)data->dp * tr + data->bt2 * tr * tr + | ||
data->bp2 * (float)data->dp * (float)data->dp + | ||
data->b12 * (float)data->dp * tr * tr + | ||
data->b21 * (float)data->dp * (float)data->dp * tr + | ||
data->bp3 * (float)data->dp * (float)data->dp * (float)data->dp; | ||
press /= 1000.0f; | ||
|
||
sensor_value_from_float(val, press); | ||
break; | ||
default: | ||
return -ENOTSUP; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int o2smpb_02e_init(const struct device *dev) | ||
{ | ||
const struct o2smpb_02e_config *config = dev->config; | ||
uint8_t chip_id; | ||
|
||
/* Reset the sensor */ | ||
i2c_reg_write_byte_dt(&config->i2c, O2SMPB_02_REG_RESET, 0xE6); | ||
|
||
k_sleep(K_MSEC(10)); | ||
|
||
/* Read CHIP ID register to make sure the device is present */ | ||
i2c_reg_read_byte_dt(&config->i2c, O2SMPB_02_REG_CHIP_ID, &chip_id); | ||
|
||
if (chip_id != 0x5C) { | ||
LOG_ERR("Invalid chip ID"); | ||
return -EIO; | ||
} | ||
|
||
if (o2smpb_02e_read_coefficients(dev) < 0) { | ||
LOG_ERR("Failed to read calibration coefficients"); | ||
return -EIO; | ||
MaureenHelm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
return 0; | ||
} | ||
|
||
static DEVICE_API(sensor, o2smpb_02e_api_funcs) = { | ||
.sample_fetch = o2smpb_02e_sample_fetch, | ||
.channel_get = o2smpb_02e_channel_get, | ||
}; | ||
|
||
#define O2SMPB_02E_INIT(n) \ | ||
static const struct o2smpb_02e_config o2smpb_02e_config_##n = { \ | ||
.i2c = I2C_DT_SPEC_INST_GET(n), \ | ||
}; \ | ||
static struct o2smpb_02e_data o2smpb_02e_data_##n; \ | ||
SENSOR_DEVICE_DT_INST_DEFINE(n, o2smpb_02e_init, NULL, &o2smpb_02e_data_##n, \ | ||
&o2smpb_02e_config_##n, POST_KERNEL, \ | ||
CONFIG_SENSOR_INIT_PRIORITY, &o2smpb_02e_api_funcs); | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(O2SMPB_02E_INIT) |
This file contains hidden or 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,6 @@ | ||
# Copyright (c) 2025 CATIE | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
zephyr_library() | ||
|
||
zephyr_library_sources(2smpb_02e.c) |
This file contains hidden or 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,11 @@ | ||
# Copyright (c) 2025 CATIE | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config 2SMPB_02E | ||
bool "OMRON 2SMPB_02E digital barometric pressure sensor" | ||
default y | ||
depends on DT_HAS_OMRON_2SMPB_02E_ENABLED | ||
select I2C | ||
select FPU if CPU_HAS_FPU | ||
help | ||
Enable driver for OMRON O2SMPB_02E digital barometric pressure sensor. |
This file contains hidden or 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 hidden or 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 hidden or 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,9 @@ | ||
# Copyright (c) 2025 CATIE | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: | | ||
Omron 2SMPB-02E digital barometric pressure sensor. | ||
|
||
compatible: "omron,2smpb-02e" | ||
|
||
include: [sensor-device.yaml, i2c-device.yaml] |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment to document where these coefficients come from