基于九轴imu963ra九轴陀螺仪的学习经验

本文作者作为大一学生在制作平衡单车时首次接触陀螺仪,分享了学习过程中的经验。文章详细介绍了如何获取陀螺仪的角度值,包括加速度计和陀螺仪数据的方法,并提到了一阶互补滤波在提高数据准确性上的作用。作者还分享了自己从误认为只有加速度计能获取角度到理解陀螺仪、角速度计和地磁计都能提供角度信息的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果觉得写的还可以,请关注加收藏,你的关注就是我继续创作优秀文章的动力,谢谢!!!!!!!!!!!!!!!!!!!!!!!
不好意思,终于迎来了2.0版本的更新,这次包括了地磁计和四元数解算的代码,希望大家多多提出意见!!!!!!!!!!!!!!

 

陀螺仪主要分为三轴,六轴和九轴陀螺仪,主要功能分别是三轴加速度计数据,三轴陀螺仪数据(角速度数据),和三轴地磁计数据(本篇中我还为学会地磁计的作用,现在我已经学会怎么使用地磁计了),经过几天对陀螺仪的使用和学习经验,做一个分享,并记录我自己的学习(以防后面忘记如何使用).

我是在制作平衡单车的时候,第一次接触和使用陀螺仪,刚开始对于陀螺仪的了解只有它能保持平衡,对于它其他方面,基本毫无了解,为了学习使用陀螺仪,我连续查了好几天资料,并对它进行了实际操作,发现他真的好难.

本人现在以及大三了,我再又一年的接触到平衡车,为了简单寻迹,所以寻迹也是使用了陀螺仪,但是由于只有陀螺仪和加速度计得出的角度,在短期内还算正常,但是时间一长就容易飘,因为我们是使用模拟地图得出的寻迹目标,所以光靠这两个融合得出的角度显然已经不够使用了,所以我们把陀螺仪改为了九轴陀螺仪,加了三轴的地磁计,地磁计的特性利用地面磁场确定航向角,类似于指南针,由于这个特性,大家也明白了一个道理,地磁计受金属,磁场影响巨大(本人亲测,影响巨大,会把指南针打死)

后面不说废话了,之接开始我的分享.

在这段时间,我纠结最多的就是如何获取陀螺仪的实际角度值,我使用了好多方法,使用一阶互补滤波(卡尔曼滤波属实看不懂)

其实我在学习陀螺仪的时候一直有一个误区,就是以为只有加速度计可以得出角度,但是后来,我通过不断的翻阅资料,慢慢发现,对于陀螺仪来说它的目的就是为了得出角度,所以他的角速度计,陀螺仪数据和地磁计都是可以得出角度的

在分享角度之前,我想给大家讲讲零漂

什么是零漂呢?其实很简单,可以见名之意一下就是在零的左右不断漂移,在静止的时候,陀螺仪、加速度计以及地磁计在零点的时候数值不断的在0附近飘动。这个漂移在短期内问题还是不大,但是随着时间的累加,漂移就会特别严重,甚至偏移的角度可能大于你的想象,不断累加,对于调直立、惯性导航以及一些对陀螺仪要求高的东西,这个零漂是致命的。我通过所学,提供我仍为比较好用的三种去零漂的代码。

(1)除10再乘10

这个就比较顾名思义了,对于零漂来说,仔细观察数据,其实他在0左右漂移的数值不会大于10,如果大于了那就不是误差了,而是你可能不小心动了一下桌子。除10再乘10就是把个位上的数据直接抹除作为不信任区。具体代码如下:

imu963ra_gyro_x = imu963ra_gyro_x /10 *10;

(2)减去误差

这个方法和上一个差不多,也是去除个位上的数据,具体思路就是计算一千次的数据累加起来然后求平均值,之后把每次获取的值减去这个平均值,也能把零漂去的还可以,注意:在计算误差的时候一定不要乱动。直接上代码:

int index=0;
void error_compute()
{
    static error = 0;
    if(index < 1000) error += imu963ra_gyro_y;
    else if(index == 1000) error = error / 1000;
    else return;
    index++;
}

(3)一阶低通滤波

这个方法就比较简单了,就是计算权重,这一次获取的数值乘以权重加上上一次获取的数值乘以(1-权重),这样的数据比较准确,但是不适合陀螺仪,只适合加速度计,直接上代码:

float a = 0.25;
float frist_pass_filter(float in_data)
{
    static last_data;
    float out_data = a * last_data + (1 - a) * in_data;
    last_data = in_data;
    return out_data;
}

以下是加速度计获取角度的方法

选择哪两个轴的方法是把车放在原地不动,左右摇晃,示波器中波动最大的两个轴就是所需要的轴

关于tan2函数的原因可以参考这篇文章atan2反正切-CSDN博客

//angle_1是加速度计通过三角函数得出的角度
//imu963ra_acc_x和imu963ra_acc_z是两个轴的加速度计
angle_1=atan2(imu963ra_acc_x,-imu963ra_acc_z)*(180/PI)+90;
//PI 指的是圆周率3.1415926

以下是陀螺仪数据获取角度的方法

