2022年电赛小车题c题 软件流程

本文介绍了使用STM32RCT6单片机实现小车运动控制的过程,包括编码器接口模式的TIM4初始化、PWM波输出以及PID控制。强调了编码器输入的5V兼容性问题和芯片TB6612FN的使用注意事项。此外,分享了编码器计数、PWM波生成及电机正反转控制的代码实现,并给出了增量式PI控制器的算法。文章还提醒在系统设计中要注意模块间的相互影响,建议先实现开环控制再进行PID调整。
摘要由CSDN通过智能技术生成

题目要求要用TI公司的MCU,MSP系列的单片机。这里用stm32来实现所以功能,因为msp接触比较少就不分享了,msp430网上资料比较多比较容易上手。

我们主控用的是stm32rct6,这个单片机很强大有8个定时器,对于小车的运动控制要两个编码器模式的定时器来获取小车的每个时刻的脉冲,得到这个就可以得到当前轮子的实时速度了。要一个通用定时器来输出pwm波控制电机,要一个基本计时器来产生一个10ms中断来进行pid调节和脉冲的读取。这个中断也可以用pwm波的定时器来产生。多翻数据手册(不是中文参考手册)确定自己的需求。

驱动模块用的是TB6612FN,这个芯片一定要把stby角拉高才能驱动,vm是电机的额定功率,vcc是单片机高电平的电压看你是5v,还是3.3v,其实接3.3v就可以了。

下面这个图是例子

 兼容性:

 关于定时器的引脚分配,这篇文章分享:

STM32定时器要点-电子工程世界 (eeworld.com.cn)

其实有一个点一定一定要注意:

