文章目录

  • 1 简介
  • 2 MPU6050
  • 3 工作原理
  • 4 单片机与MPU6050通信
    • 4.1 mpu6050 数据格式
    • 4.2 倾角计算方法
  • 5 实现代码
  • 6 最后

1 简介

Hi,大家好,这里是丹成学长,今天向大家介绍一个学长做的单片机项目

教程:MPU6050姿态解算

大家可用于 课程设计 或 毕业设计

单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052

2 MPU6050

MPU6050是一种非常流行的空间运动传感器芯片,可以获取器件当前的三个加速度分量和三个旋转角速度。由于其体积小巧,功能强大,精度较高,不仅被广泛应用于工业,同时也是航模爱好者的神器,被安装在各类飞行器上驰骋蓝天。

随着Arduino开发板的普及,许多朋友希望能够自己制作基于MPU6050的控制系统,但由于缺乏专业知识而难以上手。此外,MPU6050的数据是有较大噪音的,若不进行滤波会对整个控制系统的精准确带来严重影响。

MPU6050芯片内自带了一个数据处理子模块DMP,已经内置了滤波算法,在许多应用中使用DMP输出的数据已经能够很好的满足要求。关于如何获取DMP的输出数据,我将在以后的文章中介绍。本文将直接面对原始测量数据,从连线、芯片通信开始一步一步教你如何利用Arduino获取MPU6050的数据并进行卡尔曼滤波,最终获得稳定的系统运动状态。

3 工作原理


加速度计采用压电效应的工作原理,就像上面的图片一样,在一个立方体的盒子里面有一个小球,盒子的四壁是用压电晶体材料,当盒子倾斜时,由于重力的作用,球就会向倾斜的方向移动,当小球碰到墙壁就会产生压电电流。盒子中有上下、左右、前后三对相对的墙壁,每一对墙对应于三维空间中的一个轴:X轴、Y轴、Z轴。根据压电壁产生的电流,我们就可以确定倾角的方向和大小。

4 单片机与MPU6050通信

这里以arduino单片机为例

为避免纠缠于电路细节,我们直接使用集成的MPU6050模块。MPU6050的数据接口用的是I2C总线协议,因此我们需要Wire程序库的帮助来实现Arduino与MPU6050之间的通信。请先确认你的Arduino编程环境中已安装Wire库。

Wire库的官方文档中指出:在UNO板子上,SDA接口对应的是A4引脚,SCL对应的是A5引脚。MPU6050需要5V的电源,可由UNO板直接供电。按照下图连线。

4.1 mpu6050 数据格式

我们感兴趣的数据位于0x3B到0x48这14个字节的寄存器中。这些数据会被动态更新,更新频率最高可达1000HZ。下面列出相关寄存器的地址,数据的名称。注意,每个数据都是2个字节。

  • 0x3B,加速度计的X轴分量ACC_X
  • 0x3D,加速度计的Y轴分量ACC_Y
  • 0x3F,加速度计的Z轴分量ACC_Z
  • 0x41,当前温度TEMP
  • 0x43,绕X轴旋转的角速度GYR_X
  • 0x45,绕Y轴旋转的角速度GYR_Y
  • 0x47,绕Z轴旋转的角速度GYR_Z

4.2 倾角计算方法

Roll-pitch-yaw模型与姿态计算

表示飞行器当前飞行姿态的一个通用模型就是建立下图所示坐标系,并用Roll表示绕X轴的旋转,Pitch表示绕Y轴的旋转,Yaw表示绕Z轴的旋转。



Yaw角的问题

因为没有参考量,所以无法求出当前的Yaw角的绝对角度,只能得到Yaw的变化量,也就是角速度GYR_Z。当然,我们可以通过对GYR_Z积分的方法来推算当前Yaw角(以初始值为准),但由于测量精度的问题,推算值会发生漂移,一段时间后就完全失去意义了。然而在大多数应用中,比如无人机,只需要获得GRY_Z就可以了。

如果必须要获得绝对的Yaw角,那么应当选用MPU9250这款九轴运动跟踪芯片,它可以提供额外的三轴罗盘数据,这样我们就可以根据地球磁场方向来计算Yaw角了,具体方法此处不再赘述。

5 实现代码

