Skip to content
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

drivers: sensor: mpu6050: support for choosing sample rate divider #81649

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 89 additions & 17 deletions drivers/sensor/tdk/mpu6050/mpu6050.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,77 @@ int mpu6050_init(const struct device *dev)
return -EINVAL;
}

/* wake up chip */
if (i2c_reg_update_byte_dt(&cfg->i2c, MPU6050_REG_PWR_MGMT1,
MPU6050_SLEEP_EN, 0) < 0) {
LOG_ERR("Failed to wake up chip.");
/* Reset sequence is added to ensure all registers are reset to their
* default values, and also to enable easier addition of SPI support in
* future.
*/
/* When using SPI interface, user should use DEVICE_RESET as well as
* SIGNAL_PATH_RESET to ensure th ereest is performed properly.
* The sequence used should be:
* 1. Set DEVICE_RESET = 1 (reg PWR_MGMT_1)
* 2. Wait 100ms
* 3. Set GYRO_RESET = ACCEL_RESET = TEMP_RESET = 1 (reg SIGNAL_PATH_RESET)
* 4. Wait 100ms
* (RM-MPU-6000A-00 rev 4.2 page 41 of 46)
*/
if (i2c_reg_write_byte_dt(&cfg->i2c, MPU6050_REG_PWR_MGMT1, MPU6050_DEVICE_RESET) < 0) {
LOG_ERR("Device reset failed.");
return -EIO;
}

k_sleep(K_MSEC(100));

/* check content of Power Management 1 register. */
uint8_t tmp;

if ((i2c_reg_read_byte_dt(&cfg->i2c, MPU6050_REG_PWR_MGMT1, &tmp) < 0)) {
LOG_ERR("Device reset request failed.");
return -EIO;
}

if (tmp != MPU6050_PWR_MGMT1_RST_VAL) {
LOG_ERR("Device reset failed.");
return -EINVAL;
}

/* select clock source.
* While gyros are active, selecting the gyros as the clock source provides
* for a more accurate clock source.
* (Document Number: PS-MPU-6000A-00 Page 30 of 52)
*/
if (i2c_reg_write_byte_dt(&cfg->i2c, MPU6050_REG_PWR_MGMT1, 0x01) < 0) {
LOG_ERR("Clock select failed.");
return -EIO;
}

/* signal paths reset. */
if (i2c_reg_update_byte_dt(&cfg->i2c, MPU6050_REG_SIGNAL_PATH_RESET,
(MPU6050_GYRO_RESET | MPU6050_ACCEL_RESET | MPU6050_TEMP_RESET),
0x07) < 0) {
LOG_ERR("Signal path reset failed.");
return -EIO;
}

/* reset signal paths of all sensors and clear sensor registers. */
if (i2c_reg_update_byte_dt(&cfg->i2c, MPU6050_REG_USER_CTRL, MPU6050_SIG_COND_RESET, 1) <
0) {
LOG_ERR("Signal path reset failed.");
return -EIO;
}

k_sleep(K_MSEC(100));

if (cfg->smplrt_div > 255 || cfg->smplrt_div < 4) {
LOG_ERR("Not supported sample rate divider");
return -ENOTSUP;
}

/* Sample Rate = Gyroscope Output Rate / (1 + smplrt_div)
* (RM-MPU-6000A-00 rev 4.2 page 12 of 46)
*/
if (i2c_reg_write_byte_dt(&cfg->i2c, MPU6050_REG_SAMPLE_RATE_DIVIDER, cfg->smplrt_div) <
0) {
LOG_ERR("Sample rate divider configuration failed.");
return -EIO;
}

Expand Down Expand Up @@ -233,21 +300,26 @@ int mpu6050_init(const struct device *dev)
}
#endif

/* wake up chip */
if (i2c_reg_update_byte_dt(&cfg->i2c, MPU6050_REG_PWR_MGMT1, MPU6050_SLEEP_EN, 0) < 0) {
LOG_ERR("Failed to wake up chip.");
return -EIO;
}

