Skip to content

Commit bded58c

Browse files
sven-hmcarlescufi
authored andcommitted
Sensor: mpr: Add Honeywell MPR driver
The Honeywell MPR sensor is a piezoresistive silicon pressure sensor, which can be accessed via i2c. https://sensing.honeywell.com/micropressure-mpr-series Signed-off-by: Sven Herrmann <[email protected]>
1 parent 298df51 commit bded58c

File tree

10 files changed

+369
-0
lines changed

10 files changed

+369
-0
lines changed

drivers/sensor/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd)
4848
add_subdirectory_ifdef(CONFIG_MAX30101 max30101)
4949
add_subdirectory_ifdef(CONFIG_MAX44009 max44009)
5050
add_subdirectory_ifdef(CONFIG_MCP9808 mcp9808)
51+
add_subdirectory_ifdef(CONFIG_MPR mpr)
5152
add_subdirectory_ifdef(CONFIG_MPU6050 mpu6050)
5253
add_subdirectory_ifdef(CONFIG_MS5607 ms5607)
5354
add_subdirectory_ifdef(CONFIG_MS5837 ms5837)

drivers/sensor/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ source "drivers/sensor/mchp_tach_xec/Kconfig"
127127

128128
source "drivers/sensor/mcp9808/Kconfig"
129129

130+
source "drivers/sensor/mpr/Kconfig"
131+
130132
source "drivers/sensor/mpu6050/Kconfig"
131133

132134
source "drivers/sensor/ms5837/Kconfig"

drivers/sensor/mpr/CMakeLists.txt

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_ifdef(CONFIG_MPR mpr.c)

drivers/sensor/mpr/Kconfig

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# MPR pressure sensor configuration options
2+
3+
# Copyright (c) 2020 Sven Herrmann
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
menuconfig MPR
7+
bool "MPR pressure sensor"
8+
depends on I2C && HAS_DTS_I2C
9+
help
10+
Enable driver for MPR pressure sensor.
11+
12+
if MPR
13+
14+
choice
15+
prompt "MPR Pressure Range"
16+
default MPR_PRESSURE_RANGE_0025
17+
config MPR_PRESSURE_RANGE_0001
18+
bool "0 to 1"
19+
config MPR_PRESSURE_RANGE_01_6
20+
bool "0 to 1.6"
21+
config MPR_PRESSURE_RANGE_02_5
22+
bool "0 to 2.5"
23+
config MPR_PRESSURE_RANGE_0015
24+
bool "0 to 15"
25+
config MPR_PRESSURE_RANGE_0025
26+
bool "0 to 25"
27+
config MPR_PRESSURE_RANGE_0030
28+
bool "0 to 30"
29+
config MPR_PRESSURE_RANGE_0060
30+
bool "0 to 60"
31+
config MPR_PRESSURE_RANGE_0100
32+
bool "0 to 100"
33+
config MPR_PRESSURE_RANGE_0160
34+
bool "0 to 160"
35+
config MPR_PRESSURE_RANGE_0250
36+
bool "0 to 250"
37+
config MPR_PRESSURE_RANGE_0400
38+
bool "0 to 400"
39+
config MPR_PRESSURE_RANGE_0600
40+
bool "0 to 600"
41+
endchoice
42+
43+
choice
44+
prompt "MPR Pressure Unit"
45+
default MPR_PRESSURE_UNIT_P
46+
config MPR_PRESSURE_UNIT_P
47+
bool "psi"
48+
config MPR_PRESSURE_UNIT_K
49+
bool "kPa"
50+
config MPR_PRESSURE_UNIT_B
51+
bool "bar"
52+
config MPR_PRESSURE_UNIT_M
53+
bool "mbar"
54+
endchoice
55+
56+
choice
57+
prompt "MPR Transfer Function"
58+
default MPR_TRANSFER_FUNCTION_A
59+
config MPR_TRANSFER_FUNCTION_A
60+
bool "A"
61+
config MPR_TRANSFER_FUNCTION_B
62+
bool "B"
63+
config MPR_TRANSFER_FUNCTION_C
64+
bool "C"
65+
endchoice
66+
67+
endif # MPR

