第17章-用6050走直线和转90度功能 平衡车入门---MPU6050陀螺仪的使用 超详细陀螺仪MPU6050模块输出姿态角

电子说

1.3w人已加入

描述

功能介绍放开头, 使用便捷无需愁

这是全网最详细、性价比最高的STM32实战项目入门教程,通过合理的硬件设计和详细的视频笔记介绍,硬件使用STM32F103主控资料多方便学习,通过3万字笔记、12多个小时视频、20多章节代码手把手教会你如何开发和调试。让你更快掌握嵌入式系统开发。

**V3.3.0-STM32智能小车 **

**视频: **[https://www.bilibili.com/video/BV16x4y1M7EN/?spm_id_from=333.337.search-card.all.click]

V3:HAL库开发、功能:PID速度控制、PID循迹、PID跟随、遥控、避障、PID角度控制、视觉控制、电磁循迹、RTOS等功能。

第17章-用6050走直线和转90度功能

17.1-6050姿态数据读取

STM32读取6050数据

先把我们的参考历程里面的6050文件复制过去
代码
添加文件
代码
代码
然后在魔术棒添加上面两个的路径,不再截图了。
简单阅读代码,知道 我们需要设置两个引脚,这两个引脚使用模拟IIC读取6050数据
1.在****mpuiic.c延时使用自己写的、引脚需要使用两个先设置推挽输出、高电平**
**代码

void mpuiic_Delayus(uint32_t usdelay)
{
  __IO uint32_t Delay = usdelay * (SystemCoreClock /8U/1000U/1000);//SystemCoreClock:系统频率
  do
  {
    __NOP();//使用空指令延时、移植不同单片机注意__NOP(); 执行时间
  }
  while (Delay --);
}
  //MPU IIC 延时函数
void MPU_IIC_Delay(void)
{
mpuiic_Delayus(2);
}
​
//初始化IIC
void MPU_IIC_Init(void)
{     
//  GPIO_InitTypeDef  GPIO_InitStructure;
//
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//先使能外设IO PORTB时钟 
//
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; // 端口配置
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //推挽输出
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
//  GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIO 
//
//  GPIO_SetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_11); //PB10,PB11 输出高

}

使用软件初始化两个引脚

6050_SDA--PB9

6050_SCL--PB8
代码
PB8-输出模式-起始输出高电平
代码
PB9 输出模式 起始状态高电平
代码
生成代码

打开我们的代码,是通过模拟IIC 读取6050数据的,我们知道SDA是模拟IIC的数据线 所以通信过程中是再输入和输出模式中切换的,但是我们的STM32CubeMX是设置的输出,是在哪里更改的模式那?

是通过寄存器设置的,在mpuiic.h可以看到

删除掉#include "sys.h"

把这个修改了
代码
2.在****mpuiic.h更改相内容

改成下面这样的
代码

//IO方向设置 设置SDA-PB9为输入或者输出
#define MPU_SDA_IN()  {GPIOB- >CRH&=0XFFFFFF0F;GPIOB- >CRH|=8< < 4;}
#define MPU_SDA_OUT() {GPIOB- >CRH&=0XFFFFFF0F;GPIOB- >CRH|=3< < 4;}
  1. 这是通过****按位与后赋值 &=按位或后赋值 |=
  2. 设置****端口配置高寄存器指定位。

先看一个例子
代码
代码
代码
更改设置SDA与SCL电平的宏
代码

//IO操作函数 
#define MPU_IIC_SCL_Hige    HAL_GPIO_WritePin(SCL_6050_GPIO_Port,SCL_6050_Pin,GPIO_PIN_SET)//设置SCL高电平
#define MPU_IIC_SCL_Low      HAL_GPIO_WritePin(SCL_6050_GPIO_Port,SCL_6050_Pin,GPIO_PIN_RESET)//设置SCL低电平
#define MPU_IIC_SDA_Hige        HAL_GPIO_WritePin(SDA_6050_GPIO_Port,SDA_6050_Pin,GPIO_PIN_SET)   //设置SDA高电平
#define MPU_IIC_SDA_Low         HAL_GPIO_WritePin(SDA_6050_GPIO_Port,SDA_6050_Pin,GPIO_PIN_RESET) //设置SDA低电平
   
#define MPU_READ_SDA            HAL_GPIO_ReadPin(SDA_6050_GPIO_Port,SDA_6050_Pin)    //读SDA电平

更改一下 mupiic.c文件

//把之前的MPU_IIC_SDA=1; 换成 MPU_IIC_SDA_Hige;
//MPU_IIC_SDA=0; 换成 MPU_IIC_SDA_Low;
//MPU_IIC_SCL=1;  换成 MPU_IIC_SCL_Hige;
//MPU_IIC_SCL=0;  换成 MPU_IIC_SCL_Low;
//

编译一下、删掉没有用的文件

把u8 替换为uint8_t
代码
**t替换一下,u8 替换为uint8_t u32替换为uint32_t **

可以一个文件一个文件的替换掉,如果整个工程替换其他HAL库文件内容也可能改变了
代码
删除多余的库文件

注释掉
代码
如果有其他的delay_ms 都替换为HAL_Delay

还有一个错误

if((txd&0x80) > >7) MPU_IIC_SDA_Hige;
else MPU_IIC_SDA_Low;

代码
编译一下 、没有错误和警告

然后在main.c中定义变量和添加同文件

float pitch,roll,yaw; // 俯仰角 横滚角 航向角#include "mpu6050.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"

代码
替换inv_mpu.h的

#include "stm32f1xx_it.h"

代码
初始化6050

HAL_Delay(500);//延时0.56050上电稳定后初始化
  MPU_Init(); //初始化MPU6050
  while(MPU_Init()!=0);
  while(mpu_dmp_init()!=0);

代码
我们通过下面的代码获得数据

sprintf((char *)Usart3String,"pitch:%.2f roll:%.2f yaw:%.2frn",pitch,roll,yaw);//显示6050数据
	HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),0xFFFF);//通过串口三输出字符 strlen:计算字符串大小	

   //mpu_dmp_get_data(&pitch,&roll,&yaw);//返回值:0,DMP成功解出欧拉角
    while(mpu_dmp_get_data(&pitch,&roll,&yaw)!=0){}  //这个可以解决经常读不出数据的问题

