PID连续控制算法的表达式以及C语言实现

控制/MCU

1814人已加入

描述

  在工业应用中PID及其衍生算法是应用最广泛的算法之一,是当之无愧的万能算法,如果能够熟练掌握PID算法的设计与实现过程,对于一般的研发人员来讲,应该是足够应对一般研发问题了,而难能可贵的是,在我所接触的控制算法当中,PID控制算法又是最简单,最能体现反馈思想的控制算法,可谓经典中的经典。经典的未必是复杂的,经典的东西常常是简单的,而且是最简单的,想想牛顿的力学三大定律吧,想想爱因斯坦的质能方程吧,何等的简单!简单的不是原始的,简单的也不是落后的,简单到了美的程度。

  PID算法的一般形式:

  PID

  PID的流程简单到了不能再简单的程度,通过误差信号控制被控量,而控制器本身就是比例、积分、微分三个环节的加和。这里我们规定(在t时刻):

  1.输入量为rin(t);

  2.输出量为rout(t);

  3.偏差量为err(t)=rin(t)-rout(t);

  PID

  1. 数字(离散)PID控制算法的表达式:

  将PID调节器离散化,用差分方程来代替连续系统的微分方程,分为位置式和增量式两类。

  重点理解概念如下:

  a) 基本偏差e(t):表示当前测量值与设定目标值间的差,设定目标是被减数,结果可为正或负值,正值表示未达到目标,负值表示超过设定值。(代表比例)

  b) 偏差和:即每次测量的差值总和,注意正负(代表积分)

  c) 基本偏差的相对偏差:即e(t)-e(t-1)用本次的基本偏差减去上一次的基本偏差。(代表微分)

  位置式:

  PID

  增量式

       PID

  位置式和增量式三个参数的作用:

  1. Kp参数:能迅速反映误差,从而减小误差,但他不能消除稳态误差,加大Kp还会引起系统的不稳定。

  2. Ki参数:只要有足够的时间,积分作用将能完全消除误差。但其缺点积分控制是偏差累积控制,控制作业缓慢,但是如果积分作用太强会使系统的超调量加大,甚至出现振荡。

  3. Kd参数:预测误差变化趋势,减小超调量,克服振荡,使系统的稳定性提高,还能加快系统的动态响应速度,减小调整时间,从而改善系统的动态性能。

  参考代码如下:

  [cpp] view plain copy/*

  位置型pid

  */

  #include 《stdio.h》

  #include《ioctl.h》

  struct _pid{

  float SetSpeed; //定义设定值

  float ActualSpeed; //定义实际值

  float err; //定义偏差值

  float err_last; //定义上一个偏差值

  float Kp,Ki,Kd; //定义比例、积分、微分系数

  float voltage; //定义电压值(控制执行器的变量)

  float integral; //定义积分值

  }pid;

  //项目中获取到的参数

  void PID_init(){

  printf(“PID_init begin \n”);

  pid.SetSpeed=0.0;

  pid.ActualSpeed=0.0;

  pid.err=0.0;

  pid.err_last=0.0;

  pid.voltage=0.0;

  pid.integral=0.0;

  pid.Kp=0.2; //自己设定

  pid.Ki=0.015; //自己设定

  pid.Kd=0.2; //自己设定

  printf(“PID_init end \n”);

  }

  float PID_realize(float speed){

  pid.SetSpeed=speed; //设定值

  pid.err=pid.SetSpeed-pid.ActualSpeed; //设定值-实际值

  pid.integral+=pid.err; //积分值,偏差累加

  pid.voltage=pid.Kp*pid.err+pid.Ki*pid.integral+pid.Kd*(pid.err-pid.err_last);

  pid.err_last=pid.err; //上一个偏差值

  pid.ActualSpeed=pid.voltage*1.0; //算出实际值

  return pid.ActualSpeed; //返回

  }

  int main(){

  printf(“System begin \n”);

  PID_init();

  int count=0;

  while(count《1000)

  {

  float speed=PID_realize(200.0);

  printf(“%f\n”,speed);

  count++;

  }

  return 0;

  }

  增量式代码:

  [cpp] view plain copy/*

  增量型pid

  */

  #include《stdio.h》

  #include《stdlib.h》

  struct _pid{

  float SetSpeed; //定义设定值

  float ActualSpeed; //定义实际值

  float err; //定义偏差值

  float err_next; //定义上一个偏差值

  float err_last; //定义最上前的偏差值

  float Kp,Ki,Kd; //定义比例、积分、微分系数

  }pid;

  void PID_init(){

  pid.SetSpeed=0.0;

  pid.ActualSpeed=0.0;

  pid.err=0.0;

  pid.err_last=0.0;

  pid.err_next=0.0;

  pid.Kp=0.2;

  pid.Ki=0.015;

  pid.Kd=0.2;

  }

  float PID_realize(float speed){

  pid.SetSpeed=speed;

  pid.err=pid.SetSpeed-pid.ActualSpeed;

  float

  incrementSpeed=pid.Kp*(pid.err-pid.err_next)+pid.Ki*pid.err+pid.Kd*(pid.err-2*pid.err_next+pid.err_last);

  pid.ActualSpeed+=incrementSpeed;

  pid.err_last=pid.err_next;

  pid.err_next=pid.err;

  return pid.ActualSpeed;

  }

  int main(){

  PID_init();

  int count=0;

  while(count《1000)

  {

  float speed=PID_realize(200.0);

  printf(“%f\n”,speed);

  count++;

  }

  return 0;

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分