当前位置: 首页 > news >正文

平衡车 -- MPU6050

🌈个人主页:羽晨同学

💫个人格言:“成为自己未来的主人~” 

传感器原理

此外,用陀螺仪获取x,y,z轴的加速度。

初始化

我们现在对MPU6050进行初始化,MPU6050通过I2C总线与单片机进行通信,通过的是PB8和PB9,并且PB8和PB9需要通过重映射,才可以发挥出I2C总线的功能。

//
// @简介: 对MPU6050进行初始化
//
void App_Mpu6050_Init(void)
{//1. 初始化I2C总线,PB8、PB9 -I2C1//将I2C1的引脚重映射到PB8到PB9RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);//初始化PB8和PB9 - AF_ODRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);}

这个是对I2C1的初始化

	//2. 初始化I2C1// 开启I2C1的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);//设置I2C的参数I2C_InitTypeDef I2C_InitStruct = {0};I2C_InitStruct.I2C_ClockSpeed = 400000;//I2C通信速度I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;//占空比I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;I2C_Init(I2C1,&I2C_InitStruct);

我们对I2C1的速度设置为40000hz,也就是快速模式,然后选择的I2C的模式是标准I2C模式,占空比为2比1.我们选用快速模式的时候,一般选择的占空比就是2比1的。

寄存器部分

接下来,我们要配置寄存器部分。

所以,我们接下来封装一下读写寄存器的函数。

//
// @简介:写寄存器函数
// @参数 reg - 要写入的寄存器的地址
// @参数 value - 要写入的值
//
static void reg_write(uint8_t reg,uint8_t value)
{uint8_t bytesToSend[] = {reg,value};My_I2C_SendBytes(I2C1,0xd0,bytesToSend,2);
}
//
// @简介:读寄存器函数
// @参数 reg - 要读取的寄存器的地址
// @返回值:表示读取到的值
//
static uint8_t reg_read(uint8_t reg)
{My_I2C_SendBytes(I2C1,0xd0,&reg,1);uint8_t regValue;My_I2C_ReceiveBytes(I2C1,0xd0,&regValue,1);return regValue;
}

然后,我们对寄存器的参数进行配置

	// 2. 设置MPU6050的参数reg_write(0x6b,0x80);//复位Delay(100);reg_write(0x1b,0x18);//将陀螺仪的量程设置为+-2000°/sreg_write(0x1c,0x00);//将加速度计的量程设置为+-2g

接下来,我们对MPU6050的值进行更新

//
//@简介: MPU6050的数据更新函数
//
void App_MPU6050_Update(void)
{int16_t ax_raw = (int16_t)((reg_read(0x3b)<<8)+reg_read(0x3c));//ax的原始数据int16_t ay_raw = (int16_t)((reg_read(0x3d)<<8)+reg_read(0x3e));//ay的原始数据int16_t az_raw = (int16_t)((reg_read(0x3f)<<8)+reg_read(0x40));//az的原始数据int16_t temperature_raw = (int16_t)((reg_read(0x41)<<8)+reg_read(0x42));//温度的原始数据int16_t gx_raw = (int16_t)((reg_read(0x43)<<8)+reg_read(0x44));//gx的原始数据int16_t gy_raw = (int16_t)((reg_read(0x45)<<8)+reg_read(0x46));//gy的原始数据int16_t gz_raw = (int16_t)((reg_read(0x47)<<8)+reg_read(0x48));//gz的原始数据	
}

然后我们对数值进行更新:

void App_MPU6050_Update(void)
{int16_t ax_raw = (int16_t)((reg_read(0x3b)<<8)+reg_read(0x3c));//ax的原始数据int16_t ay_raw = (int16_t)((reg_read(0x3d)<<8)+reg_read(0x3e));//ay的原始数据int16_t az_raw = (int16_t)((reg_read(0x3f)<<8)+reg_read(0x40));//az的原始数据ax = ax_raw * 6.1035e-5f;ay = ay_raw * 6.1035e-5f;az = az_raw * 6.1035e-5f;int16_t temperature_raw = (int16_t)((reg_read(0x41)<<8)+reg_read(0x42));//温度的原始数据//temperature = temperature_raw/340 +36.53;//MPU6050temperature = temperature_raw/333.87f+21.0f;//MPU6500int16_t gx_raw = (int16_t)((reg_read(0x43)<<8)+reg_read(0x44));//gx的原始数据int16_t gy_raw = (int16_t)((reg_read(0x45)<<8)+reg_read(0x46));//gy的原始数据int16_t gz_raw = (int16_t)((reg_read(0x47)<<8)+reg_read(0x48));//gz的原始数据	gx = gx_raw * 6.1035e-2f;gy = gy_raw * 6.1035e-2f;gz = gz_raw * 6.1035e-2f;
}

然后我们创建一个接口函数,将更新到的值进行导出

float App_MPU6050_GetAx(void)
{return ax;
}
float App_MPU6050_GetAy(void)
{return ay;
}
float App_MPU6050_GetAz(void)
{return az;
}
float App_MPU6050_Temperature(void)
{return temperature;
}
float App_MPU6050_GetGx(void)
{return gx;
}
float App_MPU6050_GetGy(void)
{return gy;
}
float App_MPU6050_GetGz(void)
{return gz;
}

解算欧拉角

陀螺仪解算欧拉角

static float yaw,pitch,roll;//单位是°
//
// @简介:MPU6050的进程函数,计算欧拉角
//
void App_MPU6050_Proc(void)
{static uint32_t nxt = 0;//下次程序运行的时间if(GetTick() < nxt) return;App_MPU6050_Update();//通过陀螺仪的测量结果计算欧拉角yaw = yaw + gz * 0.005;pitch = pitch + gx * 0.005;roll = roll - gy * 0.005;nxt += 5;
}
//

这样,我们就会每5ms来执行一次这个程序

为了简化这个步骤,我们也可以这样子写

//
// @简介:MPU6050的进程函数,计算欧拉角
//
void App_MPU6050_Proc(void)
{PERIODIC(5);App_MPU6050_Update();//通过陀螺仪的测量结果计算欧拉角yaw = yaw + gz * 0.005;pitch = pitch + gx * 0.005;roll = roll - gy * 0.005;}

接下来,我们对这个部分进行测试

//
// @简介: 用来测试欧拉角
//
void MPU6050_EularAngleTest(void)
{App_Usart_Init();App_Mpu6050_Init();	while(1){App_MPU6050_Proc();Uasrt2_Proc();}}
static void Uasrt2_Proc(void)
{PERIODIC(10)float ax = App_MPU6050_GetAx();float ay = App_MPU6050_GetAy();float az = App_MPU6050_GetAz();float temperature = App_MPU6050_Temperature();float gx = App_MPU6050_GetGx();float gy = App_MPU6050_GetGy();float gz = App_MPU6050_GetGz();float yaw = App_MPU6050_GetYaw();float pitch = App_MPU6050_GetPitch();float roll = App_MPU6050_GetRoll();My_USART_Printf(USART2,"%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",ax,ay,az,temperature,gx,gy,gz,yaw,pitch,roll);
}

加速度计解算欧拉角

我们一般是会使用加速度计来计算俯仰角和翻滚角,一般不会使用加速度计来计算偏航角,因为重力对于平面上的影响是非常小的。重力向量在设备坐标系中的投影变化,直接反映了设备的Pitch和Roll角度。重力是这些角度的“绝对参考”。重力向量与设备的偏航角是完全解耦的,它不提供任何关于偏航方向的信息。所以我们不会用来计算偏航角。

	//通过加速度计解算欧拉角yaw = 0;pitch = atan2(ay,az) / 3.1415927f * 180.0f;roll = atan2(ax,az) / 3.1415927f * 180.0f;

用陀螺仪是有漂移问题的,而加速度计有噪声,所以我们用互补滤波器来解决这种问题。

//
// @简介:MPU6050的进程函数,计算欧拉角
//
void App_MPU6050_Proc(void)
{PERIODIC(5);App_MPU6050_Update();//通过陀螺仪的测量结果计算欧拉角float yaw_g = yaw + gz * 0.005;float pitch_g = pitch + gx * 0.005;float roll_g = roll - gy * 0.005;//通过加速度计解算欧拉角float yaw_a = 0;float pitch_a = atan2(ay,az) / 3.1415927f * 180.0f;float roll_a = atan2(ax,az) / 3.1415927f * 180.0f;//使用互补滤波器yaw = yaw_g;pitch = 0.95238 * pitch_g + (1-0.95238) * pitch_a;roll = 0.95238 * roll_g + (1-0.95238) * roll_a;
}

好了,今天的内容就到这里,明天再见


文章转载自:

http://1AK0KLGs.bqpgq.cn
http://nOIzmDM0.bqpgq.cn
http://pWBVZzDY.bqpgq.cn
http://liBRULfy.bqpgq.cn
http://V9slcN0x.bqpgq.cn
http://FT9ICQae.bqpgq.cn
http://Nmcv0oCX.bqpgq.cn
http://NhsDf4PF.bqpgq.cn
http://spJf5Ugb.bqpgq.cn
http://gG1Xg8yT.bqpgq.cn
http://VM1f9Le3.bqpgq.cn
http://4Dtk3eYu.bqpgq.cn
http://5dc68xsV.bqpgq.cn
http://afrzEGD0.bqpgq.cn
http://tT798AsH.bqpgq.cn
http://ALHlLrZz.bqpgq.cn
http://LPf1808a.bqpgq.cn
http://huI1yL5B.bqpgq.cn
http://FSu2ms5K.bqpgq.cn
http://3cUYaa09.bqpgq.cn
http://lulzXzDz.bqpgq.cn
http://aQcagkUo.bqpgq.cn
http://J49cH14E.bqpgq.cn
http://pwa9JHYA.bqpgq.cn
http://FC8bUWDi.bqpgq.cn
http://Ghc8n3cB.bqpgq.cn
http://a0WvuMqS.bqpgq.cn
http://FogtcFFM.bqpgq.cn
http://lhkLfF93.bqpgq.cn
http://9eFzvEBV.bqpgq.cn
http://www.dtcms.com/a/374108.html

相关文章:

  • 【PyTorch】图像二分类
  • 自动驾驶中的传感器技术39——Radar(0)
  • 【进阶版两种方法 | 题解】洛谷 P4285 [SHOI2008] 汉诺塔 [数学分析递推]
  • DFT学习--文献
  • 多轻量算轻量
  • GITHUB 项目推荐:DAIR.AI 提示词工程指南
  • DAMA数据管理|4数据管理的挑战-价值要度量
  • 【LLM微调2】
  • springboot minio 存储入门与实战
  • RabbitMQ 幂等性, 顺序性 和 消息积压
  • 单片机按键示例功能
  • Enable FIPS in ubuntu (by quqi99)
  • OpenAI的开源王牌:gpt-oss上手指南与深度解析
  • 使用nvidia-ml-py监控与管理GPU资源
  • 鹧鸪云光储流程系统全新升级:视频指引与分阶段模块使用指南
  • qx-13 开发数据服务总线
  • GD32入门到实战44--LVGL使用外部SRAM
  • 硬件驱动芯片——I.MX6ULL芯片(1)
  • MV190E0M-N10 工业广视角液晶模组技术白皮书
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年9月8日第173弹
  • 机器视觉的手机柔性屏贴合应用
  • 【PyTorch】图像二分类-部署
  • 纵向循环缓慢滚动图片
  • 项目日记 -日志系统 -明确目标、规划模块并完成项目文档
  • 【C++上岸】C++常见面试题目--网络篇(第二十二期)
  • 数据治理系列(一):数据治理的整体框架与发展趋势
  • 【LeetCode 每日一题】1504. 统计全 1 子矩形
  • FastGPT源码解析 Agent知识库文本资料处理详解和代码分析
  • php 实现 导入excel 带图片导入
  • JP4-7-MyLesson后台前端(五)