return 0;
}

#define MPU6050_DEFINE(inst) \
static struct mpu6050_data mpu6050_data_##inst; \
\
static const struct mpu6050_config mpu6050_config_##inst = { \
.i2c = I2C_DT_SPEC_INST_GET(inst), \
IF_ENABLED(CONFIG_MPU6050_TRIGGER, \
(.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }),)) \
}; \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, mpu6050_init, NULL, \
&mpu6050_data_##inst, &mpu6050_config_##inst, \
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
&mpu6050_driver_api); \
#define MPU6050_DEFINE(inst) \
static struct mpu6050_data mpu6050_data_##inst; \
\
static const struct mpu6050_config mpu6050_config_##inst = { \
.i2c = I2C_DT_SPEC_INST_GET(inst), \
.int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios), \
.smplrt_div = DT_INST_PROP(inst, smplrt_div), \
}; \
\
SENSOR_DEVICE_DT_INST_DEFINE(inst, mpu6050_init, NULL, &mpu6050_data_##inst, \
&mpu6050_config_##inst, POST_KERNEL, \
CONFIG_SENSOR_INIT_PRIORITY, &mpu6050_driver_api);

DT_INST_FOREACH_STATUS_OKAY(MPU6050_DEFINE)
22 changes: 18 additions & 4 deletions drivers/sensor/tdk/mpu6050/mpu6050.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#define MPU9250_CHIP_ID 0x71
#define MPU6880_CHIP_ID 0x19

/* Sample Rate Divider Register */
#define MPU6050_REG_SAMPLE_RATE_DIVIDER 0x19

#define MPU6050_REG_GYRO_CFG 0x1B
#define MPU6050_GYRO_FS_SHIFT 3

Expand All @@ -31,8 +34,20 @@

#define MPU6050_REG_DATA_START 0x3B

#define MPU6050_REG_PWR_MGMT1 0x6B
#define MPU6050_SLEEP_EN BIT(6)
/* Signal Path Reset Register */
#define MPU6050_REG_SIGNAL_PATH_RESET 0x68
#define MPU6050_TEMP_RESET BIT(0)
#define MPU6050_ACCEL_RESET BIT(1)
#define MPU6050_GYRO_RESET BIT(2)

/* User Control Register */
#define MPU6050_REG_USER_CTRL 0x6A
#define MPU6050_SIG_COND_RESET BIT(0)

#define MPU6050_REG_PWR_MGMT1 0x6B
#define MPU6050_SLEEP_EN BIT(6)
#define MPU6050_DEVICE_RESET BIT(7)
#define MPU6050_PWR_MGMT1_RST_VAL 0x40

/* measured in degrees/sec x10 to avoid floating point */
static const uint16_t mpu6050_gyro_sensitivity_x10[] = {
Expand Down Expand Up @@ -80,9 +95,8 @@ struct mpu6050_data {

struct mpu6050_config {
struct i2c_dt_spec i2c;
#ifdef CONFIG_MPU6050_TRIGGER
struct gpio_dt_spec int_gpio;
#endif /* CONFIG_MPU6050_TRIGGER */
int smplrt_div;
};

#ifdef CONFIG_MPU6050_TRIGGER
Expand Down
11 changes: 11 additions & 0 deletions dts/bindings/sensor/invensense,mpu6050.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,14 @@ properties:
The INT signal default configuration is active-high. The
property value should ensure the flags properly describe the
signal that is presented to the driver.

smplrt-div:
type: int
default: 7
description: |
Sensor Data Sample Rate Divider.
Sensor data Sample Rate = 8000Hz / (1 + Sample Rate Divider).
While using I2C minimal Data Sample Rate Divider is 4, which results in
1600Hz Sensor Data Sample Rate. Sample Rates higher than this are not
recommended while using I2C.
Valid range: 4 - 255
Loading