一、 简介

1.1 硬件介绍

ESP32-S3 SoC 芯片支持以下功能:

  • 2.4 GHz Wi-Fi
  • 低功耗蓝牙
  • 高性能 Xtensa® 32 位 LX7 双核处理器
  • 运行 RISC-V 或 FSM 内核的超低功耗协处理器
  • 多种外设
  • 内置安全硬件
  • USB OTG 接口
  • USB 串口/JTAG 控制

1.2 官方资料

ESP-IDF编程指南
I2C驱动程序

1.3 开发环境

软件:IDF 5.1.1
硬件:ESP32-S3-LCD-EV-Board-MB 开发板 、mpu6050模块

1.4 MPU6050介绍

MPU-6050是一款由InvenSense公司生产的集成6轴运动追踪设备(MotionTracking device),它结合了3轴陀螺仪和3轴加速度计,可以通过I2C总线进行通信。MPU-6050能够提供包括加速度、角速度、温度等在内的全方位运动追踪数据,非常适合需要运动或姿态检测的应用场合,如手势识别、游戏控制器、可穿戴设备等。

主要特性

  • 六轴感应:内置3轴陀螺仪和3轴加速度计。
  • I2C接口:支持标准和快速模式,最高400kHz。
  • 输入电压:通常为3.3V或者5V(通过外部逻辑电平转换)。
  • 数字输出:所有六轴的运动数据都通过数字输出,可以直接读取,无需模拟到数字信号的转换。
  • 自由落体检测:能够检测设备是否处于自由落体状态。
  • 运动检测:可以检测设备的运动状态。
  • 温度传感器:内置温度传感器。
  • 程序化低通滤波器:可设置不同的滤波器参数,以满足不同应用需求。

应用场合
MPU-6050因其高度的集成度和性能,在很多领域都有广泛的应用,包括:

  • 可穿戴设备:如运动追踪手环、智能手表等。
  • 游戏与虚拟现实:游戏控制器的运动检测、虚拟现实设备的姿态追踪。
  • 机器人:平衡车、无人机的姿态控制和稳定。
  • 移动设备:智能手机或平板的运动感应游戏、方向检测。

MPU-6050提供的数据可以用来计算设备的倾斜角度(通过加速度计)和旋转速率(通过陀螺仪),而且由于它的小尺寸和低功耗特性,非常适合于便携式设备。可以通过读取和处理这些数据,实现复杂的运动检测和追踪功能。

引脚定义

符号 功能描述
VCC 3.3/5V 电源输入
GND 地线
SDA I2C从数据信号线SDA
SCL I2C从时钟信号线SCL
INT 中断输出引脚
ADO 从机地址设置引脚

更多mpu6050相关信息可查看野火的MPU6050传感器—姿态检测教程

二、获取mpu6050传感器数据

2.1 引脚确认

使用的是IO19与IO20两个引脚,使用杜邦线将开发板的这两个引脚分别接到mpu6050模块的SCL与SDA引脚上,将ADO引脚接到GND。

ADO引脚为从机地址设置引脚,接地或悬空时, 地址为: 0x68;接VCC时,地址为:0x69

2.2组件添加

前往乐鑫组件管理器搜索mpu6050
mpu6050
找到mpu6050组件,在当前工程目录下使用以下命令添加组件

1
idf.py add-dependency "espressif/mpu6050^1.2.0"

2.3添加代码

此时将main.c文件修改为以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "unity.h"
#include "driver/i2c.h"
#include "mpu6050.h"
#include "esp_system.h"

#define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO 20 /*!< gpio number for I2C master data */
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */

static const char *TAG = "HK";
static mpu6050_handle_t mpu6050 = NULL;

/**
* @brief i2c master initialization
*/
static void i2c_bus_init(void)
{
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = (gpio_num_t)I2C_MASTER_SDA_IO;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = (gpio_num_t)I2C_MASTER_SCL_IO;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL;

esp_err_t ret = i2c_param_config(I2C_MASTER_NUM, &conf);
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, ret, "I2C config returned error");

ret = i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0);
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, ret, "I2C install returned error");
}