// 本代码版权归Devymex所有,以GNU GENERAL PUBLIC LICENSE V3.0发布
// http://www.gnu.org/licenses/gpl-3.0.en.html
// 相关文档参见作者于知乎专栏发表的原创文章:
// http://zhuanlan.zhihu.com/devymex/20082486//连线方法
//MPU-UNO
//VCC-VCC
//GND-GND
//SCL-A5
//SDA-A4
//INT-2 (Optional)#include <Kalman.h>
#include <Wire.h>
#include <Math.h>float fRad2Deg = 57.295779513f; //将弧度转为角度的乘数
const int MPU = 0x68; //MPU-6050的I2C地址
const int nValCnt = 7; //一次读取寄存器的数量const int nCalibTimes = 1000; //校准时读数的次数
int calibData[nValCnt]; //校准数据unsigned long nLastTime = 0; //上一次读数的时间
float fLastRoll = 0.0f; //上一次滤波得到的Roll角
float fLastPitch = 0.0f; //上一次滤波得到的Pitch角
Kalman kalmanRoll; //Roll角滤波器
Kalman kalmanPitch; //Pitch角滤波器void setup() {Serial.begin(9600); //初始化串口,指定波特率Wire.begin(); //初始化Wire库WriteMPUReg(0x6B, 0); //启动MPU6050设备Calibration(); //执行校准nLastTime = micros(); //记录当前时间
}void loop() {int readouts[nValCnt];ReadAccGyr(readouts); //读出测量值float realVals[7];Rectify(readouts, realVals); //根据校准的偏移量进行纠正//计算加速度向量的模长,均以g为单位float fNorm = sqrt(realVals[0] * realVals[0] + realVals[1] * realVals[1] + realVals[2] * realVals[2]);float fRoll = GetRoll(realVals, fNorm); //计算Roll角if (realVals[1] > 0) {fRoll = -fRoll;}float fPitch = GetPitch(realVals, fNorm); //计算Pitch角if (realVals[0] < 0) {fPitch = -fPitch;}//计算两次测量的时间间隔dt,以秒为单位unsigned long nCurTime = micros();float dt = (double)(nCurTime - nLastTime) / 1000000.0;//对Roll角和Pitch角进行卡尔曼滤波float fNewRoll = kalmanRoll.getAngle(fRoll, realVals[4], dt);float fNewPitch = kalmanPitch.getAngle(fPitch, realVals[5], dt);//跟据滤波值计算角度速float fRollRate = (fNewRoll - fLastRoll) / dt;float fPitchRate = (fNewPitch - fLastPitch) / dt;//更新Roll角和Pitch角fLastRoll = fNewRoll;fLastPitch = fNewPitch;//更新本次测的时间nLastTime = nCurTime;//向串口打印输出Roll角和Pitch角,运行时在Arduino的串口监视器中查看Serial.print("Roll:");Serial.print(fNewRoll); Serial.print('(');Serial.print(fRollRate); Serial.print("),\tPitch:");Serial.print(fNewPitch); Serial.print('(');Serial.print(fPitchRate); Serial.print(")\n");delay(10);
}//向MPU6050写入一个字节的数据
//指定寄存器地址与一个字节的值
void WriteMPUReg(int nReg, unsigned char nVal) {Wire.beginTransmission(MPU);Wire.write(nReg);Wire.write(nVal);Wire.endTransmission(true);
}//从MPU6050读出一个字节的数据
//指定寄存器地址,返回读出的值
unsigned char ReadMPUReg(int nReg) {Wire.beginTransmission(MPU);Wire.write(nReg);Wire.requestFrom(MPU, 1, true);Wire.endTransmission(true);return Wire.read();
}//从MPU6050读出加速度计三个分量、温度和三个角速度计
//保存在指定的数组中
void ReadAccGyr(int *pVals) {Wire.beginTransmission(MPU);Wire.write(0x3B);Wire.requestFrom(MPU, nValCnt * 2, true);Wire.endTransmission(true);for (long i = 0; i < nValCnt; ++i) {pVals[i] = Wire.read() << 8 | Wire.read();}
}//对大量读数进行统计,校准平均偏移量
void Calibration()
{float valSums[7] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0};//先求和for (int i = 0; i < nCalibTimes; ++i) {int mpuVals[nValCnt];ReadAccGyr(mpuVals);for (int j = 0; j < nValCnt; ++j) {valSums[j] += mpuVals[j];}}//再求平均for (int i = 0; i < nValCnt; ++i) {calibData[i] = int(valSums[i] / nCalibTimes);}calibData[2] += 16384; //设芯片Z轴竖直向下,设定静态工作点。
}//算得Roll角。算法见文档。
float GetRoll(float *pRealVals, float fNorm) {float fNormXZ = sqrt(pRealVals[0] * pRealVals[0] + pRealVals[2] * pRealVals[2]);float fCos = fNormXZ / fNorm;return acos(fCos) * fRad2Deg;
}//算得Pitch角。算法见文档。
float GetPitch(float *pRealVals, float fNorm) {float fNormYZ = sqrt(pRealVals[1] * pRealVals[1] + pRealVals[2] * pRealVals[2]);float fCos = fNormYZ / fNorm;return acos(fCos) * fRad2Deg;
}//对读数进行纠正,消除偏移,并转换为物理量。公式见文档。
void Rectify(int *pReadout, float *pRealVals) {for (int i = 0; i < 3; ++i) {pRealVals[i] = (float)(pReadout[i] - calibData[i]) / 16384.0f;}pRealVals[3] = pReadout[3] / 340.0f + 36.53;for (int i = 4; i < 7; ++i) {pRealVals[i] = (float)(pReadout[i] - calibData[i]) / 131.0f;}
}

实现效果:

单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052

6 最后

