STM32的MPU6050卡尔曼滤波融合数据控制平衡车

最近学习卡尔曼滤波的方法来融合MPU6050的加速度计所得的角度以及陀螺仪的角速度数据。一开始去B站搜视频看原理,然后找到优快云上的一篇博客,参考了初始值的设定后写了下面的滤波算法。 该up主视频讲的很好,视频链接:精通(教你从理论到实践)_哔哩哔哩_bilibili

算法的伪代码如下:

完全按照着伪代码编写的代码:

float dt=0.005;		  //每5ms进行一次滤波                 
float Kalman_Filter_x(float Accel,float Gyro)		
{
    //Accel:通过加速度计计算的角度,Gyro:陀螺仪输出的角速度,这两个值的获取查一查都有

	static float angle;
	float Q_angle=0.001; // 参考别人的的值
	float Q_gyro=0.003;	//参考别人的的值
	float R_angle=0.5;		// 参考别人的的值

	static float Q_bias, Angle_err;
	static float E;
	static float K_0, K_1;
	static float P[2][2] = { { 1, 0 },{ 0, 1 } };//参考别人的初始值

	angle+=(Gyro - Q_bias) * dt; //先验估计

	P[0][0] += Q_angle -( P[0][1] + P[1][0]) * dt;   // Pk-先验估计误差协方差微分的积分
	P[0][1] += -P[1][1] * dt;   // =先验估计误差协方差
	P[1][0] +=-P[1][1] * dt;
	P[1][1] += Q_gyro;
		
	Angle_err = Accel - angle;	//zk-先验估计
	
	
	E = R_angle + P[0][0];
	
	K_0 = P[0][0] / E;
	K_1 = P[1][0] / E;
	

	P[0][0] -= K_0 * P[0][0];		 //后验估计误差协方差
	P[0][1] -= K_0 * P[0][1];
	P[1][0] -= K_1 * P[0][0];
	P[1][1] -= K_1 * P[0][1];
		
	angle	+= K_0 * Angle_err;	 //后验估计
	Q_bias	+= K_1 * Angle_err;	 //后验估计
	
	return angle;
}

写完后用PID来控制小车,发现小车刚开始可以稳定,但是小车后面幅度越晃越大,最后直接失去平衡。

之后参考了另一篇优快云博客的代码,将P[0][0]和P[1][1]的先验估计做了修改,令Q_angle和Q_gyro都乘上dt,相当于对协方差矩阵Q乘上dt。这两个值分别代表了加速度算出来的角度方差以及陀螺仪角速度的方差,两个值都与时间相关,当距离上次更新时间越长,那么这两个方差也会越大,就比如陀螺仪积分出来的角度,时间越长,那么偏差累积也会越大。

其实这个操作也就相当于去对Q_angle和Q_gyro进行调节,取到一个更加适合的值,如果dt=0.05,最终的值其实就是Q_angle = 0.00005, Q_gyro = 0.00015。

修改后代码如下:

float Kalman_Filter_y(float Accel,float Gyro)		
{
    //Accel:通过加速度计计算的角度,Gyro:陀螺仪输出的角速度,这两个值的获取查一查都有

	static float angle;
	float Q_angle=0.001; // 参考别人的的值
	float Q_gyro=0.003;	//参考别人的的值
	float R_angle=0.5;		// 参考别人的的值

	static float Q_bias, Angle_err;
	static float E;
	static float K_0, K_1;
	static float P[2][2] = { { 1, 0 },{ 0, 1 } };//参考别人的初始值

	angle+=(Gyro - Q_bias) * dt; //先验估计

	P[0][0] += ( Q_angle -P[0][1] - P[1][0]) * dt;   // 修改了这里
	P[0][1] += -P[1][1] * dt;   // =先验估计误差协方差
	P[1][0] +=-P[1][1] * dt;
	P[1][1] += Q_gyro* dt;  // 修改了这里
		
	Angle_err = Accel - angle;	//zk-先验估计
	
	
	E = R_angle + P[0][0];
	
	K_0 = P[0][0] / E;
	K_1 = P[1][0] / E;
	

	P[0][0] -= K_0 * P[0][0];		 //后验估计误差协方差
	P[0][1] -= K_0 * P[0][1];
	P[1][0] -= K_1 * P[0][0];
	P[1][1] -= K_1 * P[0][1];
		
	angle	+= K_0 * Angle_err;	 //后验估计
	Q_bias	+= K_1 * Angle_err;	 //后验估计
	
	return angle;
}

上电后小车可以平稳运行了。

### 实现 STM32MPU6050 传感器的卡尔曼滤波算法 为了实现基于 STM32MPU6050 传感器的卡尔曼滤波算法用于平衡项目,可以按照以下方法构建系统。 #### 卡尔曼滤波器简介 卡尔曼滤波是一种高效的递归滤波器,能够估计系统的状态变量。对于平衡而言,该滤波器可以帮助更精确地测量角度变化并减少噪声影响[^1]。 #### 系统硬件配置 - **微控制器**: 使用 STM32 微控制器作为核心处理单元。 - **IMU模块**: 利用 MPU6050 提供三轴加速度计和陀螺仪数据输入给卡尔曼滤波器进行融合处理[^2]。 #### 软件设计要点 ##### 初始化设置 初始化阶段需完成如下工作: - 配置 IIC 接口以便与 MPU6050 进行通信; - 设置定时中断服务函数以固定频率读取 IMU 数据; - 对卡尔曼滤波参数做适当调整使其适应具体应用场景需求。 ##### 主循环逻辑 在主循环里执行的主要任务包括但不限于: - 定期获取来自 MPU6050 的原始传感数值; - 将这些值传递至已定义好的卡尔曼滤波模型中更新预测位置; - 输出修正后的姿态角信息指导电机控制系统动作保持身稳定。 ```c // C语言伪代码示例 void main() { while(1){ // 获取MPU6050的数据 get_mpu_data(&acceleration,&gyro); // 更新卡尔曼滤波器的状态 kalman_update(&kalman_filter, acceleration, gyro); // 计算当前的角度 float angle = calculate_angle(kalman_filter.state); // 控制电机使辆保持直立 control_motors(angle); } } ``` ##### 关键技术细节 - **优化卡尔曼增益矩阵**:合理设定 Q(过程噪音协方差)、R(观测误差协方差),从而提高滤波效果。 - **实时性能考量**:确保整个控制回路能在足够高的刷新率下运行,通常至少要达到几百赫兹以上才能满足动态响应的要求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值