drivers/sensor/mpr/mpr.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* mpr.c - Driver for Honeywell MPR pressure sensor series */
2+
3+
/*
4+
* Copyright (c) 2020 Sven Herrmann
5+
*
6+
* SPDX-License-Identifier: Apache-2.0
7+
*/
8+
9+
#define DT_DRV_COMPAT honeywell_mpr
10+
11+
#include <errno.h>
12+
#include <kernel.h>
13+
#include <sys/__assert.h>
14+
#include <drivers/sensor.h>
15+
#include <drivers/i2c.h>
16+
#include <sys/byteorder.h>
17+
#include <init.h>
18+
#include <logging/log.h>
19+
#include "mpr.h"
20+
#include "mpr_configuration.h"
21+
22+
LOG_MODULE_REGISTER(MPR, CONFIG_SENSOR_LOG_LEVEL);
23+
24+
static int mpr_init(struct device *dev)
25+
{
26+
struct mpr_data *data = dev->driver_data;
27+
const struct mpr_config *cfg = dev->config->config_info;
28+
29+
data->i2c_master = device_get_binding(cfg->i2c_bus);
30+
if (!data->i2c_master) {
31+
LOG_ERR("mpr: i2c master not found: %s", cfg->i2c_bus);
32+
return -EINVAL;
33+
}
34+
return 0;
35+
}
36+
37+
static int mpr_read_reg(struct device *dev)
38+
{
39+
struct mpr_data *data = dev->driver_data;
40+
const struct mpr_config *cfg = dev->config->config_info;
41+
42+
u8_t write_buf[] = { MPR_OUTPUT_MEASUREMENT_COMMAND, 0x00, 0x00 };
43+
u8_t read_buf[4] = { 0x0 };
44+
45+
int rc = i2c_write(data->i2c_master, write_buf, sizeof(write_buf),
46+
cfg->i2c_addr);
47+
48+
if (rc < 0) {
49+
return rc;
50+
}
51+
52+
u8_t retries = MPR_REG_READ_MAX_RETRIES;
53+
54+
for (; retries > 0; retries--) {
55+
k_sleep(K_MSEC(MPR_REG_READ_DATA_CONV_DELAY_MS));
56+
57+
rc = i2c_read(data->i2c_master, read_buf, sizeof(read_buf),
58+
cfg->i2c_addr);
59+
if (rc < 0) {
60+
return rc;
61+
}
62+
63+
if (!(*read_buf & MPR_STATUS_MASK_POWER_ON)
64+
|| (*read_buf & MPR_STATUS_MASK_INTEGRITY_TEST_FAILED)
65+
|| (*read_buf & MPR_STATUS_MASK_MATH_SATURATION)) {
66+
return -EIO;
67+
}
68+
69+
if (!(*read_buf & MPR_STATUS_MASK_BUSY)) {
70+
break;
71+
}
72+
}
73+
74+
if (retries == 0) {
75+
return -EIO;
76+
}
77+
78+
data->reg_val = (read_buf[1] << 16)
79+
| (read_buf[2] << 8)
80+
| read_buf[3];
81+
82+
return 0;
83+
}
84+
85+
/* (reg_value - out_min) * (p_max - p_min)
86+
* pressure = --------------------------------------- + p_min
87+
* out_max - out_min
88+
*
89+
* returns pressure [kPa] * 10^6
90+
*/
91+
static inline void mpr_convert_reg(const u32_t *reg, s64_t *value)
92+
{
93+
*value = (*reg - MPR_OUTPUT_MIN) * (MPR_P_MAX - MPR_P_MIN);
94+
*value *= MPR_CONVERSION_FACTOR;
95+
*value /= MPR_OUTPUT_RANGE;
96+
*value += MPR_P_MIN;
97+
}
98+
99+
static int mpr_sample_fetch(struct device *dev, enum sensor_channel chan)
100+
{
101+
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_PRESS);
102+
103+
return mpr_read_reg(dev);
104+
}
105+
106+
static int mpr_channel_get(struct device *dev,
107+
enum sensor_channel chan,
108+
struct sensor_value *val)
109+
{
110+
const struct mpr_data *data = dev->driver_data;
111+
112+
__ASSERT_NO_MSG(chan == SENSOR_CHAN_PRESS);
113+
114+
s64_t value;
115+
116+
mpr_convert_reg(&data->reg_val, &value);
117+
118+
val->val1 = value / 1000000;
119+
val->val2 = value % 1000000;
120+
121+
return 0;
122+
}
123+
124+
static const struct sensor_driver_api mpr_api_funcs = {
125+
.sample_fetch = mpr_sample_fetch,
126+
.channel_get = mpr_channel_get,
127+
};
128+
129+
static struct mpr_data mpr_data;
130+
static const struct mpr_config mpr_cfg = {
131+
.i2c_bus = DT_INST_BUS_LABEL(0),
132+
.i2c_addr = DT_INST_REG_ADDR(0),
133+
};
134+
135+
DEVICE_AND_API_INIT(mpr, DT_INST_LABEL(0), mpr_init, &mpr_data,
136+
&mpr_cfg, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
137+
&mpr_api_funcs);