/**
* @brief i2c master initialization
*/
static void i2c_sensor_mpu6050_init(void)
{
esp_err_t ret;

i2c_bus_init();
mpu6050 = mpu6050_create(I2C_MASTER_NUM, MPU6050_I2C_ADDRESS);
TEST_ASSERT_NOT_NULL_MESSAGE(mpu6050, "MPU6050 create returned NULL");

ret = mpu6050_config(mpu6050, ACCE_FS_4G, GYRO_FS_500DPS);
TEST_ASSERT_EQUAL(ESP_OK, ret);

ret = mpu6050_wake_up(mpu6050);
TEST_ASSERT_EQUAL(ESP_OK, ret);
}

void app_main(void)
{
esp_err_t ret;
uint8_t mpu6050_deviceid;
mpu6050_acce_value_t acce;
mpu6050_gyro_value_t gyro;
mpu6050_temp_value_t temp;
complimentary_angle_t angle;;

i2c_sensor_mpu6050_init();

ret = mpu6050_get_deviceid(mpu6050, &mpu6050_deviceid);
TEST_ASSERT_EQUAL(ESP_OK, ret);
TEST_ASSERT_EQUAL_UINT8_MESSAGE(MPU6050_WHO_AM_I_VAL, mpu6050_deviceid, "Who Am I register does not contain expected data");

ret = mpu6050_get_acce(mpu6050, &acce);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "acce_x:%.2f, acce_y:%.2f, acce_z:%.2f\n", acce.acce_x, acce.acce_y, acce.acce_z);

ret = mpu6050_get_gyro(mpu6050, &gyro);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "gyro_x:%.2f, gyro_y:%.2f, gyro_z:%.2f\n", gyro.gyro_x, gyro.gyro_y, gyro.gyro_z);

ret = mpu6050_get_temp(mpu6050, &temp);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "t:%.2f \n", temp.temp);

while (1)
{
/* code */
ret = mpu6050_get_acce(mpu6050, &acce);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "acce_x:%.2f, acce_y:%.2f, acce_z:%.2f\n", acce.acce_x, acce.acce_y, acce.acce_z);

ret = mpu6050_get_gyro(mpu6050, &gyro);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "gyro_x:%.2f, gyro_y:%.2f, gyro_z:%.2f\n", gyro.gyro_x, gyro.gyro_y, gyro.gyro_z);

ret = mpu6050_get_temp(mpu6050, &temp);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "t:%.2f \n", temp.temp);

ret = mpu6050_complimentory_filter(mpu6050, &acce,&gyro,&angle);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "pitch:%.2f roll:%.2f \n", angle.pitch,angle.roll);
vTaskDelay(pdMS_TO_TICKS(500));
}

}

2.4 实验现象

查看开发板上传的数据
mpu6050实验现象

三、代码讲解

3.1初始化

在i2c_sensor_mpu6050_init函数中初始化I2C接口与mpu6050传感器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void i2c_sensor_mpu6050_init(void)
{
esp_err_t ret;

i2c_bus_init();
mpu6050 = mpu6050_create(I2C_MASTER_NUM, MPU6050_I2C_ADDRESS);
TEST_ASSERT_NOT_NULL_MESSAGE(mpu6050, "MPU6050 create returned NULL");

ret = mpu6050_config(mpu6050, ACCE_FS_4G, GYRO_FS_500DPS);
TEST_ASSERT_EQUAL(ESP_OK, ret);

ret = mpu6050_wake_up(mpu6050);
TEST_ASSERT_EQUAL(ESP_OK, ret);
}

3.2 数据获取

mpu6050_get_acce函数获取加速度计测量值
mpu6050_get_gyro函数获取陀螺仪值
mpu6050_get_temp函数获取传感器温度

1
2
3
4
5
6
7
8
9
10
11
ret = mpu6050_get_acce(mpu6050, &acce);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "acce_x:%.2f, acce_y:%.2f, acce_z:%.2f\n", acce.acce_x, acce.acce_y, acce.acce_z);

ret = mpu6050_get_gyro(mpu6050, &gyro);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "gyro_x:%.2f, gyro_y:%.2f, gyro_z:%.2f\n", gyro.gyro_x, gyro.gyro_y, gyro.gyro_z);

ret = mpu6050_get_temp(mpu6050, &temp);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "t:%.2f \n", temp.temp);

3.2 角度计算

mpu6050_complimentory_filter函数通过将获取到的加速度值与陀螺仪值作为参数传入,返回pitch与roll的角度计算值

1
2
3
ret = mpu6050_complimentory_filter(mpu6050, &acce,&gyro,&angle);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "pitch:%.2f roll:%.2f \n", angle.pitch,angle.roll);

四、代码地址

Github仓库:mpu6050