四轮两驱小车(三):STM32驱动MPU6050进行转弯

2023-10-16 07:20

本文主要是介绍四轮两驱小车(三):STM32驱动MPU6050进行转弯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:

        寒假已经过了一半了,前段时间跟学弟一起从零开始搞了一下深度学习,现在才想起来这个系列还没有更完。本篇博客主要介绍一下这个小车转直角弯的神器----MPU6050

MPU6050介绍:

      我所采用的MPU6050是某宝上十几块钱的这种,这种MPU6050有个缺点是带有零点漂移,这个接下来我会在博客里给大家提供我的解决方案,优点显而易见是便宜,如果坏了也不心疼,这可比正点原子的便宜多了。          MPU6050内部整合了三轴MEMS陀螺仪、三轴MEMS加速度计以及一个可扩展的数字运动处理器DMP(Digital Motion Processor),而且还可以连接一个第三方数字传感器(如磁力计),这样的话,就可以通过IIC接口输出一个9轴信号(链接第三方数字传感器才可以输出九轴信号,否则只有六轴信号)。当然,上面给大家展示的就是一个6轴的陀螺仪。更加方便的是,有了DMP,可以结合InvenSense公司提供的运动处理资料库,实现姿态解算。通过自带的DMP,可以通过IIC接口输出9轴融合演算的数据,大大降低了运动处理运算对操作系统的负荷,同时也降低了开发难度。其实,简单一句话说,陀螺仪就是测角速度的,加速度传感器就是测角加速度的,二者数据通过算法就可以得到PITCH、YAW、ROLL角了。

        MPU6050对陀螺仪和加速度计分别用了三个16位ADC,将其测量的模拟量转化为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的。陀螺仪的可测范围为±250,±500,±1000,±2000°/秒(dps),加速度计可测范围为±2,±4,±8,±16g。

        下面是一张关于MPU6050的三个姿态角。而刚才提到的零飘问题其实就是Z轴角度出了问题。
        

管脚的使用:

        MPU6050一共有8个引脚,网上不少博主选择使用其中的5个引脚,而我选择了其中的四个引脚,没有使用INT这个引脚。这个引脚是MPU6050的中断引脚,MPU6050会50ms中断一次,我的板子上IO口不是很丰富,就没有用这个引脚。而AD0作为一个地址引脚决定了MPU6050的地址,它接地或者悬空的时候,MPU的地址为0x68,接高电平的时候,MPU的地址为0x69(博主直接悬空了)。而XCL和XDA是用来外接传感器的,这里我没有外接,所以也悬空了。此外,MPU6050的SCL和SDA,我用的是PB8、PB9来软件模拟的IIC,而不是STM32自带的硬件IIC。

MPU6050管脚对应的STM32F103RCT6 IO口
SCLPB8
SDAPB9
VCCVCC(3.3v或5v)
GNDGND

代码修改部分:

        这里我给大家展示一下对应的.c和.h文件。这里的文件涉及到的比较多,博主在自学的时候学习了很多博主的代码,发现其中缺的东西很多,要不是少sysclock.h要不就是少sys.h,干脆这里我一并给大家放上一个链接,STM32F103C8T6驱动MPU6050并且在OLED屏幕上显示。提取码:2471

         这里我要给大家强调一下,如果delay函数不对的话,很可能会导致MPU6050的IIC时序不对而发生错误,所以大家最好是参照一下我的文件。此外要给大家强调的一点是如果大家用的管脚不是PB8 PB9而要修改其他的IO口的话,那么除了这里要修改。

         对应的IO操作方向也要注意,这里给大家提个醒,当初我就是没有仔细修改这里,而导致多次初始化失败,具体修改方法可以参考数据手册

        移植完成后,我们就可以通过Read_DMP(&Pitch,&Roll,&Yaw);这个函数来读取对应的角度,这个角度是由DMP结算过的,所以可以拿过来就直接用。

是否需要扶正,是否需要开机校准

        关于这个问题,我并没有出现过网上说的不扶正就不能开机,博主的小车只是用了MPU6050来准确的转一下90°角,所以也就没有过多关注这一块。是否需要开机校准,我觉得还是需要的,当你转过一个90°弯之后,我们可以通过重新让MPU6050初始化,来把转完弯后的方向设置为0°方向,这样方便下一次转弯,在代码逻辑上会减轻不少工作量。

        如果选择开机校准的话,那么我们就要让run_self_test()函数正常运行

static void 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);printf("setting bias succesfully ......\r\n");}
}

        博主在让小车完成指令的过程中,采用了状态机的思路(FSM),当小车转弯一个90°之后,即将进入下一个状态的时候,我让MPU6050重新初始化,方便下一次转弯。

IIC_Init();
MPU6050_initialize();     //=====MPU6050初始化	
DMP_Init();
Yaw1 = 0;                //yaw1角度是缓解零飘问题的产物,这里也需要清零。

缓解yaw角零飘问题:

        这个问题其实困扰我很久,当时将MPU6050加到小车上的时候,我使用JLINK给板子烧录程序时,在OLED显示屏上看到的零飘很小,我猜测可能是有JLINK和电池一起供电的原因。我将JLINK断开后,使用电池给板子供电,零飘一秒能有2到3°,这就很离谱了,我从知乎一篇文章那里找到了一个软件的解决方案,那就是按照它的漂移规律,写一个可以随时间变换角度的函数来减缓这个趋势。我一并把代码粘出来,我将这个代码放到了TIM7定时器里,每10ms中断一次,把处理过的角度用OLED显示一下,大概是1分重才漂移1°,这就符合我们的要求了,而这个yaw1就是我们处理过后的角度。

if(++mpu_count == 6000)mpu_count = 0;
Read_DMP(&Pitch,&Roll,&Yaw);
yaw1 = Yaw - 0.001*mpu_count-0.49;

转弯函数:

        这个转弯函数是一个比较简单的写法,我通过两轮的差速来让小车进行转弯,同时利用MPU6050来时刻测算角度,满足指定角度之后,就停止差速转弯。

        这里要注意的一点是,MPU6050在旋转的过程中,如果到了180°左右,会突然变成0,这就说明这时候小车转弯转过了,就要给MPU6050加上一个角度大于0的限制,否则一旦跃变成0,那肯定会不停地旋转。

#include "stm32f10x.h"
#include "move.h"
#include "MPU6050.h"
#include "motor.h"
#include "FSM.h"extern float Yaw1;
//float Target_Left = 85.000;
float bias_r;					//左转函数用到的偏差
float bias_last_r;		//左转函数用到的上一次偏差
float bais_error;
float bias_l;
float bias_last_l;
float media_r;
unsigned char stop_flag;
void turn_right_90(float Yaw1,float Target_right)
{if(Yaw1 < Target_right){	Motor3_forward(1499);Motor4_reverse(8499);}else{Move_stop();}
}
void turn_back(float Yaw1,float Target_right)
{if((Yaw1 < Target_right)&&(Yaw1 > 0)){	Motor3_forward(1499);Motor4_reverse(8499);}else if((Yaw1 > Target_right)||(Yaw1 < 0)){Move_stop();}
}

这篇关于四轮两驱小车(三):STM32驱动MPU6050进行转弯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/219919

相关文章

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

遮罩,在指定元素上进行遮罩

废话不多说,直接上代码: ps:依赖 jquer.js 1.首先,定义一个 Overlay.js  代码如下: /*遮罩 Overlay js 对象*/function Overlay(options){//{targetId:'',viewHtml:'',viewWidth:'',viewHeight:''}try{this.state=false;//遮罩状态 true 激活,f

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87