文章目录

  • 一、前情提要
  • 二、STM32CubeMX配置
  • 三、寄存器介绍
  • 四、Keil代码介绍
  • 总结

本次调试的传感器是正点原子的MPU6050(三轴陀螺仪+三轴加速度)。因为我的毕设中并不要求解算出欧拉角,只是用来反映风电机组(demo)的振动情况即可。为了简化, 所以我只使用了三轴加速度计,但是在这篇介绍中,采用了硬件I2C来读取了硬件传感器原始数据,并对这些数据进行了 卡尔曼滤波

一、前情提要

这部分的问题是我在刚接触这个传感器的几个问题,通过自己查阅资料有了个大致的了解。因此在这里想分享一下。感谢各位大佬们的分享,让我不断地可以学习。

我看了1个博客和1个小破站上的视频,感觉博主和UP主讲的很好
小破站视频: https://www.bilibili.com/video/BV1sL411F7fu?spm_id_from=333.337.search-card.all.click
知乎博客: https://zhuanlan.zhihu.com/p/195683958
代码参考视频: https://www.bilibili.com/video/BV1qf4y1r73k?spm_id_from=333.337.search-card.all.click

这些问题也是我自己的理解,仅供参考,有不正确之处,欢迎大家指出,我的邮箱:2802433362@qq.com

1.你能解释一下这种N轴IMU常见的一些概念吗?
(1)笛卡尔坐标系:

在下面实际中的这张图好像跟上面的不太一样啊,其实我们旋转一下就好了,我说这个的目的是在姿态解算的时候,我们经常会旋转坐标系,注意XYZ轴的位置关系千万不要搞混了,有时候我自己也是多旋转就乱了,所以可以借助右手坐标系来帮助我们理解。

(2)欧拉角:我们常说的欧拉角指的是ROLL(横滚角)、偏航角(Yaw)、俯仰角(Pitch)。具体的大家可以根据下面的模型来进行理解。知乎博主“码农爱学习”写的真的不错,简单易懂,很适合我们这种小白。“https://zhuanlan.zhihu.com/p/195683958”,我敢我再写下去也是照搬人家的东西,博主概括的真的很全。

(3)四元素:他是表示旋转的另一种方式,可以与欧拉角进行转化,具体的话可以参考CSDN的另外一个博主的文章:https://blog.csdn.net/xiaoma_bk/article/details/79082629
(4)陀螺仪传感器:这个是涉及到很多物理方面的东西,我们可以简单的认为它可以X、Y、Z轴的角速度。
(5)加速度计传感器:测量的是X、Y、Z的加速度。
(6)磁力计传感器:测量的3轴磁场强度(这个目前我也不是很熟,后面要慢慢用起来的)

2. 我在网上查阅的资料看到有3轴、6轴、9轴、10轴传感器你能解释一下有什么区别吗?
(1) 3轴传感器是指3轴陀螺仪。 它测量的是3个轴(XYZ)的角速度,其实通过这三个数据也能进行姿态解算得到三个欧拉角(俯仰角、横滚角、偏航角),因此他也是可以独立工作的,出现了市面上常见的3轴传感器。但是这个传感器存在的问题是:
(a)因为它的计算方式的角度=角速度*dt,大家学过高数和大学物理,当dt很小时,我们可以把物体看成匀速运动,但是这样造成的问题是不太符合实际情况,我们只是假设这样子,会有较大的累积误差;
(b)之前看那个博主说,只使用3轴陀螺仪会出现相位差的问题(这部分我不是很懂,后面需要去补充一些知识)。
伟大的前辈们也知道这个问题,所以一个神奇的想法就产生了,能不能用两个传感器,相互校正一下,然后取个平均啥的(传感器融合当然没这么简单,此处只是举个栗子),应该能精确很多吧。但是从两个角度来做效果应该更好,因为再加一个3轴陀螺仪,就没多大必要(此处我也不知道解释比较好,就是那种本来这个误差就大,换个角度去测量会更好,而不是叠罗汉。),于是6轴加速度就产生了。
(2)6轴传感器是指3轴陀螺仪+3轴加速度计。 3轴加速度计测量的就是XYZ轴上的加速度g的一个分量。当这个坐标系很正的时候,三轴的数值应该为aacx=0g、aacy=0g、aacz=1*g,其中9为重力加速度,9.8m/s2。当这个传感器有一个倾斜的话,g在x轴和y轴上就会有个分量,有可能就变成了aacx=0.3g、aacy=0.2g、aacz=0.7g,我们其实可以根据这些数据得到三个欧拉角,所有单独用加速度计也可以进行姿态结算,但是如果单独用的话我们是无法解算出偏航的角的。可以参考下面的推导公式,我们通过传感器得到的是ax、ay、az但是我们通过推导发现y没了(p代表pitch俯仰角、r表示raw横滚角、y表示yaw偏航角),数学就是这么神奇,哈哈,想不到吧,所以3轴加速度计只能解算出pitch角和raw角,所以6轴传感器的yaw(偏航角会一直漂移),而pitch(俯仰角)和raw(横滚角)通过数据融合算法可以得到较为稳定的值。,目前常用的数据融合算法是DMP和卡尔曼滤波。卡尔曼滤波不得不说是一个很神奇的东西,此处强烈感谢卡尔曼前辈能研究出这么优秀又通用的算法。

