赞
踩
提示:本文章的串级PID位置速度控制,是在前两篇文章速度控制,位置控制的基础上实现的,这一章节中不需要额外的cubemx的配置,只需要写简单的代码即可,复杂的地方在于串级pid的调试过程。
pid是我们在学习单片机中首先要学会的控制算法,而串级pid又是在单pid的基础上衍生出来的,他能更好的控制系统,这篇文章主要介绍stm32如何编写串级pid的代码,没有对pid进行分析和解释,要想了解串级原理的可以参考这篇文章。
在之前的基础上我们已经能分别对电机的位置和电机的速度进行相应的控制了 ,那么现在的问题是当电机转到指定位置的过程中电机的速度不可控,所以我们就需要通过串级pid来进行速度的调节,我么把电机的位置环作为外环,电机的转速我们作为内环。
和前面一节的区别就是多了一个Double_Loop_Control()
函数,其实这个函数就是简单的把两个串在一起而已,代码阅读起来很简单,就不多说了。
pid.c
int Double_Loop_Control(int position, int target_position, int current_speed, int desired_speed) { int target_speed; int pwm_output; // 位置环控制 target_speed = Position_PID(position, target_position); /* 目标速度上限处理 */ if (target_speed > desired_speed)// 目标速度的最大值 { target_speed = desired_speed; } else if (target_speed < -desired_speed) { target_speed = -desired_speed; } // 速度环控制 pwm_output = Incremental_PI(current_speed, target_speed); return pwm_output; } /* 多环控制 */ /* * 函数功能:位置式PID控制器 * 入口参数:编码器测量位置信息,目标位置 * 返回 值:电机PWM * 根据位置式离散PID公式 * pwm=Kp*e(k)+Ki*∑e(k)+Kd[e(k)-e(k-1)] * e(k)代表本次偏差 * e(k-1)代表上一次的偏差 * ∑e(k)代表e(k)以及之前的偏差的累积和;其中k为1,2,,k; * pwm代表输出 **************************************************************************/ int Position_PID (int position,int target) { float Kp=0.5,Ki=0.005,Kd=1; static float Bias,Pwm,Integral_bias,Last_Bias; Bias=target-position; //计算偏差 Integral_bias+=Bias; //求出偏差的积分 if(Integral_bias>400)Integral_bias=400; //对积分 限幅 if(Integral_bias<-400)Integral_bias=-400; //积分限幅 防止到达目标位置后过冲 Pwm=Kp*Bias+Ki*Integral_bias+Kd*(Bias-Last_Bias); //位置式PID控制器 Last_Bias=Bias; //保存上一次偏差 return Pwm; //增量输出 } /************************************************************************** 函数功能:增量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=30,Ki=10; static int Bias,Pwm,Last_bias; Bias=Target-Encoder; //计算偏差 Pwm+=Kp*(Bias-Last_bias)+Ki*Bias; //增量式PI控制器 Last_bias=Bias; //保存上一次偏差 return Pwm; //增量输出 } /************************************************************************** 函数功能:限制PWM赋值 入口参数:无 返回 值:无 **************************************************************************/ int Xianfu_Pwm(int moto) //限制幅度的函数 { int Amplitude=7000; //===PWM满幅是8400 限制7000 if(moto<-Amplitude) moto = -Amplitude; if(moto>Amplitude) moto = Amplitude; return moto; }
pid.h
#ifndef __PID_H
#define __PID_H
#include "main.h"
#include "moto.h"
int Double_Loop_Control(int position, int target_position, int current_speed, int desired_speed);
int Position_PID (int position,int target);
int Incremental_PI (int Encoder,int Target);
int Xianfu_Pwm(int moto) ;//限制幅度的函数
#endif
就是简单的得到的速度值和位置值进行赋值。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//双环 { if(htim==(&htim9))//因为我采用的是定时器6 { int target_position=20000; int desired_speed=70; int moto_pwm; int Encoder; int CurrentPosition_; Encoder=Read_Encoder(); CurrentPosition_=Read_CurrentPosition(); moto_pwm=Double_Loop_Control(CurrentPosition_, target_position, Encoder, desired_speed); moto_pwm=Xianfu_Pwm(moto_pwm); Set_Pwm(moto_pwm); printf("samples: %d ,%d ,%d ,%d ,%d \n",CurrentPosition_,target_position, Encoder, desired_speed,moto_pwm); } }
其中位置环采用的是位置式PID控制器,速度环采用的是增量式PI控制器。在这种情况下,您需要分别调整位置环和速度环的PID参数,以下是一些基本的参考步骤:
调整位置环的PID参数:
a. 将Ki和Kd参数设为0,仅保留Kp参数。
b. 将目标位置值设置为一个较小的值(例如10),逐步增加Kp,直到系统开始出现持续振荡。记录此时的Kp值,称为临界增益Ku2。同时,记录振荡周期,称为临界周期Tu2。
c. 使用Ziegler-Nichols方法设置位置式PID控制器的参数。例如,可以使用以下参数:
Kp2 = 0.6 * Ku2
Ki2 = 2 * Kp2 / Tu2
Kd2 = Kp2 * Tu2 / 8
d. 应用调整后的位置环参数,并观察系统性能。如果仍然需要改进,请微调参数,直到获得满意的位置控制性能。
调整速度环的PID参数:
a. 将Kd参数设为0,仅保留Kp和Ki参数。
b. 将目标速度值设置为一个较小的值(例如50),逐步增加Kp,直到系统开始出现持续振荡。记录此时的Kp值,称为临界增益Ku1。同时,记录振荡周期,称为临界周期Tu1。
c. 使用Ziegler-Nichols方法设置增量式PI控制器的参数。例如,可以使用以下参数:
Kp1 = 0.6 * Ku1 / 20
Ki1 = 2 * Kp1 * 20 / Tu1
d. 应用调整后的速度环参数,并观察系统性能。如果仍然需要改进,请微调参数,直到获得满意的速度控制性能。
需要注意的是,在实际调试过程中,根据系统的实际需求和工作条件,可能需要在Ziegler-Nichols建议的参数基础上进行微调。您可以尝试修改各个参数,观察系统对其的敏感程度,并据此进行优化。同时,调整参数的过程中也需要密切关注系统的响应和性能,避免引起系统不稳定或控制性能不佳等问题。
下面介绍一下我的方法:
1.内环的参数整定
由于内环是速度环,要是前面你的速度环已经整定完毕以后你就可以直接使用那个值了,这时候千万不要让外环接入。
最简答的方法就是Double_Loop_Control()
函数中的
// 速度环控制
pwm_output = Incremental_PI(current_speed, target_speed);
将其中的target_speed
直接写成一个固定的值例如设置为15
// 速度环控制
pwm_output = Incremental_PI(current_speed, 15);
由此去整定速度环中p和i的值(因为用的是pi增量式所以没有d)。
2.外环的参数整定
当内环的整定完毕以后就可以把刚刚修改成15的那个改回原来的target_speed
这时候就先设置p为0.005,id都为0,这个时候来观察图像。
例如p为0.5时候图像
然后有些抖动我们就缩小p的值
这时候看来就好了很多,然后就需要对i的值进行整定
开的时候我把i设置为1,图像有明显的抖动
这种大的抖动就需要➗2或者➗10,接着我设定为0.5抖动没有丝毫的变化,接着我又设置为0.05
抖动基本消除,但是依然还有几个波动,接着减小为0.005
这个时候的基本没有抖动了大致已经是我么需要的样子了。
还需要调整一下d的值以次来抵御外部的干扰,我将其设置为1。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。