-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6c716e0
commit 34c8eb2
Showing
5 changed files
with
282 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
idf_component_register(SRCS "mpu6050.c" | ||
INCLUDE_DIRS ".") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# mpu6050 | ||
|
||
This component is a driver for the MPU6050 6-axis motion tracking device. | ||
|
||
Author: [@MaxwellJay256](https://github.com/MaxwellJay256) | ||
|
||
Reference: [*esp32系列(10):mpu6050驱动 - CSDN*](http://t.csdnimg.cn/vPGnV) | ||
|
||
## Content | ||
|
||
This component only has two source files, plus a `CMakeLists.txt` file. | ||
- [mpu6050.h](./mpu6050.h): The header file of the driver. | ||
- [mpu6050.c](./mpu6050.c): The source file of the driver. | ||
- [CMakeLists.txt](./CMakeLists.txt): A CMake file registering this component. | ||
|
||
## Usage | ||
|
||
### Edit the variables and macros | ||
|
||
There are 4 macros you must notice in [`mpu6050.h`](./mpu6050.h). | ||
You should edit them to fit your hardware. | ||
The default values are suitable for `ESP32-DevKitC`. | ||
|
||
```c | ||
#define MPU6050_I2C_SDA 19 // MPU6050 I2C 的 SDA 引脚 | ||
#define MPU6050_I2C_SCL 18 // MPU6050 I2C 的 SCL 引脚 | ||
#define MPU6050_I2C_FREQ 400000 // MPU6050 I2C 的频率 | ||
#define MPU6050_I2C_PORT_NUM I2C_NUM_0 // MPU6050 的 I2C 端口号 | ||
``` | ||
Next, in [`mpu6050.c`](./mpu6050.c), you should pay attention to the `mpu6050_init_cmd` structure, which provides the initialization commands for the MPU6050. | ||
```c | ||
static uint8_t mpu6050_init_cmd[MPU6050_INIT_CMD_COUNT][2] = { | ||
// format: {address, data} | ||
{0x6B, 0x80}, // PWR_MGMT_1, DEVICE_RESET | ||
{0x6B, 0x00}, // clear SLEEP | ||
{0x1B, 0x18}, // Gyroscope Full Scale Range = ± 2000 °/s | ||
{0x1c, 0x00}, // Accelerometer Full Scale Range = ± 2g | ||
{0x38, 0x00}, // Disable Interrupt | ||
{0x6A, 0x00}, // User Control.auxiliary I2C are logically driven by the primary I2C bus | ||
{0x23, 0x00}, // FIFO Enable.disable | ||
{0x19, 0x63}, // Sample Rate Divider.Sample Rate = 1 kHz / (1 + 99) = 10 Hz | ||
{0x1A, 0x13}, // EXT_SYNC_SET = GYRO_XOUT_L[0]; Bandwidth = 3 | ||
{0x6B, 0x01}, // Power Management 1.PLL with X axis gyroscope reference | ||
{0x6C, 0x00}, // Power Management 2 | ||
}; | ||
``` | ||
|
||
### Call the APIs | ||
|
||
Only two functions are provided in this component. | ||
|
||
#### `esp_err_t mpu6050_init()` | ||
|
||
This function initializes the MPU6050, with the macros and variables you have edited above. | ||
|
||
#### `mpu6050_output_t mpu6050_get_value()` | ||
|
||
This function reads the data from the MPU6050, and returns a `mpu6050_output_t` structure. | ||
|
||
The structure is defined as follows: | ||
|
||
```c | ||
typedef struct { | ||
struct { | ||
int16_t x; int16_t y; int16_t z; | ||
} accel; | ||
int16_t temp; | ||
struct { | ||
int16_t x; int16_t y; int16_t z; | ||
} gyro; | ||
} mpu6050_output_t; | ||
``` | ||
|
||
### Example | ||
|
||
This is an example of running this component which simply | ||
reads the data from the MPU6050 and prints it to the serial port. | ||
|
||
```c | ||
#include "mpu6050.h" | ||
|
||
void app_main(void) | ||
{ | ||
mpu6050_output_t mpu6050_out; | ||
mpu6050_init(); | ||
|
||
while (1) | ||
{ | ||
mpu6050_out = mpu6050_get_value(); | ||
printf("accl_xout: %d\t", mpu6050_out.accel.x); | ||
printf("accl_yout: %d\t", mpu6050_out.accel.y); | ||
printf("accl_zout: %d\n", mpu6050_out.accel.z); | ||
// printf("temp_out: %d\n;", mpu6050_out.temp); | ||
printf("gyro_xout: %d\t", mpu6050_out.gyro.x); | ||
printf("gyro_yout: %d\t", mpu6050_out.gyro.y); | ||
printf("gyro_zout: %d\n", mpu6050_out.gyro.z); | ||
vTaskDelay(100 / portTICK_RATE_MS); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
/** | ||
* @file mpu6050.c | ||
* @brief MPU6050 driver source file | ||
* @author @MaxwellJay256 | ||
*/ | ||
#include "mpu6050.h" | ||
|
||
#define MPU6050_INIT_CMD_COUNT 11 // MPU6050 初始化指令的长度 | ||
/// @brief MPU6050 的初始化指令数组 | ||
static uint8_t mpu6050_init_cmd[MPU6050_INIT_CMD_COUNT][2] = { | ||
// 格式:{寄存器地址, 值} | ||
{0x6B, 0x80}, // PWR_MGMT_1,复位后 DEVICE_RESET 自动清零 | ||
// 此处需要等待,见 mpu6050_init() 函数的 for 循环 | ||
{0x6B, 0x00}, // 清除睡眠模式 | ||
{0x1B, 0x18}, // 陀螺仪满量程配置 = ± 2000 °/s | ||
{0x1c, 0x00}, // 加速度计满量程配置 = ± 2g | ||
{0x38, 0x00}, // 禁用中断 | ||
{0x6A, 0x00}, // 设置 AUX I2C 接口 | ||
{0x23, 0x00}, // 设置 FIFO | ||
{0x19, 0x63}, // 设置采样率为 1 kHz / (1 + 99) = 10 Hz | ||
{0x1A, 0x13}, // 设置数字低通滤波器,带宽为 44 Hz | ||
{0x6B, 0x01}, // 设置系统时钟源为 X 轴陀螺仪 PLL 参考时钟 | ||
{0x6C, 0x00}, // 使能传感器 | ||
}; | ||
|
||
#define ACK_CHECK_EN 0x1 // I2C 主机检查从机的 ACK | ||
#define ACK_CHECK_DIS 0x0 // I2C 主机不检查从机的 ACK | ||
#define ACK_VAL 0x0 // I2C 主机发送 ACK | ||
#define NACK_VAL 0x1 // I2C 主机发送 NACK | ||
|
||
/// @brief 从 MPU6050 的寄存器读取数据 | ||
/// @param i2c_num I2C 端口号 | ||
/// @param reg_addr 要读取的寄存器地址 | ||
/// @param data_rd 用于存储读取数据的缓冲区 | ||
/// @param size 要读取的数据长度 | ||
/// @return ESP_OK: Execute success | ||
static esp_err_t mpu6050_i2c_read( | ||
i2c_port_t i2c_num, uint8_t *reg_addr, uint8_t *data_rd, size_t size) | ||
{ | ||
if (size == 0) | ||
return ESP_OK; | ||
|
||
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); // 创建 I2C 指令 | ||
i2c_master_start(cmd); | ||
i2c_master_write_byte(cmd, (MPU6050_ADDR << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN); // 发送 MPU6050 地址和写入位 | ||
i2c_master_write_byte(cmd, *reg_addr, ACK_CHECK_EN); // 发送寄存器地址 | ||
i2c_master_start(cmd); | ||
i2c_master_write_byte(cmd, (MPU6050_ADDR << 1) | I2C_MASTER_READ, ACK_CHECK_EN); // 发送 MPU6050 地址和读取位 | ||
if (size > 1) | ||
i2c_master_read(cmd, data_rd, size - 1, ACK_VAL); | ||
i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL); // 读取最后一个字节 | ||
i2c_master_stop(cmd); | ||
|
||
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); // 发送 I2C 指令 | ||
i2c_cmd_link_delete(cmd); // 删除 I2C 指令 | ||
return ret; | ||
} | ||
|
||
/// @brief 向 MPU6050 写入数据 | ||
/// @param i2c_num I2C 端口号 | ||
/// @param data_wr 要写入的数据 | ||
/// @param size 要写入的数据长度 | ||
/// @return ESP_OK: Execute success | ||
static esp_err_t mpu6050_i2c_write(i2c_port_t i2c_num, uint8_t *data_wr, size_t size) | ||
{ | ||
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); // 创建 I2C 指令 | ||
i2c_master_start(cmd); | ||
i2c_master_write_byte(cmd, (MPU6050_ADDR << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN); // 发送 MPU6050 地址和写入位 | ||
i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN); // 发送数据 | ||
i2c_master_stop(cmd); | ||
|
||
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS); // 发送 I2C 指令 | ||
i2c_cmd_link_delete(cmd); // 删除 I2C 指令 | ||
return ret; | ||
} | ||
|
||
static const char *TAG = "MPU6050"; | ||
esp_err_t mpu6050_init() | ||
{ | ||
ESP_LOGI(TAG, "MPU6050 Initializing..."); | ||
esp_err_t esp_err; | ||
i2c_config_t conf = { | ||
.mode = I2C_MODE_MASTER, | ||
.sda_io_num = MPU6050_I2C_SDA, | ||
.sda_pullup_en = GPIO_PULLUP_ENABLE, | ||
.scl_io_num = MPU6050_I2C_SCL, | ||
.scl_pullup_en = GPIO_PULLUP_ENABLE, | ||
.master.clk_speed = MPU6050_I2C_FREQ, | ||
}; | ||
|
||
esp_err = i2c_param_config(MPU6050_I2C_PORT_NUM, &conf); | ||
ESP_LOGI(TAG, "i2c_param_config: %d", esp_err); | ||
|
||
esp_err = i2c_driver_install(MPU6050_I2C_PORT_NUM, conf.mode, 0, 0, 0); | ||
ESP_LOGI(TAG, "i2c_driver_install: %d", esp_err); | ||
|
||
for (size_t i = 0; i < MPU6050_INIT_CMD_COUNT; i++) | ||
{ | ||
esp_err = mpu6050_i2c_write(MPU6050_I2C_PORT_NUM, mpu6050_init_cmd[i], 2); | ||
if (i == 0) | ||
vTaskDelay(500 / portTICK_RATE_MS); // 等待复位完成 | ||
} | ||
ESP_LOGI(TAG, "mpu6050_init_cmd: %d", esp_err); | ||
return esp_err; | ||
} | ||
|
||
mpu6050_output_t mpu6050_get_value() | ||
{ | ||
uint8_t *measurement_bytes_out = (uint8_t *)malloc(14); | ||
uint8_t reg_addr = 0x3B; | ||
mpu6050_i2c_read(MPU6050_I2C_PORT_NUM, ®_addr, measurement_bytes_out, 14); | ||
mpu6050_output_t measurement_out = { | ||
.accel = { | ||
.x = (int16_t)(measurement_bytes_out[0] << 8) | measurement_bytes_out[1], | ||
.y = (int16_t)(measurement_bytes_out[2] << 8) | measurement_bytes_out[3], | ||
.z = (int16_t)(measurement_bytes_out[4] << 8) | measurement_bytes_out[5], | ||
}, | ||
.temp = (int16_t)(measurement_bytes_out[6] << 8) | measurement_bytes_out[7], | ||
.gyro = { | ||
.x = (int16_t)(measurement_bytes_out[8] << 8) | measurement_bytes_out[9], | ||
.y = (int16_t)(measurement_bytes_out[10] << 8) | measurement_bytes_out[11], | ||
.z = (int16_t)(measurement_bytes_out[12] << 8) | measurement_bytes_out[13], | ||
}, | ||
}; | ||
|
||
return measurement_out; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* @file mpu6050.h | ||
* @brief MPU6050 driver header file | ||
* @author @MaxwellJay256 | ||
*/ | ||
#ifndef _MPU6050_H_ | ||
#define _MPU6050_H_ | ||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include "esp_err.h" | ||
#include "driver/i2c.h" | ||
#include "esp_log.h" | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
|
||
// 以下宏定义待修改 | ||
#define MPU6050_I2C_SDA 19 // MPU6050 I2C 的 SDA 引脚 | ||
#define MPU6050_I2C_SCL 18 // MPU6050 I2C 的 SCL 引脚 | ||
#define MPU6050_I2C_FREQ 400000 // MPU6050 I2C 的频率 | ||
#define MPU6050_I2C_PORT_NUM I2C_NUM_0 // MPU6050 的 I2C 端口号 | ||
#define MPU6050_ADDR 0x68 // MPU6050 I2C 的地址 b110100(AD0) | ||
|
||
/// @brief 初始化 MPU6050 | ||
/// @return ESP_OK: Init success | ||
esp_err_t mpu6050_init(); | ||
|
||
typedef struct { | ||
struct { | ||
int16_t x; | ||
int16_t y; | ||
int16_t z; | ||
} accel; | ||
int16_t temp; | ||
struct { | ||
int16_t x; | ||
int16_t y; | ||
int16_t z; | ||
} gyro; | ||
} mpu6050_output_t; | ||
|
||
/// @brief 读取 MPU6050 的加速度计、陀螺仪和温度计数据 | ||
/// @return mpu6050_output_t 结构体,包含加速度计、陀螺仪和温度计数据 | ||
mpu6050_output_t mpu6050_get_value(); | ||
|
||
#endif // _MPU6050_H_ |