跳过正文

STM32-pid平衡车

·2595 字·6 分钟· loading · loading ·
Baoxo
作者
Baoxo
技术宅也会梦见云朵彩虹
作者
hehe
心之所动,且随缘去吧。
飞起来!

STM32-pid平衡车详细教学
#

本文是基于stm32f103c8t6单片机开发的平衡小车项目。这个项目常用于广大学子的pid算法的入门项目,我认为pid应用并非很难,重要的是调参。所以调参的过程很重要。而且平衡车也相对简单,也以选择它作为学完32后的第一个项目(本人就是)。本人的小车添加了直立环,速度环和转向环。最后有源码和调好的视频。


一.下面介绍平衡车的硬件:
#

  • 1.一个开发板或者用面包板也可以,开发板可以自己嘉立创打板,也可以选择淘宝的亚博智能科技的开发板。
  • 2.两个编码电机(520,370都可以,只要有编码器就行),或者买直流电机再买编码器,也是可以的。
  • Ps:如果买亚博智能科技的板子,需要买他家的电机,因为别的商家的电机接口不一样!
  • 3.tb6612电机驱动不多说,买个10多块的,不要图便宜买几块的,到时候小车抽搐就难受了。
  • 4.hc-06蓝牙通信模块,用于手机控制小车,也可用上位机调参。
  • 5.Mpu605陀螺仪模块,这个模块用于测量小车的三维的各种参数。
  • 6.12v可充电的锂电池,开发板应有降压模块。
  • 7.Oled0.96屏幕,可有可无。
  • 8.车模(轮胎等等)。
  • 9.St-link下载器(也有可用J-link等下载器)。
  • 10.如果要加避障功能,可以购买超声波避障模块。
  • 11.适当的杜邦线,螺丝刀,电池充电器等等基础器件。

ps:可能说的不全,如果有遗漏根据自己的需求自行购买。 贴一张组装好的照片

二.介绍用到的单片机软件资源:
#

  • 1.3个通用定时器分别是:TIM2,TIM3,TIM3.
  • 2.1个usart3串口
  • 3.Oled和Mpu6050的软件模拟IIC通信

PS:如果添加避障模块,应该还要一个定时器用来计时超声波模块。其他功能如果需要 自行分配单片机资源。

三.介绍主要硬件模块的使用方式:
#

  • 1.tb6612: 下面是tb6612的引脚图

PwmA和PwmB是要从单片机输入的两个pwm波接收口,Ain1,Ain2为PwmA的io控制,对应的为右边的A01,A02,通过控制两个io口的高低电平来控制电机的正反转。同理PwmB也是如此。至于Vcc和Gnd是用来上电的(要共地)。STBY接5V/3.3V,VM接12V即可.

  • 2.电机编码器:
    这个图片已经介绍的很清楚了,有的电机接口不一样,要注意。
  • 3.mpu6050:这个模块涉及太多,简单应用可以去看b站江科大的mpu6050, https://blog.csdn.net/weixin_41640116/article/details/104878646 这是更加详细的介绍,有需要可以去看看。

四.下面是各个软件资源的分配:
#

  • 1.TIM2:输出两路pwm波,开启定时中断,再次中断中存放着最主要的电机控制程序,周期应该最好不要超过10us。
  • 2.TIM3和TIM4为读取两个电机的编码值。
  • 3.Usart3用于与手机相连接。

五.接着介绍最主要的pid部分:
#

六.Pid代码:
#

(Ps:直立环需P,D,速度环需P,I,转向环需P,D)

1.三环变量声明:
#

extern float Kp,Ki,Kd;   //直立环参数
float err;               //此次误差
float last_err;          //上次误差
float err_sum=0;         //误差累加
float err_difference;    //误差的差值

extern float VKp,VKi;    //速度环参数
float err2;               //此次误差
float filt_velocity;     //滤波后的速度
float last_filt_velocity;//上一次的滤波后的速度
//float velocity_err_sum=0;    //速度的累加
float velocity_sum;

extern float tkp,tkd;//转向环
float yaw_err,yaw_err_differnence,last_yaw_err;

2.直立环:
#

//直立环:
int vertical_PID_value(float measure,float calcu)
{

   err = measure - calcu;             //误差
   err_sum+=err;                      //误差的累加
   err_difference = err - last_err;   //误差的差值
   last_err = err;                    //此次误差记录为“上次误差”
   
   return Kp*err + Ki*err_sum + Kd*err_difference;
}

3.速度环:
#

//速度环:
int velocity_PID_value(int velocity_measure,int velocity_calcu)
{
   float a=0.3; 	//滤波系数(反映滤波程度)
   err2=velocity_measure-velocity_calcu;
   filt_velocity = a*err2 + (1-a)*last_filt_velocity; //一阶速度滤波
   
   velocity_sum+=  filt_velocity;                        //速度的累加
   I_xianfu(&velocity_sum,3000);                         //累加限幅,调参时可以去掉
   last_filt_velocity = filt_velocity;                   //此次速度记录为“上次速度”

   return VKp*filt_velocity + VKi*velocity_sum;
}