选择的轴的方法就是将所有陀螺仪数据放入示波器中,左右摇摆,晃动最大的那个就是所需要的陀螺仪数据轴,记住,传过来的陀螺仪数据一定要先转化为实际的物理值,一定要先去零漂

//gyroRate是你得出来的那个轴的数据
//dt是积分的时间间隔,一般是ms,具体多少看实际情况
double integrateGyro(double gyroRate, double dt)
{
    static double gyroAngle = 0.0;
    // 对角速度进行积分得到角度
    gyroAngle += gyroRate * dt;
    // 返回角度
    return gyroAngle;
}

最后为了让数据更加准确,一般使用一阶互补滤波对加速度计得出的角度和陀螺仪数据得出的角度进行互补滤波,以下是我在学习中看到的一个互补滤波

float acc_ratio = 4.90;      //加速度计比例
float gyro_ratio = 0.45;    //陀螺仪比例,结合示波器调参
float dt = 0.005;           //采样周期,赶紧实际情况填写

float angle_calc(float angle_m, float gyro_m)
{
    float temp_angle;
    float gyro_now;
    float error_angle;
    static float last_angle;
    static uint8 first_angle;
    if(!first_angle)
    {
        first_angle = 1;
        last_angle = angle_m;
    }
    gyro_now = gyro_m * gyro_ratio;
    error_angle = (angle_m - last_angle)*acc_ratio;
    temp_angle = last_angle + (error_angle + gyro_now)*dt;
    last_angle = temp_angle;
    return temp_angle;
}

以下是地磁计的学习经验

后面为大家分享的就是地磁计的学习经验了,但是我不知道是我的问题还是没有找到,我并没有找到利用地磁计得出角度的方法,我利用地磁计融合的方式是直接利用四元数解算方法得出欧拉角,相对更加准确,我觉得大家可以试试,至于九轴的四元数解算代码,容我找一找,代码太多了,太乱了,容我整理一下,过两天更新。

最后一部分终于来啦

个人亲测,使用九轴陀螺仪的时候一定不要靠近金属和磁场

