一、 简介
1.1 硬件介绍
ESP32-S3 SoC 芯片支持以下功能:
- 2.4 GHz Wi-Fi
- 低功耗蓝牙
- 高性能 Xtensa® 32 位 LX7 双核处理器
- 运行 RISC-V 或 FSM 内核的超低功耗协处理器
- 多种外设
- 内置安全硬件
- USB OTG 接口
- USB 串口/JTAG 控制
1.2 官方资料
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组件,在当前工程目录下使用以下命令添加组件
idf.py add-dependency "espressif/mpu6050^1.2.0"
2.3添加代码
此时将main.c文件修改为以下内容
#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 实验现象
查看开发板上传的数据
三、代码讲解
3.1初始化
在i2c_sensor_mpu6050_init函数中初始化I2C接口与mpu6050传感器
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
函数获取传感器温度
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的角度计算值
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