//I限幅:
void I_xianfu(float *velocity_sum,int max)
{
   if(*velocity_sum>max)  *velocity_sum=max;
   if(*velocity_sum<-max) *velocity_sum=-max;
}

4.转向环:
#

//转向环
int yaw_pid_value(float yaw_measure,float yaw_calcu){ 

   yaw_err=yaw_measure-yaw_calcu;
   
   //防止临界突然转动,改变系统稳定
   if(yaw_err>=180){yaw_err-=360;}
   if(yaw_err<-180){yaw_err+=360;}
   
   yaw_err_differnence=yaw_err-last_yaw_err;
   last_yaw_err=yaw_err;
   return tkp*yaw_err+tkd*yaw_err_differnence;
}

七.Pid调参:
#

PS:极性就是参数符号的正负。 (所有调参时初始参数为0,一点一点加,调极性时所有环的pid参数初始为0)


1.直立环:
#

  • 确立极性;给P一定的值,如果发现小车有缓慢摔倒而不是促进摔倒的话,证明极性正确。
  • P值;P值不断加大直到出现低频抖动。
  • D值:D值增加后发现有一定的平衡性,加到小车可以平稳的直立,但注意此时是假平衡,他只可以站立一会,所以速度环弥补,为了引用速度环还要增加D值,知道出现低频的快速抖动,注意要及时关闭电机,防止电机电流过大损坏电机或其他器件。

2.速度环(正反馈):
#

  • 确定极性:给一定P值,用手转动轮子,轮子很快的转动起来,证明极性正确,否则你会发现有一股力阻止你转动轮子。
  • 工程经验:多年来总结的经验,加入速度环之前应将直立环的参数调成原来的0.6倍。
  • 增大PI值:速度环P=200*I,根据此关系可以一起调两个值,逐渐增大,直到出现平稳状态,如果出现一些抖动,可适当增大直立环的D值来抑制系统。

3.转向环:
#

  • 还是要确定极性:和速度环差不多。
  • 调参:首先转向环可以有三种组合方式: 纯p控制,p+d控制,p+d+i控制。如果只有p,调法很简单,极性确认完之后,p从0往上加,直到你满意的效果为止。如果p大了,就会出现过冲现象,即给小车一个角度理论值后(或者用手拨弄一下小车)车头会左右摆动几下才稳定,此时就可以加入d来抑制过冲,也是从0开始往上加,观察到过冲越来越小,直到你满意为止,如果d太大了,小车会抽搐(高频率小幅度震荡),要避免这种现象发生,这就是最常用的p+d控制。如果你想追求更高的精度,消除稳态误差,那么加一点点i就可以了,即p+d+i控制,不过这个稳态误差一般可以忽略不计,如果你稳态误差很大,考虑是不是p太小了。

PS:调参视频:可观看

点我<-

或者

更加详细

八.控制代码部分
#

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){
		if(MPU6050_DMP_Get_Data(&pitch,&roll,&yaw)==0)
	{ 	
			
			measure = roll;                                     //roll测量值
			calcu = zhongzhi;                                   //roll理论值
			measure_yaw=yaw;
			velocity = ( read_encoder2() + read_encoder1() )/2; //速度测量值      
		
		  //PID计算:直立环+速度环
			PWM = vertical_PID_value(measure, calcu) + 1.88555*velocity_PID_value(velocity,ad_v);
			//1.88555这个系数可以有也可没有,用pid参数可以弥补,1.88555就是我大概试出来的一个范围然后瞎打的
			PWM_yaw=yaw_pid_value(measure_yaw,calcu_yaw);
			
			//转向环计算
			pwm_left=PWM-PWM_yaw;
			pwm_right=PWM+PWM_yaw;		
		
			PWM_Xianfu(5000,&PWM);      //PWM限幅,速度环调参时可以先去掉
			
			SETPWM_left(pwm_left);SETPWM_right(pwm_right);
			if(motor_flag) {SETPWM_left(pwm_left);SETPWM_right(pwm_right);} //给电机PWM
			else           {SETPWM_left(0);SETPWM_right(0);} //关闭电机		
	}
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}
(直立环和速度环为串级pid,要保证定时中断周期不超过10us)

9.成功视频
#

视频中的蓝牙调试助手随便一找就有,作者在这里就不贴链接了(因为作者也找不着了)

点此获取源码:

源码

有问题主页联系作者或者邮箱:1039214848@qq.com

相关文章

一个简单的CE修改器教程
·841 字·2 分钟· loading · loading
介绍一下使用七牛云对象存储加速网站
·422 字·1 分钟· loading · loading
介绍使用cdn加速来加速全站
·690 字·2 分钟· loading · loading