以下是我四元数解算陀螺仪的代码

 
void MadgwickQuaternionUpdate(Axis3f acc, Axis3f gyro, Axis3f mag, Axis3f *Angle , float dt)
{
		float norm;
		float hx, hy, _2bx, _2bz;
		float s1, s2, s3, s4;
		float qDot1, qDot2, qDot3, qDot4;
	 
		
		//提前计算好下面要用到的数值防止重复计算,减少运算量
		float _2q1mx;
		float _2q1my;
		float _2q1mz;
		float _2q2mx;
		float _4bx;
		float _4bz;
		float _2q1 = 2.0f * q1;
		float _2q2 = 2.0f * q2;
		float _2q3 = 2.0f * q3;
		float _2q4 = 2.0f * q4;
		float _2q1q3 = 2.0f * q1 * q3;
		float _2q3q4 = 2.0f * q3 * q4;
		float q1q1 = q1 * q1;
		float q1q2 = q1 * q2;
		float q1q3 = q1 * q3;
		float q1q4 = q1 * q4;
		float q2q2 = q2 * q2;
		float q2q3 = q2 * q3;
		float q2q4 = q2 * q4;
		float q3q3 = q3 * q3;
		float q3q4 = q3 * q4;
		float q4q4 = q4 * q4;
	 
				
			//度转弧度
		gyro.x = gyro.x * DEG2RAD;	/* 度转弧度 */
		gyro.y = gyro.y * DEG2RAD;
		gyro.z = gyro.z * DEG2RAD;
	 
		//单位化加速度向量
		norm = sqrtf(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z);
		if (norm == 0.0f) return; // handle NaN
		norm = 1.0f/norm;
		acc.x *= norm;
		acc.y *= norm;
		acc.z *= norm;
	 
		//单位化磁力计向量
		norm = sqrtf(mag.x * mag.x + mag.y * mag.y + mag.z * mag.z);
		if (norm == 0.0f) return; // handle NaN
		norm = 1.0f/norm;
		mag.x *= norm;
		mag.y *= norm;
		mag.z *= norm;
	 
		//提前计算好下面要用到的值
		_2q1mx = 2.0f * q1 * mag.x;
		_2q1my = 2.0f * q1 * mag.y;
		_2q1mz = 2.0f * q1 * mag.z;
		_2q2mx = 2.0f * q2 * mag.x;
		//磁力计从机体到地球
		hx = mag.x * q1q1 - _2q1my * q4 + _2q1mz * q3 + mag.x * q2q2 + _2q2 * mag.y * q3 + _2q2 * mag.z * q4 - mag.x * q3q3 - mag.x * q4q4;
		hy = _2q1mx * q4 + mag.y * q1q1 - _2q1mz * q2 + _2q2mx * q3 - mag.y * q2q2 + mag.y * q3q3 + _2q3 * mag.z * q4 - mag.y * q4q4;
		/*让导航坐标系中X轴指向正北方*/
		_2bx = sqrtf(hx * hx + hy * hy);
		_2bz = -_2q1mx * q3 + _2q1my * q2 + mag.z * q1q1 + _2q2mx * q4 - mag.z * q2q2 + _2q3 * mag.y * q4 - mag.z * q3q3 + mag.z * q4q4;
		_4bx = 2.0f * _2bx;
		_4bz = 2.0f * _2bz;
	 
		//梯度下降法计算纠正误差
		s1 = -_2q3 * (2.0f * q2q4 - _2q1q3 - acc.x) + _2q2 * (2.0f * q1q2 + _2q3q4 - acc.y) - _2bz * q3 * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mag.x) + (-_2bx * q4 + _2bz * q2) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - mag.y) + _2bx * q3 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mag.z);
		s2 = _2q4 * (2.0f * q2q4 - _2q1q3 - acc.x) + _2q1 * (2.0f * q1q2 + _2q3q4 - acc.y) - 4.0f * q2 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - acc.z) + _2bz * q4 * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mag.x) + (_2bx * q3 + _2bz * q1) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - mag.y) + (_2bx * q4 - _4bz * q2) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mag.z);
		s3 = -_2q1 * (2.0f * q2q4 - _2q1q3 - acc.x) + _2q4 * (2.0f * q1q2 + _2q3q4 - acc.y) - 4.0f * q3 * (1.0f - 2.0f * q2q2 - 2.0f * q3q3 - acc.z) + (-_4bx * q3 - _2bz * q1) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mag.x) + (_2bx * q2 + _2bz * q4) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - mag.y) + (_2bx * q1 - _4bz * q3) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mag.z);
		s4 = _2q2 * (2.0f * q2q4 - _2q1q3 - acc.x) + _2q3 * (2.0f * q1q2 + _2q3q4 - acc.y) + (-_4bx * q4 + _2bz * q2) * (_2bx * (0.5f - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mag.x) + (-_2bx * q1 + _2bz * q3) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - mag.y) + _2bx * q2 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5f - q2q2 - q3q3) - mag.z);
			//单位化计算好的误差向量
		norm = sqrtf(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4);    
		norm = 1.0f/norm;
		s1 *= norm;
		s2 *= norm;
		s3 *= norm;
		s4 *= norm;
	 
		// 将计算好的误差向量补偿到四元数
		qDot1 = 0.5f * (-q2 * gyro.x - q3 * gyro.y - q4 * gyro.z) - beta * s1;
		qDot2 = 0.5f * (q1 * gyro.x + q3 * gyro.z - q4 * gyro.y) - beta * s2;
		qDot3 = 0.5f * (q1 * gyro.y - q2 * gyro.z + q4 * gyro.x) - beta * s3;
		qDot4 = 0.5f * (q1 * gyro.z + q2 * gyro.y - q3 * gyro.x) - beta * s4;
	 
		//更新四元数的值
		q1 += qDot1 * dt;
		q2 += qDot2 * dt;
		q3 += qDot3 * dt;
		q4 += qDot4 * dt;
		norm = sqrtf(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4);    // normalise quaternion
		norm = 1.0f/norm;
		q1 = q1 * norm;
		q2 = q2 * norm;
		q3 = q3 * norm;
		q4 = q4 * norm;
		
			//四元数转换为欧拉角	
		Angle->z   = atan2(2.0f * (q2 * q3 + q1 * q4), q1 * q1 + q2 * q2 - q3 * q3 - q4 * q4) * RAD2DEG;   
		Angle->x = -asin(2.0f * (q2 * q4 - q1 * q3)) * RAD2DEG;
		Angle->y  = atan2(2.0f * (q1 * q2 + q3 * q4), q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4) * RAD2DEG;
}

以上是我对陀螺仪的了解,日后学习到更多的知识会进行实时更新,谢谢关注!

 

有问题可以加入QQ群一起讨论QQ群:974530818

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
陀螺仪IMU963是一种集成了加速度计、陀螺仪和磁力计的惯性测量单元(IMU),常用于姿态解算、导航系统等领域。它通过内部传感器获取物体运动状态的数据,并经过一系列算法处理来确定设备的空间位置和方向。 ### 惯导原理: 1. **加速度计**:检测线性加速度,在静止状态下可以感知重力场的方向,进而估算倾角信息;动态过程中则能捕捉到沿各坐标的速度变化情况。 2. **陀螺仪**:主要用于测量旋转速率(即角速度)。通过对时间积分可以获得角度增量值,累积起来就可以得到物体绕各个向转动的角度了。 3. **磁力计**:用来感应地磁场强度分布特征,帮助校准航向角偏差问题,确保最终输出结果更为精确可靠。 结合以上三种物理量的变化规律并利用适当的滤波技术(如卡尔曼滤波等),我们便可以从噪声干扰较大的原始数据中提取出较为准确的姿态信息(包括俯仰Pitch、横滚Roll以及偏航Yaw三个维度)。对于IMU963而言,其内置专用硬件资源实现了上述功能模块间的高效协作运算,使得开发者能够方便快捷地读取所需参数进行后续应用开发工作。 此外值得注意的是,由于单纯依靠IMU存在误差累计的问题,实际使用时往往需要配合GPS或者其他辅助手段来进行定期修正,以保证长时间运行下的定位精度不会大幅下降。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思成毛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值