基于C++的PID控制器
来源:互联网 发布:video.js 编辑:程序博客网 时间:2024/05/17 04:03
PID控制器是一种广泛用于各种工业控制场合的控制器,它结构简单,可以根据工程经验整定参数Kp,Ki,Kd. 虽然现在控制专家提出了很多智能的控制算法,比如神经网络,模糊控制等,但是PID仍然被广泛使用。
常见的PID控制器有位置PID控制器,增量PID控制器。两个PID控制器各有自己的优点,需要根据具体的场合来使用。
pid控制器的结构框图为:
(1)位置PID
连续形式公式如下:
也可以写成如下形式:
为了方便软件编程实现,一般转换成离散形式,即用连加代替积分,有差分代替微分,
离散型PID公式:
使用C++实现一个位置PID控制器,首先需要创建一个PID_position的类,其定义如下:
//位置式PIDclass PID_position{private: float kp;//比例系数 float ki;//积分系数 float kd;//微分系数 float target;//目标值 float actual;//实际值 float e;//误差 float e_pre;//上一次误差 float integral;//积分项public: PID_position(); ~PID_position(){}; PID_position(float p,float i,float d); float pid_control(float tar,float act);//执行PID控制 void pid_show();//显示PID控制器的内部参数};
接下来,对类中声明的方法进行定义;
//位置PIDPID_position::PID_position():kp(0),ki(0),kd(0),target(0),actual(0),integral(0){ e=target-actual; e_pre=e;}PID_position::PID_position(float p,float i,float d):kp(p),ki(i),kd(d),target(0),actual(0),integral(0){ e=target-actual; e_pre=e;}float PID_position::pid_control(float tar,float act){ float u; target=tar; actual=act; e=target-actual; integral+=e; u=kp*e+ki*integral+kd*(e-e_pre); e_pre=e; return u;}void PID_position::pid_show(){ using std::cout; using std::endl; cout<<"The infomation of this position PID controller is as following:"<<endl; cout<<" Kp="<<kp<<endl; cout<<" Ki="<<ki<<endl; cout<<" Kd="<<kd<<endl; cout<<" integral="<<integral<<endl; cout<<" target="<<target<<endl; cout<<" actual="<<actual<<endl; cout<<" e="<<e<<endl; cout<<" e_pre="<<e_pre<<endl;}
以上代码就可以实现一个位置PID控制器,只需要实例化PID_position类对象,调用相关的方法就可以实现P位置ID控制。
位置PID结构简单,但是由于有积分项,容易产生积分饱和的现象,而且它每次输出的都是全量,此全量均和过去的输出有关,易产生累计误差。需要对其进行改进,由此产生的改进型PID控制器——增量型PID控制器。其区别在于,控制器输出的不是全量,而只是增量,每次输出均与过去的所有状态无关,而且它没有积分项,运算量小,容易实现手动到自动的无冲击切换。
增量型PID控制器的公式如下:
可以表示为更一般的形式:
由此可以编写增量式PID的C++代码:
类声明为:
//增量式PIDclass PID_incremental{private: float kp; float ki; float kd; float target; float actual; float e; float e_pre_1; float e_pre_2; float A; float B; float C;public: PID_incremental(); PID_incremental(float p,float i,float d); float pid_control(float tar,float act); void pid_show();};
方法定义:
//增量PIDPID_incremental::PID_incremental():kp(0),ki(0),kd(0),e_pre_1(0),e_pre_2(0),target(0),actual(0){ A=kp+ki+kd; B=-2*kd-kp; C=kd; e=target-actual;}PID_incremental::PID_incremental(float p,float i,float d):kp(p),ki(i),kd(d),e_pre_1(0),e_pre_2(0),target(0),actual(0){ A=kp+ki+kd; B=-2*kd-kp; C=kd; e=target-actual;}float PID_incremental::pid_control(float tar,float act){ float u_increment; target=tar; actual=act; e=target-actual; u_increment=A*e+B*e_pre_1+C*e_pre_2; e_pre_2=e_pre_1; e_pre_1=e; return u_increment;}void PID_incremental::pid_show(){ using std::cout; using std::endl; cout<<"The infomation of this incremental PID controller is as following:"<<endl; cout<<" Kp="<<kp<<endl; cout<<" Ki="<<ki<<endl; cout<<" Kd="<<kd<<endl; cout<<" target="<<target<<endl; cout<<" actual="<<actual<<endl; cout<<" e="<<e<<endl; cout<<"e_pre_1="<<e_pre_1<<endl; cout<<"e_pre_2="<<e_pre_2<<endl;}
下面可以对两个控制器进行简单的测试,这里需要对PID的参数进行整定,笔者也是通过多次试验,最终获得了比较合理的kp,ki,kd。
测试代码如下:
#include<iostream>#include"pid_controller.h"using namespace std;int main(){ //测试增量PID PID_incremental pid1(0.35,0.65,0.005); float target=1000.0; float actual=0; float pid_increment=0.0; int N=50; pid1.pid_show(); cout<<"target="<<target<<endl; for(;N>0;N--) { pid_increment=pid1.pid_control(target,actual); actual+=pid_increment; cout<<"N="<<50-N<<" actual="<<actual<<endl; } pid1.pid_show(); //测试位置PID PID_position pid2(0.59,0.35,0.002); pid2.pid_show(); cout<<"target="<<target<<endl; N=100; for(;N>0;N--) { actual=pid2.pid_control(target,actual); cout<<"N="<<100-N<<" actual="<<actual<<endl; } pid2.pid_show(); system("pause"); return 0;}
测试结果显示增量PID,28次到达目标值1000,位置PID,61次达到1000.
完整代码见https://github.com/shuoyueqishi/PID-controller
- 基于C++的PID控制器
- 基于STM32与μC/GUI的多路PID控制器
- 经典PID控制器的缺陷
- PID控制器
- 分数阶PID控制器的分析界面
- 基于注解的控制器
- 通过PID 控制器的C实现来说明P I D 三参数的优点与不足
- PID控制器详解
- PID控制器原理详解
- 基于注解的Controller控制器
- 基于Ogre的角色控制器
- 基于AVR单片机: 两轮自平衡智能车(2)-PID控制器
- 基于BP神经网络的PID控制
- linux C 获取pid终极父进程的PID
- PID算法的C语言实现一 PID算法原理
- 一种基于μC/OS-III及STM32的多功能控制器
- 取PID遇到的c语言问题
- PID算法的C语言实现
- 面试题目44—扑克牌的顺子
- 解决RecyclerView代码复用问题
- 无领导小组讨论注意事项
- 面试题45—圆圈中最后剩下的数字
- 浅谈Web网站架构演变过程
- 基于C++的PID控制器
- 一犯再犯的面试错误
- Java发送邮件
- 面试题46—求1+2+3...+n
- 【技巧】浅谈Johnson算法
- 天生丽质小仙女-快速秒会VisualSVN Server的安装与配置
- 【JZOJ 5174】C
- 职场礼仪之西装十大禁忌
- Spring Boot实战之Maven