✅ 操作成功!

位置式pid

发布时间:2023-06-07 作者:admin 来源:文学

位置式pid

位置式pid

秋微微博-微型音响

2023年2月21日发(作者:拇指的拼音)

【平衡⼩车制作】(六)位置式PID、直⽴环与速度环编程(超详解)

  ⼤家好,我是⼩政。本篇⽂章我将针对位置式PID算法、直⽴环、速度环等的编程进⾏详细的讲解,让每位⼩伙伴能够对这三个概念的

编程逻辑有更加清晰的理解。

⼀、直⽴环(PD控制器)

1.中⽂公式

 直⽴环输出=Kp1×⾓度偏差+Kd×⾓度偏差的微分

 //⾓度偏差=真实⾓度-期望⾓度

2.英⽂公式

 直⽴环PD控制器:Kp×Ek+Kd×Ek_D

 (Ek:⾓度偏差;Ek_D:⾓度偏差的微分)

Ek=真实⾓度-期望⾓度(Angle-Med,由陀螺仪MPU6050测得)

Ek_D=真实⾓速度(gyro_Y,由陀螺仪MPU6050测得)

3.软件编程

  根据理论公式进⾏软件编程,相信看完上⾯的讲解后这段代码应该⽐较清晰易懂。

/*****************

直⽴环PD控制器:Kp*Ek+Kd*Ek_D

⼊⼝:Med:机械中值(期望⾓度),Angle:真实⾓度,gyro_Y:真实⾓速度

出⼝:直⽴环输出

******************/

intVertical(floatMed,floatAngle,floatgyro_Y)

{

intPWM_out;

PWM_out=Vertical_Kp*(Angle-Med)+Vertical_Kd*(gyro_Y-0);

returnPWM_out;

}

⼆、速度环(PI控制器)

1.中⽂公式

 速度环输出=Kp2×电机速度偏差+Ki2×电机速度偏差的积分

 //电机速度偏差=真实速度-期望速度

2.英⽂公式

 速度环PI控制器:Kp×Ek+Ki×Ek_S

 (Ek:电机速度偏差;Ek_S:电机速度偏差的积分)

Ek=真实速度-期望速度(真实速度:左电机速度+右电机速度;期望速度:0)

Ek_S=速度偏差的累加

3.低通滤波

  期间需要低频滤波,我们是以直⽴环为主,速度环为辅,速度环相对于直⽴环来说是⼀个⼲扰,最终⽬的是直⽴。低频滤波作⽤是使得

波形更加平滑,滤除⾼频⼲扰,防⽌速度过⼤影响直⽴环正常⼯作。

4.积分限幅

  通过⽐较限制积分在规定范围内变动,不得超出。

5.软件编程

  根据理论公式进⾏软件编程,相信看完上⾯的讲解后这段代码应该⽐较清晰易懂。

/*****************

速度环PI控制器:Kp*Ek+Ki*Ek_S(Ek_S:偏差的积分)

******************/

intVelocity(intTarget,intencoder_left,intencoder_right)

{

//定义成静态变量,保存在静态存储器,使得变量不丢掉

staticintPWM_out,Encoder_Err,Encoder_S,EnC_Err_Lowout,EnC_Err_Lowout_last;

floata=0.7;

//1.计算速度偏差

//舍去误差--我的理解:能够让速度为"0"的⾓度,就是机械中值。

Encoder_Err=((encoder_left+encoder_right)-Target);

//2.对速度偏差进⾏低通滤波

//low_out=(1-a)*Ek+a*low_out_last

EnC_Err_Lowout=(1-a)*Encoder_Err+a*EnC_Err_Lowout_last;//使得波形更加平滑,滤除⾼频⼲扰,放置速度突变

EnC_Err_Lowout_last=EnC_Err_Lowout;//防⽌速度过⼤影响直⽴环的正常⼯作

//3.对速度偏差积分出位移

Encoder_S+=EnC_Err_Lowout;

//4.积分限幅

Encoder_S=Encoder_S>10000?10000:(Encoder_S<(-10000)?(-10000):Encoder_S);

//5.速度环控制输出

PWM_out=Velocity_Kp*EnC_Err_Lowout+Velocity_Ki*Encoder_S;

returnPWM_out;

}

三、转向环

1.中⽂公式

 转向环输出=系数×Z轴⾓速度

 (Z轴⾓速度由陀螺仪MPU6050测得)

2.软件编程

  转向环的编程⽐较简单,我们只需设置⼀个参数调节Z轴⾓速度即可。

/*****************

转向环:系数*Z轴⾓速度

******************/

intTurn(intgyro_Z)

{

intPWM_out;

PWM_out=(-0.6)*gyro_Z;

returnPWM_out;

}

四、控制函数

1、采集编码器数据和MPU6050⾓度信息

 编码器数据:左电机速度,右电机速度

(两个电机是相对安装,刚好相差180度,为了编码器输出极性⼀致,就需要对其中⼀个取反)

 MPU6050数据:⾓度数据,⾓速度数据,⾓加速度数据

2、将数据压⼊闭环控制中,计算出控制输出量

 直⽴环输出

 速度环输出

 转向环输出

3、把控制输出量加载到电机上,完成最终的控制

 左电机输出(编码器放置相对)

 右电机输出

 限幅

 赋值

4、控制中断函数

 ⾸先要判断是否接受到中断请求,即检测MPU6050的ANT引脚是否处在低电平(即为发⽣中断),然后清除中断标志位,进⾏接下来三

步(即上⾯的三个步骤)。

voidEXTI9_5_IRQHandler(void)