(3)9轴传感器是指3轴陀螺仪+3轴加速度计+3轴磁力计。加3轴磁力计的目的大家可能可以猜到的啦,可以把偏航角也给校准了,这样可以得到较为稳定的3个欧拉角(或者稳定的四元组),具体的解算过程大家可以参考上面推荐的知乎博客,大佬写的真的不错,当然小破站上的小哥哥的那个视频讲的也很清楚,再次感谢大佬们。我这次没有选用类似MPU9250的9轴传感器,一是因为我并不需要进行姿态计算,二是因为我的整个系统存在电机和钢轴,会对磁力计的校准影响很大,不能起到相应的效果。因此大家在使用的时候应该主要有磁场校准影响的情况。
9轴传感器不是已经很完美了吗?可以完全把姿态计算出来,10轴传感器又是啥哩
(4)10轴传感器是指3轴陀螺仪+3轴加速度计+3轴磁力计+1个气压计,这个可以把气压高度计算出来,我认为这个是锦上添花的作用。 ,当然存在即是合理,自然有它的应用场景。

3. 网上说的DMP算法和卡尔曼滤波你能简要说一下他们是什么吗?
(1)对于DMP算法:可以参考知乎博主“码农爱学习”的这篇文章:https://zhuanlan.zhihu.com/p/165156300
复制他的一段话:DMP就是MPU6050内部的运动引擎,全称Digital Motion Processor,直接输出四元数,可以减轻外围微处理器的工作负担且避免了繁琐的滤波和数据融合。 就我们使用的诸如MPU6050、MPU9250等来说,DMP是硬件融合,就是商家已经做了硬件的嵌入,我们只需要调用相应的驱动库即可,这样可以很方便的,具体的一些驱动程序可以参考正点原子的驱动程序。
(2)对于卡尔曼滤波算法: 利用加速度计采集的3轴加速度计进行姿态融合成的pitch、roll作为观测值, 利用陀螺仪采集的3轴角度值进行的姿态融合成的pitch,yaw,raw作为测量值。所以利用卡尔曼滤波可以实现pitch(俯仰角)、roll(横滚角)的稳定输出。
(3)下面还是引用知乎博主“码农爱学习”中的内容:这部分其实反映的是卡尔曼滤波的思想,K其实指的是卡尔曼增益,这部分我们可以这样理解:每个传感器都可以进行姿态解算,得到自己的三个欧拉角,而我们希望把这些融合(直接取平均的方式显然太low)了。因为每个传感器都有自己的优缺点,我们应该把每个传感器的优点利用起来会使结果更加地准确,因此前辈们提取了每个传感器权重不同的方法来进行融合,至于这个权重到底是多少,卡尔曼老先生在自己的论文中有明确的推导(卡尔曼滤波最经典的那5个方程:2个预测方程,3个更新方程)。此处不再多做介绍,大家如果对卡尔曼滤波原理什么的想要有更深的了解,可以自行搜索,后面我也会自己出一期我自己对卡尔曼滤波的理解。

二、STM32CubeMX配置

有了上面的一些基础概念和了解,我们下面开始配置STM32CubeMX
(1) 在“SYS”设置为“SW”调试模式;

(2)我们在“RCC”中选择外部晶振模式;