【毕业设计】MPU6050姿态解算 姿态估计 - 物联网 单片机 stm32相关推荐

  1. MPU6050卡尔曼滤波解算姿态角

    前言 自己在课上吹的牛,课程作业再麻烦也得干.模了好几天鱼,终于在DDL前一天弄完了惯导模块的简单demo,卡尔曼滤波算是我弄的最久的了(大概2-3天),虽然没有彻底弄懂原理(概率论没学,隐马尔可夫链 ...

  2. 四旋翼无人机飞控系统设计(姿态解算)

    姿态解算   姿态传感器读出加速度和角速度,而对一个系统的自动控制往往需要更加上层和贴近应用的的一个属性:角度.所以需要通过加速度和角速度进行数据融合转化得到姿态角度.   以MPU6050为例,姿态 ...

  3. 基于STM32F407四旋翼无人机 --- 姿态解算讲解(四元数)(叉积法融合陀螺仪数据和加速度数据)(五)

    基于STM32F407四旋翼无人机 --- 姿态解算讲解(五) 姿态解算 姿态解算定义 欧拉角 四元数 四元数性质 方向余弦矩阵 四元数方向余弦矩阵 叉积法融合陀螺仪数据和加速度数据 叉积运算 一阶龙 ...

  4. Arduino 与 MPU6050 姿态解算+ PROCESSING

    2019独角兽企业重金招聘Python工程师标准>>> 买的MPU6050自带姿态解算大大减轻了上层处理器所做的工作. 通过熟悉了一下processing之后做了一个小例子更是感觉这 ...

  5. 从MPU6050了解姿态解算

    前言 最近正在学习和陀螺仪有关的知识,要将陀螺仪用到期末大作业中,代码还处在调试阶段,目前先总结一下学到的理论知识,学习资料来源 三维转动的四元数表述 - 中国知网 (cnki.net) MPU605 ...

  6. MPU6050姿态解算1-DMP方式

    MPU6050的姿态解算方法有多种,包括硬件方式的DMP解算,软件方式的欧拉角与旋转矩阵解算,软件方式的轴角法与四元数解算.本篇先介绍最易操作的DMP方式. MPU6050基本功能 3轴陀螺仪 陀螺仪 ...

  7. MPU6050介绍及姿态解算

    1.介绍:MPU6050 是 InvenSense 公司推出的全球首款整合性 6 轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时之轴间差的问题,减少了安装空间. (1)绕X轴旋转角度为r ...

  8. android 陀螺仪滤波_Arduino MPU6050陀螺仪运用卡尔曼滤波姿态解算实验

    Arduino MPU6050陀螺仪运用卡尔曼滤波姿态解算实验 版权声明:本文为博主原创文章,未经博主允许不得转载. 2019年3月20日 发布 实例效果 输出效果: 首先看看本例程XYZ轴的输出效果 ...

  9. android 陀螺仪滤波_Arduino+mpu6050陀螺仪运用卡尔曼滤波姿态解算实验

    MPU6050六轴陀螺仪 作用于四轴无人机,平衡车,机器人等等的电子实作当中,用于姿态判断,掌握了可以发挥自己的想象完成更多更有趣的作品. 本例程输出XYZ的角度,正负90度. 运用卡尔曼滤波算法解算 ...

最新文章

  1. 产权分割商铺,太坑人!
  2. linux下oracle数据库的启动和关闭
  3. linux面试题-基础题1
  4. Markdown编辑器攻略——字体,字号,颜色
  5. numpy如何直接在数组上进行添加_NumPy 论文登上了 Nature!
  6. 何时才有Email发布功能
  7. 前端学习(2822):页面配置文件
  8. LeetCode MySQL 1661. 每台机器的进程平均运行时间
  9. GitHub#SQL#:SQL必知必会
  10. 电脑显示屏亮度怎么调_金合光电丨深圳led显示屏厂家为您诠释行业专业术语
  11. shell下的常用语句
  12. 大数据在银行的七个应用实例
  13. 区块链行业被攻击怎么办?
  14. i3 10105f对比i5 10400f选哪个好
  15. linux格式化u盘为ntfs格式,Linux上格式化U盘为NTFS格式
  16. 【重要】国庆节快乐!有三AI所有课程限时7天优惠
  17. Linux系统必学必会知识点整理
  18. 泰坦尼克号数据挖掘项目实战——Task7 模型融合
  19. oracle 提示ORA-00942: 表或视图不存在,但是plsql查询有数据,解决办法
  20. 城市“断气”敲警钟 资源“价改”正逢时?

热门文章

  1. Python从视频抽取帧保存为图片
  2. 机器学习入门--手写体识别
  3. python二手交易平台代码_使用Python探索二手车市场(含代码)
  4. 兴澄特钢计算机中心怎么样,信息学院案例中心举办传统企业数字化转型——兴澄特钢数字钢资产案例研讨会...
  5. Node之父发布新项目deno:下一代Node;百度推出没有广告的简单搜索;甲骨文计划砍掉Java序列化功能;丨Q新闻...
  6. If ngModel is used within a form tag, either the name attribute must be set or the form control must
  7. linux .desktop,桌面应用|为你的 Linux 应用创建 .desktop 文件
  8. 华为IOT,技术干货
  9. Amap套件说明--kali
  10. python股票项目分析图