drivers/sensor/mpr/mpr.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2020 Sven Herrmann
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_DRIVERS_SENSOR_MPR_H_
8+
#define ZEPHYR_DRIVERS_SENSOR_MPR_H_
9+
10+
11+
/* MPR output measurement command */
12+
#define MPR_OUTPUT_MEASUREMENT_COMMAND (0xAA)
13+
14+
/* MPR status byte masks */
15+
#define MPR_STATUS_MASK_MATH_SATURATION (0x01)
16+
#define MPR_STATUS_MASK_INTEGRITY_TEST_FAILED (0x04)
17+
#define MPR_STATUS_MASK_BUSY (0x20)
18+
#define MPR_STATUS_MASK_POWER_ON (0x40)
19+
20+
/* MPR register read maximum retries */
21+
#ifndef MPR_REG_READ_MAX_RETRIES
22+
#define MPR_REG_READ_MAX_RETRIES (3)
23+
#endif
24+
25+
/* MPR register read data conversion delay [ms] */
26+
#ifndef MPR_REG_READ_DATA_CONV_DELAY_MS
27+
#define MPR_REG_READ_DATA_CONV_DELAY_MS (5)
28+
#endif
29+
30+
struct mpr_data {
31+
struct device *i2c_master;
32+
33+
u32_t reg_val;
34+
};
35+
36+
struct mpr_config {
37+
const char *i2c_bus;
38+
u16_t i2c_addr;
39+
};
40+
41+
int mpr_reg_read(struct device *dev, u8_t reg, u16_t *val);
42+
43+
#endif /* ZEPHYR_DRIVERS_SENSOR_MPR_H_ */
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2020 Sven Herrmann
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_DRIVERS_SENSOR_MPR_CONFIGURATION_H_
8+
#define ZEPHYR_DRIVERS_SENSOR_MPR_CONFIGURATION_H_
9+
10+
/*
11+
* Pressure Range
12+
*
13+
* MIN is always 0
14+
*/
15+
#define MPR_P_MIN (0)
16+
17+
#if defined(CONFIG_MPR_PRESSURE_RANGE_0001)
18+
#define MPR_P_MAX (1)
19+
20+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_01_6)
21+
#define MPR_P_MAX (1.6)
22+
23+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_02_5)
24+
#define MPR_P_MAX (2.5)
25+
26+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0015)
27+
#define MPR_P_MAX (15)
28+
29+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0025)
30+
#define MPR_P_MAX (25)
31+
32+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0030)
33+
#define MPR_P_MAX (30)
34+
35+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0060)
36+
#define MPR_P_MAX (60)
37+
38+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0100)
39+
#define MPR_P_MAX (100)
40+
41+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0160)
42+
#define MPR_P_MAX (160)
43+
44+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0250)
45+
#define MPR_P_MAX (250)
46+
47+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0400)
48+
#define MPR_P_MAX (400)
49+
50+
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0600)
51+
#define MPR_P_MAX (600)
52+
53+
#else
54+
#error "MPR: Unknown pressure range."
55+
#endif
56+
57+
/*
58+
* Pressure Unit
59+
*/
60+
#if defined(CONFIG_MPR_PRESSURE_UNIT_P)
61+
/* psi to kPa conversion factor: 6.894757 * 10^6 */
62+
#define MPR_CONVERSION_FACTOR (6894757)
63+
64+
#elif defined(CONFIG_MPR_PRESSURE_UNIT_K)
65+
/* kPa to kPa conversion factor: 1 * 10^6 */
66+
#define MPR_CONVERSION_FACTOR (1000000)
67+
68+
#elif defined(CONFIG_MPR_PRESSURE_UNIT_B)
69+
/* bar to kPa conversion factor: 100 * 10^6 */
70+
#define MPR_CONVERSION_FACTOR (100000000)
71+
72+
#elif defined(CONFIG_MPR_PRESSURE_UNIT_M)
73+
/* mbar to kPa conversion factor: 0.1 * 10^6 */
74+
#define MPR_CONVERSION_FACTOR (100000)
75+
76+
#else
77+
#error "MPR: Unknown pressure unit."
78+
#endif
79+
80+
/*
81+
* Transfer function
82+
*/
83+
#if defined(CONFIG_MPR_TRANSFER_FUNCTION_A)
84+
#define MPR_OUTPUT_MIN (0x19999A) /* 10% of 2^24 */
85+
#define MPR_OUTPUT_MAX (0xE66666) /* 90% of 2^24 */
86+
#elif defined(CONFIG_MPR_TRANSFER_FUNCTION_B)
87+
#define MPR_OUTPUT_MIN (0x66666) /* 2.5% of 2^24 */
88+
#define MPR_OUTPUT_MAX (0x399999) /* 22.5% of 2^24 */
89+
#elif defined(CONFIG_MPR_TRANSFER_FUNCTION_C)
90+
#define MPR_OUTPUT_MIN (0x333333) /* 20% of 2^24 */
91+
#define MPR_OUTPUT_MAX (0xCCCCCC) /* 80% of 2^24 */
92+
#else
93+
#error "MPR: Unknown pressure reference."
94+
#endif
95+
96+
#define MPR_OUTPUT_RANGE (MPR_OUTPUT_MAX - MPR_OUTPUT_MIN)
97+
98+
#endif /* ZEPHYR_DRIVERS_SENSOR_MPR_CONFIGURATION_H_ */
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
description: |
4+
Honeywell Digital Pressure Sensor. For details see here:
5+
https://sensing.honeywell.com/micropressure-mpr-series
6+
7+
compatible: "honeywell,mpr"
8+
9+
include: i2c-device.yaml

tests/drivers/build_all/i2c.dtsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,3 +517,9 @@ test_i2c_bq274xx: bq27xx@47 {
517517
taper-current = <45>;
518518
terminate-voltage = <3000>;
519519
};
520+
521+
test_i2c_mpr: mpr@18 {
522+
compatible = "honeywell,mpr";
523+
label = "MPR";
524+
reg = <0x18>;
525+
};

tests/drivers/build_all/sensors_a_h.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ CONFIG_HMC5883L=y
3030
CONFIG_HP206C=y
3131
CONFIG_HTS221=y
3232
CONFIG_ADXL345=y
33+
CONFIG_MPR=y

0 commit comments

Comments
 (0)