(3) 因为MPU6050采用的通信协议是I2C,而我们又想采用硬件I2C去开发,所以必须进行勾选。

(4)因为我们想把数据打印到电脑的“串口调试助手”,所以我们需要开一路串口,波特率为115200;

(5)我们下面配置时钟树;

(6)将这个工程存放在文件夹中,整个目录最好不要有中文,因为后面自动生成代码的时候并不能直接打开,不过问题也不大,需要自己去相关文件夹中的找到工程文件打开;

(7)我们勾选一下我们希望生成文件的配置。

到此为止,我们的配置就已经完成了。

三、寄存器介绍

对于传感器而言,寄存器是很重要的东西,所以我们想要使用一个传感器,一定要清楚他的寄存器怎样配置,数据存储在哪个寄存器中
(其实我在学习的时候也不喜欢看手册,但是咱们都是搞这个的,datasheet肯定要看的,后面我们能形成属于自己的一套看datasheet的流程和经验,会很舒服的)。我这里只是介绍一下我再这次调试中用到的寄存器,具体的每一个比特位到底表示什么大家自己查手册就好了。








四、Keil代码介绍

这部分是参考小破站上的视频讲解:https://www.bilibili.com/video/BV1qf4y1r73k?spm_id_from=333.337.search-card.all.click(俺是妥妥自己搬运工具人,同时加上自己的一点理解)。关于我们应该对I2C通信有个简单的了解吧(不了解的话,小破绽也有很多资源,我比较推荐的是创客学院的武老师的讲解)。对于I2C设备,都有一个自己的设备地址,我们首先要做的知道设备地址。

(1)首先我们进行多串口重映像,在“usart.h”文件中添加以下代码;

#include "stdarg.h"
#include "string.h"
#include "stdio.h"

(2)在“usart.c”文件中添加下面的代码;

#define TXBUF_SIZE_MAX 100
void usart2_printf(const char *format, ...)
{va_list args;uint32_t length;uint8_t txbuf[TXBUF_SIZE_MAX] = {0};va_start(args, format);length = vsnprintf((char *)txbuf, sizeof(txbuf), (char *)format, args);va_end(args);HAL_UART_Transmit(&huart2, (uint8_t *)txbuf, length, HAL_MAX_DELAY);memset(txbuf, 0, TXBUF_SIZE_MAX);
}

(3)对于类似树莓派的Linux系统中我们可以通过I2C查询的指令即可实现,当然,STM32也有相应的程序可以查看:

for (uint8_t i=0; i<255;i++)
{if(HAL_I2C_IsDeviceReady(&hi2c1, i ,1, 1000) == HAL_OK)    //寻找设备地址,I2C原装函数      {       usart2_printf("%d\r\n",i);break;}.
}

我们在串口中可以看到返回值,我返回的是208,转换成16进制数据为0xD0,所以我们的I2C设备地址为0xD0。
(4)下面我们在“main.c”文件中 添加宏定义:

//***************************************MPU6050是地址***********************************//
#define MPU6050_ADDR 0xD0
//*******************************通过查看芯片手册相关传感器地址**************************//
#define SMPLRT_DIV_REG 0x19
#define GYRO_CONFIG_REG 0x1B
#define ACCEL_CONFIG_REG 0x1c
#define ACCEL_XOUT_H_REG 0x3B
#define TEMP_OUT_H_REG 0x41
#define GYRO_XOUT_H_REG 0x43
#define PWR_MGMT_1_REG 0x6B   //电源管理1寄存器
#define WHO_AM_I_REG 0x75
//************************加速度计*********************//
int16_t Accel_X_RAW = 0;
int16_t Accel_Y_RAW = 0;
int16_t Accel_Z_RAW = 0;
//***********************陀螺仪***********************//
int16_t Gyro_X_RAW = 0;
int16_t Gyro_Y_RAW = 0;
int16_t Gyro_Z_RAW = 0;
int16_t Temp_RAW = 0;
float Ax,Ay,Az,Gx,Gy,Gz,Temp;    //将最后读取的值放入这些变量中

(5)进行MPU6050初始化,配置一些寄存器;