编码器是5v输入,要看定时器的配置引脚是不是满足5v的输入条件,配置相应的模式!!!(比赛的时候因为这个错误莫名其妙烧了芯片发现不出来,在快结束的时候烧了,这个bug不会一下就烧你芯片但是出现了就是致命的

软件上的控制就这么多,上干货:

encoder.c

/**************************************************************************
函数功能:把TIM4初始化为编码器接口模式
入口参数:无
返回  值:无
**************************************************************************/
void Encoder_Init_TIM4(void)
{
	RCC->APB1ENR|=1<<2;     //TIM4时钟使能
	RCC->APB2ENR|=1<<3;    //使能PORTb时钟
	GPIOB->CRL&=0X00FFFFFF;//PB6 PB7
	GPIOB->CRL|=0X44000000;//浮空输入
	/* 把定时器初始化为编码器模式 */ 
	TIM4->PSC = 0x0;//预分频器
	TIM4->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值 
  TIM4->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  TIM4->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  TIM4->CCER |= 0<<1;           //IC1不反向
  TIM4->CCER |= 0<<5;           //IC2不反向
	TIM4->SMCR |= 3<<0;	          //SMS='011' 所有的输入均在上升沿和下降沿有效
	TIM4->CR1 |= 0x01;    //CEN=1,使能定时器
}
/**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回  值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
    int Encoder_TIM;    
   switch(TIMX)
	 {
	   case 2:  Encoder_TIM= (short)TIM2 -> CNT;  TIM2 -> CNT=0;break;
		 case 3:  Encoder_TIM= (short)TIM3 -> CNT;  TIM3 -> CNT=0;break;	
		 case 4:  Encoder_TIM= (short)TIM4 -> CNT;  TIM4 -> CNT=0;break;	
		 default:  Encoder_TIM=0;
	 }
		return Encoder_TIM;
}

另外一个定时器自己写一下

encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H
#include <sys.h>	 
  

/**************************************************************************/
#define ENCODER_TIM_PERIOD (u16)(65535)   //不可大于65535 因为F103的定时器是16位的。
void Encoder_Init_TIM2(void);
void Encoder_Init_TIM4(void);
int Read_Encoder(u8 TIMX);
#endif

pwm波的输出

PWM.C

void MiniBalance_PWM_Init(u16 arr,u16 psc)
{		 					 
//	MiniBalance_Motor_Init(); //初始化电机控制所需IO
	RCC->APB1ENR|=1<<1;       //TIM3时钟使能    
	RCC->APB2ENR|=1<<3;       //PORTB时钟使能     
	GPIOB->CRL&=0XFFFFFF00;   //PORTB0 1复用输出
	GPIOB->CRL|=0X000000BB;   //PORTB0 1复用输出
	TIM3->ARR=arr;//设定计数器自动重装值 
	TIM3->PSC=psc;//预分频器不分频
	TIM3->CCMR2|=6<<12;//CH4 PWM1模式	
	TIM3->CCMR2|=6<<4; //CH3 PWM1模式	
	TIM3->CCMR2|=1<<11;//CH4预装载使能	 
	TIM3->CCMR2|=1<<3; //CH3预装载使能	  
	TIM3->CCER|=1<<12; //CH4输出使能	   
	TIM3->CCER|=1<<8;  //CH3输出使能	
	TIM3->CR1=0x8000;  //ARPE使能 
	TIM3->CR1|=0x01;   //使能定时器3 										  
} 

PWM.h

#ifndef __MOTOR_H
#define __MOTOR_H
#include <sys.h>	 

#define PWMA   TIM3->CCR4
#define AIN2   PBout(15)
#define AIN1   PBout(14)
//#define BIN2   PCout(5)
#define BIN2   PBout(13)
#define BIN1   PBout(12)


#define AIN4   PCout(6)
#define AIN3   PCout(7)
#define BIN3   PCout(8)
#define BIN4   PCout(9)

#define PWMB   TIM3->CCR3
void MiniBalance_PWM_Init(u16 arr,u16 psc);
void MiniBalance_Motor_Init(void);
#endif

电机驱动的引脚自己定义一下,随意一个四个引脚输出高低电平就可以控制正反转了。

然后产生一个10ms的中断,后来主控坏了只能用c8t6只有四个定时器就只能用time1来进行了

中断里面不仅跑的是采样,而且加入的pid,同时也要对pwm波进行限幅保护电机,同时控制电机正反转。

control.c

//int Target_velocity=30;  //设定速度控制的目标速度为50个脉冲每10ms
//int Target_velocity1=30;  //设定速度控制的目标速度为50个脉冲每10ms
int TIM1_UP_IRQHandler(void)  
{    
	if(TIM1->SR&0X0001)//5ms定时中断
	{   
		encoder();
		PWMA_TASK(20);
		PWMB_TASK(20);	

	}       	
	 return 0;	  
} 
void encoder(void){
		 TIM1->SR&=~(1<<0);                                       //===清除定时器1中断标志位		 
		 Encoder1=Read_Encoder(2);                                  //===读取编码器的值,M法测速,输出为每10ms的脉冲数

		 Encoder2=Read_Encoder(4);                                  //===读取编码器的值,M法测速,输出为每10ms的脉冲数
}
/**************************************************************************
函数功能:速度控制函数,最大60左右.不能超过(5v小电机)
入口参数:脉冲
返回  值:无
**************************************************************************/
void PWMA_TASK(int Target_velocity){
		 
		 Xianfu_Pwm();                                            //===PWM限幅
		 Moto1=Incremental_PI(Encoder1,Target_velocity);           //===速度PI控制器
//		 Moto1=Encoder1;
		 Set_Pwm1(Moto1);                                          //===赋值给PWM寄存器
}

void PWMB_TASK(int Target_velocity){
		 
		 Xianfu_Pwm();                                            //===PWM限幅
		 Moto2=Incremental_PI(Encoder2,Target_velocity);           //===速度PI控制器
		 Set_Pwm2(Moto2);                                          //===赋值给PWM寄存器
}
/**************************************************************************
函数功能:赋值给PWM寄存器
入口参数:PWM
返回  值:无
**************************************************************************/
void Set_Pwm1(int moto1)
{	
			if(moto1<0)			AIN2=0,			AIN1=1,AIN4=0,			AIN3=1;
			else 	          AIN2=1,			AIN1=0,AIN4=1,			AIN3=0;
			PWMA=myabs(moto1);
			PWMC=myabs(moto1);
}

void Set_Pwm2(int moto2)
{	
			if(moto2<0)			BIN2=0,			BIN1=1,BIN4=0,			BIN3=1;
			else 	          BIN2=1,			BIN1=0,BIN4=1,			BIN3=0;
			PWMB=myabs(moto2);
			PWMD=myabs(moto2);
}
/**************************************************************************
函数功能:限制PWM赋值 
入口参数:无
返回  值:无
**************************************************************************/
void Xianfu_Pwm(void)
{	
	  int Amplitude=7100;    //===PWM满幅是7200 限制在7100
    if(Moto1<-Amplitude) Moto1=-Amplitude;	
		if(Moto1>Amplitude)  Moto1=Amplitude;	
		if(Moto2<-Amplitude) Moto2=-Amplitude;	
		if(Moto2>Amplitude)  Moto2=Amplitude;	
}

/**************************************************************************
函数功能:绝对值函数
入口参数:int
返回  值:unsigned int
**************************************************************************/
int myabs(int a)
{ 		   
	  int temp;
		if(a<0)  temp=-a;  
	  else temp=a;
	  return temp;
}
/**************************************************************************
函数功能:增量PI控制器
入口参数:编码器测量值,目标速度
返回  值:电机PWM
根据增量式离散PID公式 
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)]
e(k)代表本次偏差 
e(k-1)代表上一次的偏差  以此类推 
pwm代表增量输出
在我们的速度控制闭环系统里面,只使用PI控制
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)
**************************************************************************/
int Incremental_PI (int Encoder,int Target)
{ 	
   float Kp=120,Ki=100;	
	 static int Bias,Pwm,Last_bias;
	 Bias=Encoder-Target;                //计算偏差
	 Pwm+=Kp*(Bias-Last_bias)+Ki*Bias;   //增量式PI控制器
	 Last_bias=Bias;	                   //保存上一次偏差 
	 return Pwm;                         //增量输出
}

 control.h

#ifndef __CONTROL_H
#define __CONTROL_H
#include "sys.h"
  /**************************************************************************

**************************************************************************/
#define PI 3.14159265
int TIM1_UP_IRQHandler(void);  
void Set_Pwm1(int moto1);
void Set_Pwm2(int moto2);
void Xianfu_Pwm(void);
int myabs(int a);
int Incremental_PI (int Encoder,int Target);
void PWMA_TASK(int Target_velocity);
void PWMB_TASK(int Target_velocity);
void encoder(void);
#endif

基本对于小车运动控制就在这里了,基本上所以的坑我们都踩过了,

最后一些惨痛教训:

1.不能带pid加系统的,小车系统每加一个模块就要重新调pid,所以pid是最后调的,先开环把所以功能先实现,要不然你不知道是pid的问题还是你本身模块驱动的问题或是接线的问题。切记切记! 

2.在做设计的时候要留有余量,特别是比赛的时候,用c8t6是把芯片榨干了,但是最后加模块的时候就很痛苦没有资源了,rc可以满足要求也相对比较便宜。

  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 2022电赛小车跟随行驶系统是指小车能够自主跟随指定目标进行行驶,达到自动驾驶的效果。该系统使用了激光雷达、摄像头、GPS等多个传感器进行数据采集,通过算法进行数据处理,实现了小车的自主导航和目标跟踪。 在该系统中,小车通过激光雷达进行环境感知,获取周围障碍物信息,同时通过摄像头进行图像识别,识别出目标物体并进行跟踪。此外,系统还使用GPS进行定位,保证小车在行驶过程中能够精准地跟踪目标移动。 该系统具有较高的安全性和可靠性,能够应用于自动驾驶车辆、机器人等领域,为人们的出行和生活带来更便捷、更安全的体验。 需要注意的是,在使用该系统时,需要对小车进行充分的测试和调试,保证系统的稳定性和可靠性。同时,需要遵守交通规则,确保小车的行驶安全,避免对人和物的损害。 ### 回答2: 2022电赛小车跟随行驶系统是一个基于智能控制的系统,通过传感器和计算机的处理,实现小车跟随车流自动行驶的功能。该系统采用的技术主要包括图像处理、控制算法和实时数据处理等方面。 在系统的实现过程中,首先需要搭建一个自动驾驶平台,通过安装多个相机和传感器,对前方的车流进行监测和识别。同时,也需要构建一个高效的图像处理算法,对监测得到的图像数据进行分析和处理,准确地识别车流的类型、速度和距离,并将数据传输至系统的控制器。 控制器是该系统的核心部分,它负责实现小车的自动控制,包括转向、加减速、避障等多个功能。在控制器中,需要设计出符合预定目标的运动规划算法,通过实时数据处理,决定小车的行驶方向和速度,并根据车流的变化实时调整。 此外,在小车跟随行驶系统的实现过程中,还需要充分考虑安全性和稳定性。在小车遇到障碍物或违规行为时,需要及时停车或避让,确保驾驶安全。同时,也需要设计出适应不同路况和天气的控制策略,确保小车能够稳定地跟随车流行驶。 综上所述,2022电赛小车跟随行驶系统是一个具有重大实际意义的项目,将为未来自动驾驶技术的发展提供有力支撑。 ### 回答3: 2022电赛小车跟随行驶系统(c)是基于现代控制理论和计算机技术进行设计开发的一款自动驾驶系统。该系统最主要的任务是让小车能够自主地跟随前方的车辆进行行驶。 该系统采用深度学习算法和机器视觉技术实现对前方车辆的识别和跟踪。通过摄像头获取的图像数据可以实时地进行图像处理,将车辆的位置、速度等数据提取出来,并传递给控制器进行处理。控制器则根据这些数据进行车辆控制,驱动电机和转向系统进行相应的操作,使小车跟随前车进行行驶。 此外,为了保证系统的安全性和稳定性,系统还需要具备避障和自动制动等功能。当前方有障碍物时,系统会自动识别并采取相应的措施进行避让或制动。在异常情况下,如失控或发生事故时,车辆会自动停车并向操作员发送警报通知。 2022电赛小车跟随行驶系统的成功实现对智能交通系统的发展和安全性能有着重要的意义。该系统可以大大提高交通安全性和交通运输效率,同时也促进了自动驾驶技术的发展和应用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值