{

intPWM_out;

if(EXTI_GetITStatus(EXTI_Line5)!=0)//⼀级判定

{

if(PBin(5)==0)//⼆级判断

{

EXTI_ClearITPendingBit(EXTI_Line5);//清除中断标志位

//1.采集编码器数据&MPU6050⾓度信息

//电机是相对安装,刚好相差180度,为了编码器输出极性⼀致,就需要对其中⼀个取反

Encoder_Left=-Read_Speed(2);

Encoder_Right=Read_Speed(4);

mpu_dmp_get_data(&Pitch,&Roll,&Yaw);//读取⾓度

MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);//读取⾓速度

MPU_Get_Accelerometer(&aacx,&aacy,&aacz);//读取加速度

//2.将数据压⼊闭环控制中,计算出控制输出量

Velocity_out=Velocity(Target_Speed,Encoder_Left,Encoder_Right);//速度环

Vertical_out=Vertical(Velocity_out+Med_Angle,Roll,gyrox);//直⽴环

Turn_out=Turn(gyroz);

PWM_out=Vertical_out;//最终输出

//3.把控制输出量加载到电机上,完成最终控制

MOTO1=PWM_out-Turn_out;//左电机

MOTO2=PWM_out+Turn_out;//右电机

Limit(&MOTO1,&MOTO2);//PWM限幅

Load(MOTO1,MOTO2);//加载到电机上

}

}

}

五、整个控制函数源代码

1、control.c

#include"control.h"

floatMed_Angle=0;//机械中值,能使得⼩车真正平衡住的⾓度

floatTarget_Speed=0;//期望速度。---⼆次开发接⼝,⽤于控制⼩车前进后退及其速度。

float

Vertical_Kp=0,

Vertical_Kd=0;//直⽴环Kp、Kd

float

float

Velocity_Kp=0,//速度环Kp、Ki(正反馈)

Velocity_Ki=0;

float

Turn_Kp=0;

intVertical_out,Velocity_out,Turn_out;//直⽴环&速度环&转向环的输出变量

intVertical(floatMed,floatAngle,floatgyro_Y);//函数声明

intVelocity(intTarget,intencoder_left,intencoder_right);

intTurn(intgyro_Z);

voidEXTI9_5_IRQHandler(void)

{

intPWM_out;

if(EXTI_GetITStatus(EXTI_Line5)!=0)//⼀级判定

{

if(PBin(5)==0)//⼆级判断

{

EXTI_ClearITPendingBit(EXTI_Line5);//清除中断标志位

//1.采集编码器数据&MPU6050⾓度信息

//电机是相对安装,刚好相差180度,为了编码器输出极性⼀致,就需要对其中⼀个取反

Encoder_Left=-Read_Speed(2);

Encoder_Right=Read_Speed(4);

mpu_dmp_get_data(&Pitch,&Roll,&Yaw);//读取⾓度

MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);//读取⾓速度

MPU_Get_Accelerometer(&aacx,&aacy,&aacz);//读取加速度

//2.将数据压⼊闭环控制中,计算出控制输出量

Velocity_out=Velocity(Target_Speed,Encoder_Left,Encoder_Right);//速度环

Vertical_out=Vertical(Velocity_out+Med_Angle,Roll,gyrox);//直⽴环

Turn_out=Turn(gyroz);

PWM_out=Vertical_out;//最终输出

//3.把控制输出量加载到电机上,完成最终控制

MOTO1=PWM_out-Turn_out;//左电机

MOTO2=PWM_out+Turn_out;//右电机

Limit(&MOTO1,&MOTO2);//PWM限幅

Load(MOTO1,MOTO2);//加载到电机上

}

}

}

/*****************

直⽴环PD控制器:Kp*Ek+Kd*Ek_D

⼊⼝:Med:机械中值(期望⾓度),Angle:真实⾓度,gyro_Y:真实⾓速度

出⼝:直⽴环输出

******************/

intVertical(floatMed,floatAngle,floatgyro_Y)

{

intPWM_out;

PWM_out=Vertical_Kp*(Angle-Med)+Vertical_Kd*(gyro_Y-0);

returnPWM_out;

}

/*****************

速度环PI控制器:Kp*Ek+Ki*Ek_S(Ek_S:偏差的积分)

******************/

intVelocity(intTarget,intencoder_left,intencoder_right)

{

//定义成静态变量,保存在静态存储器,使得变量不丢掉

staticintPWM_out,Encoder_Err,Encoder_S,EnC_Err_Lowout,EnC_Err_Lowout_last;

floata=0.7;

floata=0.7;

//1.计算速度偏差

//舍去误差--我的理解:能够让速度为"0"的⾓度,就是机械中值。

Encoder_Err=((encoder_left+encoder_right)-Target);

//2.对速度偏差进⾏低通滤波

//low_out=(1-a)*Ek+a*low_out_last

EnC_Err_Lowout=(1-a)*Encoder_Err+a*EnC_Err_Lowout_last;//使得波形更加平滑,滤除⾼频⼲扰,放置速度突变

EnC_Err_Lowout_last=EnC_Err_Lowout;//防⽌速度过⼤影响直⽴环的正常⼯作

//3.对速度偏差积分出位移

Encoder_S+=EnC_Err_Lowout;

//4.积分限幅

Encoder_S=Encoder_S>10000?10000:(Encoder_S<(-10000)?(-10000):Encoder_S);

//5.速度环控制输出

PWM_out=Velocity_Kp*EnC_Err_Lowout+Velocity_Ki*Encoder_S;

returnPWM_out;

}

/*****************

转向环:系数*Z轴⾓速度

******************/

intTurn(intgyro_Z)

{

intPWM_out;

PWM_out=Turn_Kp*gyro_Z;

returnPWM_out;

}

👁️ 阅读量:0