void MPU6050_Init(void )
{/*HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);第1个参数为I2C操作句柄第2个参数为从机设备地址第3个参数为从机寄存器地址第4个参数为从机寄存器地址长度第5个参数为发送的数据的起始地址第6个参数为传输数据的大小第7个参数为操作超时时间   
*/uint8_t check,Data;// check device ID WHO_AM_I//检查设备ID HAL_I2C_Mem_Read (&hi2c1 ,MPU6050_ADDR,WHO_AM_I_REG,1,&check ,1,1000);if(check == 104)       //if the device is present,寄存器地址默认0x68{//power management register 0x6B we should write all 0's to wake the sensor up//电源管理寄存器,我们应该在0x6B中写入所有0来唤醒传感器Data = 0;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR ,PWR_MGMT_1_REG ,1,&Data ,1,1000);//Set DATA RATE of 1KHz by writing SMPLRT_DIV register//通过写入SMPLRT_DIV寄存器设置1KHz的数据速率Data = 0x07;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR ,SMPLRT_DIV_REG ,1 ,&Data,1,1000);// Set accelerometer configuration in ACCEL_CONFIG Register// XA_ST=0,YA_ST=0,ZA_ST=0,  FS_SEL=0 ->±2g//在加速度寄存器中修改配置Data = 0x00;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &Data, 1, 1000);// Set Gyroscopic configuration in GYRO_CONFIG Register// XG_ST=0,YG_ST=0,  FS_SEL=0 ->± 250 °/s//修改重力加速计配置Data = 0x00;HAL_I2C_Mem_Write (&hi2c1 ,MPU6050_ADDR, GYRO_CONFIG_REG, 1, &Data, 1, 1000);}
}

(6)进行数据读取函数:加速度数据读取、陀螺仪数据读取、温度数据读取;

//************************************加速度传感器读取*************************************//
void MPU6050_Read_Accel(void)
{uint8_t Rec_Data[6];//Read 6 BYTES of data starting from ACCEL_XOUT_H registerHAL_I2C_Mem_Read (&hi2c1 ,MPU6050_ADDR ,ACCEL_XOUT_H_REG ,1,Rec_Data ,6,1000);Accel_X_RAW = (int16_t )(Rec_Data [0] <<8 | Rec_Data [1]);Accel_Y_RAW = (int16_t )(Rec_Data [2] <<8 | Rec_Data [3]);Accel_Z_RAW = (int16_t )(Rec_Data [4] <<8 | Rec_Data [5]);Ax = Accel_X_RAW/16384.0;Ay = Accel_Y_RAW/16384.0;Az = Accel_Z_RAW/16384.0;
}
//*********************************陀螺仪数据读取*****************************************//
void MPU6050_Read_Gyro(void )
{uint8_t Rec_Data[6];// Read 6 BYTES of data staring from GYRO_XOUT_H registerHAL_I2C_Mem_Read (&hi2c1, MPU6050_ADDR ,GYRO_XOUT_H_REG ,1,Rec_Data ,6 ,1000);Gyro_X_RAW = (int16_t )(Rec_Data [0] << 8 | Rec_Data [1]);Gyro_Y_RAW = (int16_t )(Rec_Data [2] << 8 | Rec_Data [3]);Gyro_Z_RAW = (int16_t )(Rec_Data [4] << 8 | Rec_Data [5]);Gx = Gyro_X_RAW/131.0;Gy = Gyro_Y_RAW/131.0;Gz = Gyro_Z_RAW/131.0;
}
//***********************************芯片温度读取************************************//
void MPU6050_Read_Temp(void )
{uint8_t Rec_Data[2];HAL_I2C_Mem_Read (&hi2c1 ,MPU6050_ADDR ,TEMP_OUT_H_REG ,1 ,Rec_Data  ,2 ,1000);Temp_RAW = (int16_t )(Rec_Data [0]<<8)|Rec_Data [1];Temp = 36.53 + (Temp_RAW )/340;
}

(7) 在主函数中调用这些函数即可;

MPU6050_Init ();
MPU6050_Read_Accel();
MPU6050_Read_Gyro();
MPU6050_Read_Temp();
usart2_printf("Ax=%.2f,Ay=%.2f,Az=%.2f\r\n",Ax,Ay,Az);
usart2_printf("Gx=%.2f,Gy=%.2f,Gz=%.2f\r\n",Gx,Gy,Gz);
usart2_printf("Temperature=%.2f,\r\n",Temp );
HAL_Delay (500);

(8)我们将这些代码编译,烧录到我们单片机中即可。


