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 <sven.herrmann@posteo.de>
This commit is contained in:
parent
298df51c0c
commit
bded58cee5
10 changed files with 369 additions and 0 deletions
|
@ -48,6 +48,7 @@ add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd)
|
|||
add_subdirectory_ifdef(CONFIG_MAX30101 max30101)
|
||||
add_subdirectory_ifdef(CONFIG_MAX44009 max44009)
|
||||
add_subdirectory_ifdef(CONFIG_MCP9808 mcp9808)
|
||||
add_subdirectory_ifdef(CONFIG_MPR mpr)
|
||||
add_subdirectory_ifdef(CONFIG_MPU6050 mpu6050)
|
||||
add_subdirectory_ifdef(CONFIG_MS5607 ms5607)
|
||||
add_subdirectory_ifdef(CONFIG_MS5837 ms5837)
|
||||
|
|
|
@ -127,6 +127,8 @@ source "drivers/sensor/mchp_tach_xec/Kconfig"
|
|||
|
||||
source "drivers/sensor/mcp9808/Kconfig"
|
||||
|
||||
source "drivers/sensor/mpr/Kconfig"
|
||||
|
||||
source "drivers/sensor/mpu6050/Kconfig"
|
||||
|
||||
source "drivers/sensor/ms5837/Kconfig"
|
||||
|
|
5
drivers/sensor/mpr/CMakeLists.txt
Normal file
5
drivers/sensor/mpr/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_MPR mpr.c)
|
67
drivers/sensor/mpr/Kconfig
Normal file
67
drivers/sensor/mpr/Kconfig
Normal file
|
@ -0,0 +1,67 @@
|
|||
# MPR pressure sensor configuration options
|
||||
|
||||
# Copyright (c) 2020 Sven Herrmann
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig MPR
|
||||
bool "MPR pressure sensor"
|
||||
depends on I2C && HAS_DTS_I2C
|
||||
help
|
||||
Enable driver for MPR pressure sensor.
|
||||
|
||||
if MPR
|
||||
|
||||
choice
|
||||
prompt "MPR Pressure Range"
|
||||
default MPR_PRESSURE_RANGE_0025
|
||||
config MPR_PRESSURE_RANGE_0001
|
||||
bool "0 to 1"
|
||||
config MPR_PRESSURE_RANGE_01_6
|
||||
bool "0 to 1.6"
|
||||
config MPR_PRESSURE_RANGE_02_5
|
||||
bool "0 to 2.5"
|
||||
config MPR_PRESSURE_RANGE_0015
|
||||
bool "0 to 15"
|
||||
config MPR_PRESSURE_RANGE_0025
|
||||
bool "0 to 25"
|
||||
config MPR_PRESSURE_RANGE_0030
|
||||
bool "0 to 30"
|
||||
config MPR_PRESSURE_RANGE_0060
|
||||
bool "0 to 60"
|
||||
config MPR_PRESSURE_RANGE_0100
|
||||
bool "0 to 100"
|
||||
config MPR_PRESSURE_RANGE_0160
|
||||
bool "0 to 160"
|
||||
config MPR_PRESSURE_RANGE_0250
|
||||
bool "0 to 250"
|
||||
config MPR_PRESSURE_RANGE_0400
|
||||
bool "0 to 400"
|
||||
config MPR_PRESSURE_RANGE_0600
|
||||
bool "0 to 600"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "MPR Pressure Unit"
|
||||
default MPR_PRESSURE_UNIT_P
|
||||
config MPR_PRESSURE_UNIT_P
|
||||
bool "psi"
|
||||
config MPR_PRESSURE_UNIT_K
|
||||
bool "kPa"
|
||||
config MPR_PRESSURE_UNIT_B
|
||||
bool "bar"
|
||||
config MPR_PRESSURE_UNIT_M
|
||||
bool "mbar"
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "MPR Transfer Function"
|
||||
default MPR_TRANSFER_FUNCTION_A
|
||||
config MPR_TRANSFER_FUNCTION_A
|
||||
bool "A"
|
||||
config MPR_TRANSFER_FUNCTION_B
|
||||
bool "B"
|
||||
config MPR_TRANSFER_FUNCTION_C
|
||||
bool "C"
|
||||
endchoice
|
||||
|
||||
endif # MPR
|
137
drivers/sensor/mpr/mpr.c
Normal file
137
drivers/sensor/mpr/mpr.c
Normal file
|
@ -0,0 +1,137 @@
|
|||
/* mpr.c - Driver for Honeywell MPR pressure sensor series */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Sven Herrmann
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT honeywell_mpr
|
||||
|
||||
#include <errno.h>
|
||||
#include <kernel.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <drivers/i2c.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <init.h>
|
||||
#include <logging/log.h>
|
||||
#include "mpr.h"
|
||||
#include "mpr_configuration.h"
|
||||
|
||||
LOG_MODULE_REGISTER(MPR, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int mpr_init(struct device *dev)
|
||||
{
|
||||
struct mpr_data *data = dev->driver_data;
|
||||
const struct mpr_config *cfg = dev->config->config_info;
|
||||
|
||||
data->i2c_master = device_get_binding(cfg->i2c_bus);
|
||||
if (!data->i2c_master) {
|
||||
LOG_ERR("mpr: i2c master not found: %s", cfg->i2c_bus);
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpr_read_reg(struct device *dev)
|
||||
{
|
||||
struct mpr_data *data = dev->driver_data;
|
||||
const struct mpr_config *cfg = dev->config->config_info;
|
||||
|
||||
u8_t write_buf[] = { MPR_OUTPUT_MEASUREMENT_COMMAND, 0x00, 0x00 };
|
||||
u8_t read_buf[4] = { 0x0 };
|
||||
|
||||
int rc = i2c_write(data->i2c_master, write_buf, sizeof(write_buf),
|
||||
cfg->i2c_addr);
|
||||
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
u8_t retries = MPR_REG_READ_MAX_RETRIES;
|
||||
|
||||
for (; retries > 0; retries--) {
|
||||
k_sleep(K_MSEC(MPR_REG_READ_DATA_CONV_DELAY_MS));
|
||||
|
||||
rc = i2c_read(data->i2c_master, read_buf, sizeof(read_buf),
|
||||
cfg->i2c_addr);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!(*read_buf & MPR_STATUS_MASK_POWER_ON)
|
||||
|| (*read_buf & MPR_STATUS_MASK_INTEGRITY_TEST_FAILED)
|
||||
|| (*read_buf & MPR_STATUS_MASK_MATH_SATURATION)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (!(*read_buf & MPR_STATUS_MASK_BUSY)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retries == 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data->reg_val = (read_buf[1] << 16)
|
||||
| (read_buf[2] << 8)
|
||||
| read_buf[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (reg_value - out_min) * (p_max - p_min)
|
||||
* pressure = --------------------------------------- + p_min
|
||||
* out_max - out_min
|
||||
*
|
||||
* returns pressure [kPa] * 10^6
|
||||
*/
|
||||
static inline void mpr_convert_reg(const u32_t *reg, s64_t *value)
|
||||
{
|
||||
*value = (*reg - MPR_OUTPUT_MIN) * (MPR_P_MAX - MPR_P_MIN);
|
||||
*value *= MPR_CONVERSION_FACTOR;
|
||||
*value /= MPR_OUTPUT_RANGE;
|
||||
*value += MPR_P_MIN;
|
||||
}
|
||||
|
||||
static int mpr_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_PRESS);
|
||||
|
||||
return mpr_read_reg(dev);
|
||||
}
|
||||
|
||||
static int mpr_channel_get(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
const struct mpr_data *data = dev->driver_data;
|
||||
|
||||
__ASSERT_NO_MSG(chan == SENSOR_CHAN_PRESS);
|
||||
|
||||
s64_t value;
|
||||
|
||||
mpr_convert_reg(&data->reg_val, &value);
|
||||
|
||||
val->val1 = value / 1000000;
|
||||
val->val2 = value % 1000000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api mpr_api_funcs = {
|
||||
.sample_fetch = mpr_sample_fetch,
|
||||
.channel_get = mpr_channel_get,
|
||||
};
|
||||
|
||||
static struct mpr_data mpr_data;
|
||||
static const struct mpr_config mpr_cfg = {
|
||||
.i2c_bus = DT_INST_BUS_LABEL(0),
|
||||
.i2c_addr = DT_INST_REG_ADDR(0),
|
||||
};
|
||||
|
||||
DEVICE_AND_API_INIT(mpr, DT_INST_LABEL(0), mpr_init, &mpr_data,
|
||||
&mpr_cfg, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
|
||||
&mpr_api_funcs);
|
43
drivers/sensor/mpr/mpr.h
Normal file
43
drivers/sensor/mpr/mpr.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Sven Herrmann
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_MPR_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_MPR_H_
|
||||
|
||||
|
||||
/* MPR output measurement command */
|
||||
#define MPR_OUTPUT_MEASUREMENT_COMMAND (0xAA)
|
||||
|
||||
/* MPR status byte masks */
|
||||
#define MPR_STATUS_MASK_MATH_SATURATION (0x01)
|
||||
#define MPR_STATUS_MASK_INTEGRITY_TEST_FAILED (0x04)
|
||||
#define MPR_STATUS_MASK_BUSY (0x20)
|
||||
#define MPR_STATUS_MASK_POWER_ON (0x40)
|
||||
|
||||
/* MPR register read maximum retries */
|
||||
#ifndef MPR_REG_READ_MAX_RETRIES
|
||||
#define MPR_REG_READ_MAX_RETRIES (3)
|
||||
#endif
|
||||
|
||||
/* MPR register read data conversion delay [ms] */
|
||||
#ifndef MPR_REG_READ_DATA_CONV_DELAY_MS
|
||||
#define MPR_REG_READ_DATA_CONV_DELAY_MS (5)
|
||||
#endif
|
||||
|
||||
struct mpr_data {
|
||||
struct device *i2c_master;
|
||||
|
||||
u32_t reg_val;
|
||||
};
|
||||
|
||||
struct mpr_config {
|
||||
const char *i2c_bus;
|
||||
u16_t i2c_addr;
|
||||
};
|
||||
|
||||
int mpr_reg_read(struct device *dev, u8_t reg, u16_t *val);
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_MPR_H_ */
|
98
drivers/sensor/mpr/mpr_configuration.h
Normal file
98
drivers/sensor/mpr/mpr_configuration.h
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Sven Herrmann
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_MPR_CONFIGURATION_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_MPR_CONFIGURATION_H_
|
||||
|
||||
/*
|
||||
* Pressure Range
|
||||
*
|
||||
* MIN is always 0
|
||||
*/
|
||||
#define MPR_P_MIN (0)
|
||||
|
||||
#if defined(CONFIG_MPR_PRESSURE_RANGE_0001)
|
||||
#define MPR_P_MAX (1)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_01_6)
|
||||
#define MPR_P_MAX (1.6)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_02_5)
|
||||
#define MPR_P_MAX (2.5)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0015)
|
||||
#define MPR_P_MAX (15)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0025)
|
||||
#define MPR_P_MAX (25)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0030)
|
||||
#define MPR_P_MAX (30)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0060)
|
||||
#define MPR_P_MAX (60)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0100)
|
||||
#define MPR_P_MAX (100)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0160)
|
||||
#define MPR_P_MAX (160)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0250)
|
||||
#define MPR_P_MAX (250)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0400)
|
||||
#define MPR_P_MAX (400)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_RANGE_0600)
|
||||
#define MPR_P_MAX (600)
|
||||
|
||||
#else
|
||||
#error "MPR: Unknown pressure range."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Pressure Unit
|
||||
*/
|
||||
#if defined(CONFIG_MPR_PRESSURE_UNIT_P)
|
||||
/* psi to kPa conversion factor: 6.894757 * 10^6 */
|
||||
#define MPR_CONVERSION_FACTOR (6894757)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_UNIT_K)
|
||||
/* kPa to kPa conversion factor: 1 * 10^6 */
|
||||
#define MPR_CONVERSION_FACTOR (1000000)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_UNIT_B)
|
||||
/* bar to kPa conversion factor: 100 * 10^6 */
|
||||
#define MPR_CONVERSION_FACTOR (100000000)
|
||||
|
||||
#elif defined(CONFIG_MPR_PRESSURE_UNIT_M)
|
||||
/* mbar to kPa conversion factor: 0.1 * 10^6 */
|
||||
#define MPR_CONVERSION_FACTOR (100000)
|
||||
|
||||
#else
|
||||
#error "MPR: Unknown pressure unit."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Transfer function
|
||||
*/
|
||||
#if defined(CONFIG_MPR_TRANSFER_FUNCTION_A)
|
||||
#define MPR_OUTPUT_MIN (0x19999A) /* 10% of 2^24 */
|
||||
#define MPR_OUTPUT_MAX (0xE66666) /* 90% of 2^24 */
|
||||
#elif defined(CONFIG_MPR_TRANSFER_FUNCTION_B)
|
||||
#define MPR_OUTPUT_MIN (0x66666) /* 2.5% of 2^24 */
|
||||
#define MPR_OUTPUT_MAX (0x399999) /* 22.5% of 2^24 */
|
||||
#elif defined(CONFIG_MPR_TRANSFER_FUNCTION_C)
|
||||
#define MPR_OUTPUT_MIN (0x333333) /* 20% of 2^24 */
|
||||
#define MPR_OUTPUT_MAX (0xCCCCCC) /* 80% of 2^24 */
|
||||
#else
|
||||
#error "MPR: Unknown pressure reference."
|
||||
#endif
|
||||
|
||||
#define MPR_OUTPUT_RANGE (MPR_OUTPUT_MAX - MPR_OUTPUT_MIN)
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_MPR_CONFIGURATION_H_ */
|
9
dts/bindings/sensor/honeywell,mpr.yaml
Normal file
9
dts/bindings/sensor/honeywell,mpr.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Honeywell Digital Pressure Sensor. For details see here:
|
||||
https://sensing.honeywell.com/micropressure-mpr-series
|
||||
|
||||
compatible: "honeywell,mpr"
|
||||
|
||||
include: i2c-device.yaml
|
|
@ -517,3 +517,9 @@ test_i2c_bq274xx: bq27xx@47 {
|
|||
taper-current = <45>;
|
||||
terminate-voltage = <3000>;
|
||||
};
|
||||
|
||||
test_i2c_mpr: mpr@18 {
|
||||
compatible = "honeywell,mpr";
|
||||
label = "MPR";
|
||||
reg = <0x18>;
|
||||
};
|
||||
|
|
|
@ -30,3 +30,4 @@ CONFIG_HMC5883L=y
|
|||
CONFIG_HP206C=y
|
||||
CONFIG_HTS221=y
|
||||
CONFIG_ADXL345=y
|
||||
CONFIG_MPR=y
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue