MPU6050篇——姿态解算,卡尔曼滤波

news2024/11/15 19:48:03

一、DMP文件的修改:

        首先我们打开inv_mpu.c文件夹,如下图所示便是第一个要修改的地方:

我们将其修改为:define定义可以改为自己使用的型号的单片机。

修改后在上面定义这个宏,并加上一个MPU6050的宏,用于源文件区别芯片:

然后我们打开inv_mpu_dmp_motion_driver.c,找到如下地方,和上面一样:   

修改为:(记得在上面加入#define  STM32F10x_MPU6050)

此时还有一些地方需要完善,但大致已经改完了,修缮一下:编译,报3处错,如下:

 这里报错:(inv_mpu.h文件中)

修改为:

 在inv_mpu_dmp_motion_driver.c中:

此时编译还有一个错误:

可以发现是inv_mpu中的问题,我们找到这给注释掉

此时再编译,无错误,一个警告,如下图:

我们点击过去给函数注释掉:(注意一定要注释全,是一整个函数,比较长)

 此时再编译:无错误。

 二、官方源码的移植

 此时,我们的DMP代码已经改完了,下面还要移植官方例子的初始化等代码:下面来转植代码,打开官方库如下文件:

下拉,在main函数复制下面方框的结构体及初始化函数,并自己创建一个函数封装起来并判断返回值:这些函数正确执行就会返回0,否则返回非0数。 

到这步你的代码应该是这样:

这几个函数是设置传感器、设置fifo、设置采样率的,复制到自己的代码:

其中DEFAULT_MPU_HZ为官方定义的,ctrl+f搜索一下复制到自己函数上面,然后在相应函数判断返回值,此时代码应该如下:

下面复制DMP初始化步骤代码并粘贴到自己的函数中并判断其返回值:

删掉两行关于注册函数的(未使用到)

再删掉结构体,不使用结构体赋值,如下效果:

这里有个函数报错,去官方库把这个函数复制过来:

即将这两个函数都复制过去并粘贴到MPU6050_DMP_Init上面:

在官方文件找到自检函数复制过来,同样判断返回值:

再将此函数从官方库找出来粘贴到我们初始化函数上方,删掉下图所示内容:

添加返回值,错误返回1,否则为0

自此,其移植已经完成了,下面经行获取姿态数据 

三、使用MPU6050获取姿态数据

 先写下获取数据的函数,由于DMP会将处理好的数据放入fifo,所以我们只需要读取fifo就可以取出其数据了。至于怎么使用这个函数可以转向定义看看:

定义好相关参数并传到读fifo函数中,再判断其返回值,此时代码应该为:

接下来就开始解析四元数了,将四元数转化为欧拉角:

fifo函数的标志位为sensors,当某个数据存在,读函数会把sensors参数某个位置置一。

我们要获取四元数,判断其标志位,如果有四元数便经行下一步解析。将读出四元数转换成浮点数,直接除2的30次方便将Q30格式换为浮点数了。在上方定义四个浮点型变量用来存储转换后的数据:2^30 = 1073741824,我们宏定义于函数上方,在转换为浮点数,第二张图:

最后将四元数转换为欧拉角,网上百度一下公式,如下:

我们根据其公式编写代码:(乘57.3目的时弧度转换成角度) 至于返回值是好查看错误时是哪步的问题。

此时编译无错误警告,移植完成

需要添加的代码我放下面:

#define DEFAULT_MPU_HZ  (100)
//q30格式,long转float时的除数.
#define q30  1073741824.0f
void mget_ms(unsigned long *time)
{
    //空函数,未使用
}

static unsigned short inv_row_2_scale(const signed char *row)
{
    unsigned short b;

    if (row[0] > 0)
        b = 0;
    else if (row[0] < 0)
        b = 4;
    else if (row[1] > 0)
        b = 1;
    else if (row[1] < 0)
        b = 5;
    else if (row[2] > 0)
        b = 2;
    else if (row[2] < 0)
        b = 6;
    else
        b = 7;      // error
    return b;
}

static unsigned short inv_orientation_matrix_to_scalar(
    const signed char *mtx)
{
    unsigned short scalar;

    /*
       XYZ  010_001_000 Identity Matrix
       XZY  001_010_000
       YXZ  010_000_001
       YZX  000_010_001
       ZXY  001_000_010
       ZYX  000_001_010
     */

    scalar = inv_row_2_scale(mtx);
    scalar |= inv_row_2_scale(mtx + 3) << 3;
    scalar |= inv_row_2_scale(mtx + 6) << 6;


    return scalar;
}

static signed char gyro_orientation[9] = {-1, 0, 0,
                                           0,-1, 0,
                                           0, 0, 1};

static int run_self_test(void)
{
    int result;
    long gyro[3], accel[3];

    result = mpu_run_self_test(gyro, accel);
    if (result == 0x3) {
        /* Test passed. We can trust the gyro data here, so let's push it down
         * to the DMP.
         */
        float sens;
        unsigned short accel_sens;
        mpu_get_gyro_sens(&sens);
        gyro[0] = (long)(gyro[0] * sens);
        gyro[1] = (long)(gyro[1] * sens);
        gyro[2] = (long)(gyro[2] * sens);
        dmp_set_gyro_bias(gyro);
        mpu_get_accel_sens(&accel_sens);
        accel[0] *= accel_sens;
        accel[1] *= accel_sens;
        accel[2] *= accel_sens;
        dmp_set_accel_bias(accel);
    }else   return 1;
    return 0;
}

int MPU6050_DMP_Init(void)
{
    int result;
    struct int_param_s int_param;
    result = mpu_init(&int_param);//mpu初始化
    if(result != 0)    return -1;
    result = mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL);//设置传感器
    if(result != 0)    return -2;
    result = mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL);//设置fifo
    if(result != 0)    return -3;
    result = mpu_set_sample_rate(DEFAULT_MPU_HZ);//设置采样率
    if(result != 0)    return -4;
    result = dmp_load_motion_driver_firmware();//加载DMP固件
    if(result != 0)    return -5;
    result = dmp_set_orientation(
        inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向
    if(result != 0)    return -6;
    result = dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
                                DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
                                DMP_FEATURE_GYRO_CAL);//设置dmp功能
    if(result != 0)    return -7;
    result = dmp_set_fifo_rate(DEFAULT_MPU_HZ);//设置输出速率
    if(result != 0)    return -8;
    result = run_self_test();//自检
    if(result != 0)     return -9;
    result = mpu_set_dmp_state(1);//使能DMP
    if(result != 0)    return -10;
    return result;
}

int mpu_dmp_get_data(float *pitch,float *roll,float *yaw)
{
    float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
	unsigned long sensor_timestamp;
	short gyro[3], accel[3], sensors;
	unsigned char more;
	long quat[4]; 
    if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))return 1;
    if(sensors&INV_WXYZ_QUAT) 
	{
        q0 = quat[0] / q30;	//q30格式转换为浮点数
		q1 = quat[1] / q30;
		q2 = quat[2] / q30;
		q3 = quat[3] / q30; 
		//计算得到俯仰角/横滚角/航向角
		*pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3;	// pitch
		*roll  = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3;	// roll
		*yaw   = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;	//yaw
    }else return 2;
    return 0;
}

我们在主函数就可以读取数据了:

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "stdio.h"
#include "mpu6050.h"
#include "inv_mpu.h"

int main(void)
{
    u8 string[10] = {0};
    float pitch,roll,yaw;
	MPU_Init();
    MPU6050_DMP_Init();
	while (1)
	{       
        mpu_dmp_get_data(&pitch,&roll,&yaw);
        sprintf((char *)string,"Pitch:%.2f",1.32);//0300
        OLED_ShowString(16,10,string,16,1);
        sprintf((char *)string,"Roll :%.2f",roll);//0300
        OLED_ShowString(16,26,string,16,1);
        sprintf((char *)string,"Yaw  :%.2f",yaw);//0300
        OLED_ShowString(16,46,string,16,1);
        OLED_DrawLine(5,5,125,5,1);
        OLED_DrawLine(5,5,5,62,1);
        OLED_DrawLine(5,62,125,62,1);
        OLED_DrawLine(125,5,125,62,1);
        OLED_Refresh();
        OLED_Refresh();
        if(pitch>70)pitch=70;
        if(pitch<-70)pitch=-70;
        if(roll>70)pitch=70;
        if(roll<-70)pitch=-70;
            
		OLED_Refresh();
        
	}
}

上面MPU6050_DMP_Init应该 int型,并返回负数,否则结果不对!

效果:没拍好,但是代码可用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1800576.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法005:有效三角形的个数

. - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/valid-triangle-number/ 要组成三角形的三条边&#xff0c;需要保证&am…

【MATLAB源码-第224期】基于matlab的快跳频系统仿真采用4FSK,模拟了单音干扰,宽带干扰以及部分频带干扰,输出误码率曲线以及各节点图像。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 跳频通信系统概述 跳频通信系统是一种通过快速切换载波频率来进行信息传输的无线通信技术。它在军事和商业通信中广泛应用&#xff0c;具有较强的抗干扰和抗截获能力。系统设计主要包括信号调制、跳频序列生成、信道模拟以及…

BC6 小飞机

BC6 小飞机 废话不多说先上题目&#xff1a; 代码如下&#xff1a; #include<stdio.h> int main() {printf(" ## \n############\n############\n # # \n # # \n");return 0; }这是用一个printf打印我们还可以用多个printf发打印代码如下…

俄罗斯服务器租用攻略:选择优质服务器,开启海外市场新征程

随着国际贸易的不断发展&#xff0c;俄罗斯作为一个重要的贸易伙伴备受关注。许多企业和公司为了开拓海外市场&#xff0c;选择将业务拓展到俄罗斯&#xff0c;而在这个过程中&#xff0c;租用一台优质的服务器成为了必须面对的问题。俄罗斯作为一个经济发展迅速的国家&#xf…

JavaEE初阶---多线程编程(一.线程与进程)

目录 &#x1f923;一.线程与进程的概念与联系&#xff1a; 进程的基本概念&#xff1a; 线程的基本概念&#xff1a; 进程和线程的区别与联系&#xff1a; &#x1f643;代码执行实列&#xff1a; 1.通过继承Thread父类来实现多线程 2.通过实现Runnable接口来实现多线程…

JavaEE:http请求 | 过滤器 | 同步与异步请求 | 跨域问题 | axios框架 有这一篇就够!

&#x1f4c3;HTTP请求 ▐ http超文本传输协议&#xff1a; ⦁ http超文本传输协议属于应用层协议&#xff0c;传输内容必须是超文本内容 (网页内容) ⦁ 例如在网页上点击超链接&#xff0c;提交表单&#xff0c;都可以向后端发送一个http请求 ⦁ 一次http请求中包含请求行、…

《深入浅出C语言:从基础到指针的全面指南》

1. 简介 C语言是一种通用的编程语言&#xff0c;广泛应用于系统编程、嵌入式系统和高性能应用程序。它由Dennis Ritchie在1972年开发&#xff0c;并且至今仍然非常流行。C语言以其高效、灵活和强大的功能著称&#xff0c;是许多现代编程语言的基础。 2. 基本语法 2.1 Hello, …

Ezsql(buuctf加固题)

开启环境 SSH连接 第一个为页面地址WEB服务 or 11# 利用万能密码登录 密码可以随便输入或者不输入 这里就可以判断这个题目是让我们加固这个登录页面 防止sql注入 查看index.php 添加以下代码 $username addslashes($username); $password addslashes($password);…

SEO之关键词分布

初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; 1、我给不会敲代码又想搭建网站的人建议 2、新手上云 经过核心关键词确定与关键词扩展&#xff0c;应该已经得到一个至少包含几百个相关关键词的大列表。这些关键…

02.体验CSS以及Bootstrap框架