代码
然后我看一下 这个Usart3String 现在发送的大概多大的?
代码

uint8_t OledString[50];
uint8_t Usart3String[50];

编译、烧录、然后就可以连接手机蓝牙,在蓝牙软件查看数据了
代码

17.2-利用6050直线和90度(有代码)

为什么小车还是不能走直线

为什么两个电机转速一样不能走非常正直线,如何控制小车转弯90度。

当然,我们可以开环控制,但是控制效果可能不好,受外界影响比较大。

如果我们使用闭环控制,就要使用一个传感器来获得现在小车角度。
代码
[https://www.bilibili.com/video/BV1UV4y1p7Hd/?spm_id_from=333.337.search-card.all.click]

走直线(控制朝一个方向运动)

在pid.c中定义一个姿态控制使用的PID
代码

tPid pidMPU6050YawMovement;  //利用6050偏航角 进行姿态控制的PID

代码

pidMPU6050YawMovement.actual_val=0.0;
	pidMPU6050YawMovement.target_val=0.00;//设定姿态目标值
	pidMPU6050YawMovement.err=0.0;
	pidMPU6050YawMovement.err_last=0.0;
	pidMPU6050YawMovement.err_sum=0.0;
	pidMPU6050YawMovement.Kp=2;//定距离跟随的Kp大小通过估算PID输入输出数据,确定大概大小,然后在调试
	pidMPU6050YawMovement.Ki=0;
	pidMPU6050YawMovement.Kd=0;

仿照之前红外循迹代码编写姿态控制函数
代码

float  g_fMPU6050YawMovePidOut = 0.00f; //姿态PID运算输出
float  g_fMPU6050YawMovePidOut1 = 0.00f; //第一个电机控制输出
float  g_fMPU6050YawMovePidOut2 = 0.00f; //第一个电机控制输出

走直线程序如下(因为上电初始化时候航向角是0、而且pidMPU6050YawMovementPID结构体的目标值target_val 也是0)
代码


//*************MPU6050航向角 PID转向控制*****************//

sprintf((char *)Usart3String,"pitch:%.2f roll:%.2f yaw:%.2frn",pitch,roll,yaw);//显示6050数据 俯仰角 横滚角 航向角
HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const char *)Usart3String),0xFFFF);//通过串口三输出字符 strlen:计算字符串大小

//mpu_dmp_get_data(&pitch,&roll,&yaw);//返回值:0,DMP成功解出欧拉角
while(mpu_dmp_get_data(&pitch,&roll,&yaw)!=0){} //这个可以解决经常读不出数据的问题


g_fMPU6050YawMovePidOut = PID_realize(&pidMPU6050YawMovement,yaw);//PID计算输出目标速度 这个速度,会和基础速度加减

g_fMPU6050YawMovePidOut1 = 1.5 + g_fMPU6050YawMovePidOut;//基础速度加减PID输出速度
g_fMPU6050YawMovePidOut2 = 1.5 - g_fMPU6050YawMovePidOut;
if(g_fMPU6050YawMovePidOut1 >3.5) g_fMPU6050YawMovePidOut1 =3.5;//进行限幅
if(g_fMPU6050YawMovePidOut1 <0) g_fMPU6050YawMovePidOut1 =0;
if(g_fMPU6050YawMovePidOut2 >3.5) g_fMPU6050YawMovePidOut2 =3.5;
if(g_fMPU6050YawMovePidOut2 <0) g_fMPU6050YawMovePidOut2 =0;
motorPidSetSpeed(g_fMPU6050YawMovePidOut1,g_fMPU6050YawMovePidOut2);

然后调节PID参数

**顺序 先确定P 正负 然后P大小 **

然后D正负 然后D大小

最后调节的参数如下
代码

pidMPU6050YawMovement.Kp=0.02;//6050航向角PID运动控制 
	pidMPU6050YawMovement.Ki=0;
	pidMPU6050YawMovement.Kd=0.1;

然后我们把小车放在地上就可以完成一直朝着初始方向前进,如果往侧面推也会马上矫正。

转弯90度功能(控制转弯角度)

然后我们增加一下,如何旋转90度程序

在串口接收回调函数表姿态PID的目标值
代码

extern tPid pidMPU6050YawMovement;  //利用6050偏航角 进行姿态控制的PID

代码

if(g_ucUsart3ReceiveData == 'H')//转向90度
		{				
			if(pidMPU6050YawMovement.target_val <= 180)pidMPU6050YawMovement.target_val += 90;//目标值
		}
		if(g_ucUsart3ReceiveData == 'I')//转回90度
		{				
			if(pidMPU6050YawMovement.target_val >= -180)pidMPU6050YawMovement.target_val -= 90;//目标值
        }

然后我们的蓝牙APP增加两个发送按钮的设置
代码
现象 是上电小车向初始方向直行,如果推小车车头方向,小车能够立马矫正。

然后连接蓝牙发送转90度 小车会转90度,按下 转回90度小车回转回。

这样我们就把6050转向程序写完了,下面开始 把上面代码如何结合一下,然后讲解如何增加视觉功能。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分