总结

通过本次实验,我学会了:
(1)了解了陀螺仪进行姿态计算的原理;
(2)大致了解卡尔曼滤波的基本过程,同时怎么样将卡尔曼应用到卡尔曼滤波;
(3)通过单片机实现了MPU6050原始数据的读取。
后面还需要学习的:
(1)陀螺仪、加速度计、磁力计他们的工作原理是什么,误差到底来自于那些方面;
(2)利用这些原始数据进行姿态解算的具体怎么操作;
(3)在草稿本上认真推导姿态解算的过程,并把它记录下来。

毕业设计2- MPU6050传感器调试记录(STM32CubeMX+STM32F103C8T6)相关推荐

  1. stm32F1x上调试mpu6050的心得记录

    最近学校正在举行电赛,我就去参加了.正好选的题目里面要用到mpu6050.我前前后后调试了很久才 调试出来,下面就来分享一下我调试的心得,希望对大家有所帮助. 硬件和程序:我用的板子是[正点原子]的s ...

  2. JAVA儿童接种系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA儿童接种系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA儿童接种系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语言:Ja ...

  3. JAVA宠物医院管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA宠物医院管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA宠物医院管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  4. JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA菜鸟驿站快递分发系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 ...

  5. 第44章 MPU6050传感器—姿态检测—零死角玩转STM32-F429系列

    第44章     MPU6050传感器-姿态检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...

  6. JAVA诊所信息管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA诊所信息管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA诊所信息管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  7. JAVA地铁舆情管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA地铁舆情管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA地铁舆情管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  8. JAVA租车网站计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA租车网站计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA租车网站计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 ...

  9. JAVA电子书店管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA电子书店管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA电子书店管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S架构 开发语 ...

  10. JAVA珠宝首饰进销存管理系统计算机毕业设计Mybatis+系统+数据库+调试部署

    JAVA珠宝首饰进销存管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 JAVA珠宝首饰进销存管理系统计算机毕业设计Mybatis+系统+数据库+调试部署 本源码技术栈: 项目架构:B/S ...

最新文章

  1. 我在 GitHub 上发现了一款骚气满满的字体!
  2. mock模拟的数据能增删改查吗_Mock.js模拟数据,脱离后端独立开发,实现增删改查功能...
  3. redis的一些操作命令
  4. 28-Interview-面试
  5. 控制台浏览器代码实战
  6. php字符串转换mysql_在PHP中将字符串转换为MySQL时间戳格式
  7. gorm preload 搜索_LeetCode刷题笔记|95:不同的二叉搜索树 II
  8. ADSL、SRA、HDSL
  9. 此电脑怎么放在桌面上_电脑内部与麦克风的声音怎么同时录制?详细教程在此...
  10. 【配送路径规划】基于matlab遗传算法求解带时间窗的多配送中心半开放式车辆路径规划问题【含Matlab源码 YC002期】
  11. LaTeX通用简洁模板
  12. windows批量ping脚本
  13. php require失败,关于php:致命错误:require_once()[function.require]:要求打开失败
  14. Mac 电脑系统重装(详细流程,包含 Intel、Apple M系列)
  15. 学计算机的要起一个群名,吸引人的学生群名字
  16. Windows10 笔记本从睡眠状态唤醒时取消输入密码的方法
  17. 每天记账,是穷人才会做的事?
  18. 错误 编码(此代码是错误的)
  19. 花168大洋买来的「阿里P8Java成长笔记」,看完才知道我就是lj
  20. numpy序列预处理dna序列_合成生物学快讯2019年第12期:基于DNA的分子数字数据存储...

热门文章

  1. 【Unity3D插件】VOXL插件分享《多人沙盒游戏插件》
  2. Python POST 修改某计步APP的数据
  3. win7如何启用计算机的无线功能,win7笔记本怎么打开无线-win7打开无线功能,win7已关闭无线功能 未修复...
  4. 无线摄像头服务器关闭,监控摄像头服务器停止
  5. 转:关于市场上几家PB系统简介
  6. Linux系统下的TCP测试工具,TCPING安装简明教程
  7. kettle下载安装使用教程
  8. 莫烦nlp-GPT 单向语言模型
  9. 开源聚力,共创未来 | 麒麟信安祝贺openKylin首个体验版正式发布!
  10. 数据结构银行叫号系统