目录 CSS固定格式 1&#xff09;style标签 2&#xff09;div标签 3&#xff09;span标签 CSS属性 一、文字属性 1.规范文字样式的属性 2.规定文字粗细的属性 3.规定文字大小的属性 4.规范文字字体的属性 二、文本属性 1.文本装饰属性 2.文本水平对齐属性 3.文本缩进…

数据库中锁的机制和MVCC协议以及隔离级别

文章目录 数据库中的锁锁与索引的关系释放锁的时机乐观锁与悲观锁行锁与表锁共享锁与排它锁意向锁记录锁、间隙锁和临键锁记录锁间隙锁临键锁 锁优化方案 MVCC协议MySQL的隔离级别脏读和幻读快照读和当前读 版本链Read ViewRead View 与已提交读Read View 与可重复读m_up_limit…

【C语言题解】1、写一个宏来计算结构体中某成员相对于首地址的偏移量;2、写一个宏来交换一个整数二进制的奇偶位

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f308;感谢大家的阅读、点赞、收藏和关注 &#x1f495;希望大家喜欢我本次的讲解&#x1f495; 目录&#x1f451; 1、写一个宏&#xff0c;计算结构体中某变量相对于首地址的偏…

STM32_HAL库_外部中断

一、设置分组 stm32f1xx_hal_cortex.c 查看分组 五个形参&#xff0c;分组0~4 stm32f1xx_hal.c 设置了分组为2&#xff0c; 此工程就不需要再设置了 再回到stm32f1xx_hal_cortex.c 查看NVIC_SetPriorityGrouping的定义&#xff0c;若无法跳转&#xff0c;先编译一下&…

【数据结构】穿梭在二叉树的时间隧道:顺序存储的实现

专栏引入 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家…

Apple开发者应用商店(AppStore)描述文件及ADHOC描述文件生成

创建AD HOC描述文件 1.选中Profiles,然后点击加号创建 2.创建已注册设备可安装描述文件 3.选择要注册的id 4.选择证书 5.选择设备 6.输入文件名,点击生成 7.生成成功,点击下载

重新ysyx

一、克隆仓库 1.创建ssh key ssh-keygen -t rsa cd ~/.ssh ls 查看里面是否有id_rsa id_rsa.pub ssh-keygen -t rsa -C "xiantong15834753336outlook.com" cat id_rsa.pub***********查看里面的内容&#xff0c;复制到下图中绿色的按钮 git init ssh -T g…

Alsa UCM

Alsa Use Case Manager&#xff08;用例管理器&#xff09;描述如何为某些用例&#xff08;如 “播放音频”、“通话”&#xff09;设置 mixer 混频器。它还描述如何修改 mixer 混频器状态以将音频路由到某些输出和输入&#xff0c;以及如何控制这些设备。 这基本上涵盖了 Pul…

胶南代理记账,为您提供专业、便捷的会计服务

欢迎来到胶南代理记账服务站&#xff0c;这里我们专注于为企业提供专业的会计服务&#xff0c;无论您是初创企业还是已经在业界有一定规模的企业&#xff0c;我们都将以最专业的态度和最高效的服务为您量身定制合适的记账方案。 我们的目标不仅是帮助您完成财务报告的制作&…

奥威BI零售数据分析方案的优缺点一览

奥威BI零售数据分析方案是一套基于BI大数据智能可视化分析系统&#xff0c;根据零售企业数据分析共性需求、业务特殊性量身打造&#xff0c;点击下载应用&#xff0c;立即将零售数据情况分析清楚&#xff0c;直观呈现。很多企业都是直接在该零售数据分析方案的基础上实现了智能…

Windows系统中好用的闪迪U盘修复工具

本文向你介绍了一款简单好用的闪迪U盘修复工具&#xff0c;它可以帮助你轻松修复闪迪U盘的各种问题。该工具操作简单&#xff0c;能帮用户节省大量的时间和精力。 闪迪U盘损坏可以修复吗&#xff1f; “我有一只32GB的闪迪U盘出现了问题&#xff0c;可能是因为我在关机前将它强…