/*==================================================================================================== Main Program
=====================================================================================================*/
double sensor (void) // Dummy Sensor Function {
return 100.0; }
void actuator(double rDelta) // Dummy Actuator Function {}
void main(void) {
PID sPID; // PID Control Structure double rOut; // PID Response (Output) double rIn; // PID Feedback (Input)
PIDInit ( &sPID ); // Initialize Structure sPID.Proportion = 0.5; // Set PID Coefficients sPID.Integral = 0.5; sPID.Derivative = 0.0;
sPID.SetPoint = 100.0; // Set PID Setpoint for (;;) { // Mock Up of PID Processing rIn = sensor (); // Read Input
rOut = PIDCalc ( &sPID,rIn ); // Perform PID Interation actuator ( rOut ); // Effect Needed Changes } }
#include
#include \ /* derivative-specific definitions */ #include
#define VV_KPVALUE 3 //比例 #define VV_KIVALUE 40 //积分 #define VV_KDVALUE 3 //微分
#define VV_MAX 10000 //返回的最大值,是pwm的周期值 #define VV_MIN 0
#define VV_DEADLINE 0X08 //速度PID,设置死区范围 typedef struct PID //定义数法核心数据
{
signed int vi_Ref; //速度PID,速度设定值 signed int vi_FeedBack; //速度PID,速度反馈值
signed long vi_PreError; //速度PID,前一次,速度误差,,vi_Ref - vi_FeedBack signed long vi_PreDerror; //速度PID,前一次,速度误差之差,d_error-PreDerror; unsigned int v_Kp; //速度PID,Ka = Kp
unsigned int v_Ki; //速度PID,Kb = Kp * ( T / Ti ) unsigned int v_Kd; //速度PID, signed long vl_PreU; //电机控制输出值 }PID;
PID sPID; // PID Control Structure void PIDInit(void) {
sPID.vi_Ref = 0 ; //速度设定值 sPID.vi_FeedBack = 0 ; //速度反馈值
sPID.vi_PreError = 0 ; //前一次,速度误差,,vi_Ref - vi_FeedBack sPID.vi_PreDerror = 0 ; //前一次,速度误差之差,d_error-PreDerror; sPID.v_Kp = VV_KPVALUE; sPID.v_Ki = VV_KIVALUE; sPID.v_Kd = VV_KDVALUE;
sPID.vl_PreU = 0 ; //电机控制输出值
} unsigned int v_PIDCalc( PID *pp ) {
signed long error,d_error,dd_error;
error = (signed long)(pp->vi_Ref - pp->vi_FeedBack); // 偏差计算 d_error = error - pp->vi_PreError; dd_error = d_error - pp->vi_PreDerror; pp->vi_PreError = error; //存储当前偏差 pp->vi_PreDerror = d_error;
if( ( error < VV_DEADLINE ) && ( error > -VV_DEADLINE ) ); //设置调节死区 //速度PID计算
pp->vl_PreU += (signed long)( pp -> v_Kp * d_error + pp -> v_Ki * error pp->v_Kd*dd_error);
else if( pp->vl_PreU >= VV_MAX ) //速度PID,防止调节最高溢出 pp->vl_PreU = VV_MAX;
+
else if( pp->vl_PreU <= VV_MIN ) //速度PID,防止调节最低溢出 pp->vl_PreU = VV_MIN; else;
return ( pp->vl_PreU ); // 返回预调节占空比 void main(void) {
/* put your own code here */ InitMCu(); IncPIDInit();
int g_CurrentVelocity=0; //全局变量也初始化
int g_Flag=0; //全局变量也初始化 EnableInterrupts; While(1) {
if (g_Flag&&vi_FeedBack) {
PWMOUT+= v_PIDCalc( PID *pp ); g_Flag&=~ vi_FeedBack; } } }
for(;;) {
_FEED_COP(); /* feeds the dog */ } /* loop forever */
/* please make sure that you never leave main */ }
PID控制器参数选择的方法很多,例如试凑法、临界比例度法、扩充临界比例度法等。但是,对于PID控制而言,参数的选择始终是一件非常烦杂的工作,需要经过不断的调整才能得到较为满意的控制效果。依据经验,一般PID参数确定的步骤如下: (1) 确定比例系数Kp
确定比例系数Kp时,首先去掉PID的积分项和微分项,可以令Ti=0、Td=0,使之成为
纯比例调节。输入设定为系统允许输出最大值的60%~70%,比例系数Kp由0开始逐渐增大,直至系统出现振荡;再反过来,从此时的比例系数Kp逐渐减小,直至系统振荡消失。记录此时的比例系数Kp,设定PID的比例系数Kp为当前值的60%~70%。 (2) 确定积分时间常数Ti
比例系数Kp确定之后,设定一个较大的积分时间常数Ti,然后逐渐减小Ti,直至系统出现振荡,然后再反过来,逐渐增大Ti,直至系统振荡消失。记录此时的Ti,设定PID的积分时间常数Ti为当前值的150%~
180%。
(3) 确定微分时间常数Td
微分时间常数Td一般不用设定,为0即可,此时PID调节转换为PI调节。如果需要设定,则与确定Kp的方法相同,取不振荡时其值的30%。 (4) 系统空载、带载联调
对PID参数进行微调,直到满足性能要求。 //定义变量
float Kp; //PI调节的比例常数 float Ti; //PI调节的积分常数 float T; //采样周期 float Ki;
float ek; //偏差e[k] float ek1; //偏差e[k-1] float ek2; //偏差e[k-2] float uk; //u[k]
signed int uk1; //对u[k]四舍五入取整 signed int adjust; //调节器输出调整量 //变量初始化 Kp=\ Ti=\。005; T=\
// Ki=\,微分系数Kd=KpTd/T=0.8,Td=0.0002,根据实验调得的结果确定这些参数 ek=\ ek1=0; ek2=0; uk=\ uk1=0; adjust=\
int piadjust(float ek) //PI调节算法 {
if( gabs(ek)<0.1 ) {
adjust=\ } else {
uk=\ //计算控制增量 ek1=ek;
uk1=(signed int)uk; if(uk>0) {
if(uk-uk1>=0.5) {
uk1=uk1+1;
} } if(uk<0) {
if(uk1-uk>=0.5) {
uk1=uk1-1; } }
adjust=\ } return adjust; }
下面是在AD中断程序中调用的代码。
。。。。。。。。。。。
else //退出软启动后,PID调节,20ms调节一次 {
EvaRegs.CMPR3=EvaRegs.CMPR3+piadjust(ek);//误差较小PID调节稳住 if(EvaRegs.CMPR3>=890) {
EvaRegs.CMPR3=890; //限制PWM占空比 } }
PID_控制参数如何设定调节
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)
![](/skin/haowen/images/icon_star.png)