一、PID学习
PID的知识网上有很多教学讲解的非常清楚,可以再参考学习【平衡小车之家】的视频教程。
二、位置PID学习
位置PID控制公式为:Pwm=Kp*e(K)+Ki*∑e(K)+Kd[e(K)-e(k-1)];其中:
Kp=设定的比例系数;Ki=设定的积分系数;Kd=设定的微分系数;e(K)=当前差(值);e(K-1)=上次差(值);∑e(K):历次差(值)的累积;
C语言实现函数:
int Position_PID(int encoder,int target)
{
float position_Kp=10,position_Ki=0.03,position_Kd=15;
static float bias,pwm,integral_bias,last_bias;
bias=encoder-target; //计算偏差
integral_bias+=bias; //求出偏差的积分
pwm=position_Kp*bias+position_Ki*integral_bias+position_Kd*(bias-last_bias);
last_bias=bias; //存储当前偏差作为下次计算的依据
return pwm;
}
函数实现流程:首先必须设定一个标准的定时,循环读取和反馈PID控制;
读取电机Encoder编码;
PID控制计算,计算出控制量;
PID控制量作为电机PWM控制电机转动;
encoder_R=__HAL_TIM_GET_COUNTER(&htim3); //读取右电机编码器的值
motor_R_PWM=Position_PID(encoder_R,target); //PID控制计算
Set_PWM(motor_R_PWM,0); //取绝对值/限幅/赋值给电机
data_to_computer(&encoder_R,&target); //上位机发送数据
三、匿名科创地面站(上位机)使用(简单的数据波形使用):
1、首先查看自己的USB转TTL设备使用的端口-不知道怎么查看的可以直接打开串口调试助手查看;
2、打开匿名客串地面站V4.34,在“程序设定”里设定刚才查到的端口号和设定的波特率;
3、点击右下角打开连接,如果程序运行正常,会看到RX有数据的传输;
4、点击“高级收码”,“帧格式设置”,选择“1”,勾选“使能该帧”和“显示该帧”;下面的“数据容器设置”中,选择页标签1的数据来源=帧1,数据位置=1,选择页标签“2”的数据来源=帧1,数据位置=4;
5、点击进入“数据波形”页面,勾选UserData_1和UserData_2,点击“开始显示”,即可在“数据波形”页面看到发送来的读取的点击Encoder编码数据和设定的目标值数据:
四、位置PID参数整定:
在使用PID控制中,比例控制是最基本的控制,根据需要PID控制可以衍生出P或PI、PD控制。其中:
比例P参数主要用于提高响应速度-即影响快速性;
积分I参数主要用于减少静差-即影响准确性;
微分D参数主要用于抑制震荡-即影响稳定性;
我用的电机的编码器是260线,A/B双相再经X4设置后,电机输出轴转动1轴的总编码数=1040,这里设定位置PID的目标=1040:
int target=1040; //位置PID参数整定:目标值
在PID控制子函数中设置Kp/Ki/Kd的值,并通过观察波形对PID参数进行调整:
1、设定position_Kp=500,position_Ki=0,position_Kd=0,波形如下:
Kp取值过高,电机处于抖动状态;
2、设定position_Kp=30,position_Ki=0,position_Kd=0,波形如下:
可以看出,只要比例P参数设定得当,单独的比例P控制就基本上能够达到预定目的,但是存在过量,需要减少Kd;存在震荡,可以加入Kd系数(一般Kd>Kp)抑制震荡;并且存在静差(稳定值同目标值有差异),可以加入Ki减少静差(Ki一般设置Kp的1/200左右);
3、设定position_Kp=10,position_Ki=0,position_Kd=15,波形如下:
五、增量式速度PID
1、增量PID控制公式:
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)]
在闭环速度控制中,可以只使用PI控制就能够达到目的,所以公式可以简化为:
pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)
2、C语言实现的函数
int Incremental_PI (int Encoder,int Target)
{
float Kp=20,Ki=30;
static int Bias,Pwm,Last_bias;
Bias=Encoder-Target; //计算偏差
Pwm+=Kp*(Bias-Last_bias)+Ki*Bias; //增量式PI控制器
Last_bias=Bias; //保存上一次偏差
return Pwm; //增量输出
}
3、测试函数
先测试在最大pwm时电机编码器5ms读取数据的差额:
设定pwm=7000,并使电机向前转动:
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_3,7000);//右电机Pwm输出
Motor_R_Forward(); //测试:使右电机向前转动
5ms定时循环读取并使用printf串口打印:
/*由stm32f1xx_it.c中void SysTick_Handler(void)子函数产生的5ms定时*/
if(delay5ms_flag==1) //5ms定时
{
encoder_R=__HAL_TIM_GET_COUNTER(&htim3); //测试:读取右电机编码器的值
printf("encoder_R=%d\r\n",encoder_R);
delay5ms_flag=0;
}
pwm=7000时每5ms编码器大约=70
设定目标值
int target=30; //速度PID参数整定目标值:不能超过Pwm=7000时的速度
测试函数
/* 电机速度PID闭环控制测试代码 */
encoder_R=__HAL_TIM_GET_COUNTER(&htim3); //测试:读取右电机编码器的值
bias_encoder_R=encoder_R-last_encoder_R; //计算同上次的差值:M法则 5ms编码器数据
motor_R_PWM=Incremental_PI(bias_encoder_R,target);//PI控制 Set_PWM(motor_R_PWM,0); //取绝对值/限幅/电机赋值 last_encoder_R=encoder_R;//保存本次编码器值
data_to_computer(&bias_encoder_R,&target); //上位机发送数据
下载的原代码加压后需要打开目录下的"Car_Test_PID"stm32CubeMX工程,重新生产MDK工程,编译前,点魔法棒“Options for Target”,在C/C++下添加自己的库函数“My Modular”文件夹的目录,并在“Application/user”组下添加目录下的所有.c文件,再编译。