PID控制算法的C语言实现-完整版-笔记

 

PID控制算法的C语言实现一 PID算法原理

    

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

https://i-blog.csdnimg.cn/blog_migrate/c3bc639469d71651febebefee7ef30b4.png

 通过误差信号控制被控量

https://i-blog.csdnimg.cn/blog_migrate/769bff454bbe58bc13ed2f66722bffb9.png

   2.输入量rin(t)为电机转速预定值;    

   3.输出量rout(t)为电机转速实际值;    

    4.执行器为直流电机

    5.传感器为光电码盘,假设码盘为10线

    6.直流电机采用PWM调速 转速用单位 /min 表示;   

 

不难看出以下结论: 

   

  1.输入量rint)为电机转速预定值(转/min;    

  2 输出量rout(t)为电机转速实际值(转/min;    

    3.偏差量为预定值和实际值之差(转/min;

 

那么以下几个问题需要弄清楚: 

    1.通过PID环节之后的U(t)是什么值呢? 

    2.控制执行器(直流电机)转动转速应该为电压值(也就是PWM占空比)。    

   3.那么U(t)PWM之间存在怎样的联系呢?

 http://blog.21ic.com/user1/3407/archives/2006/33541.html(见附录1)这篇文章上给出了一种方法,即,每个电压对应一个转速,电压和转速之间呈现线性关系。但是我考虑这种方法的前提是把直流电机的特性理解为线性了,而实际情况下,直流电机的特性绝对不是线性的,或者说在局部上是趋于线性的,这就是为什么说PID调速有个范围的问题。具体看一下

  

http://articles.e-works.net.cn/component/article90249.htm(见附录2)这篇文章就可以了解了。所以在正式进行调速设计之前,需要现有开环系统,测试电机和转速之间的特性曲线(或者查阅电机的资料说明),然后再进行闭环参数整定。这篇先写到这,下一篇说明连续系统的离散化问题。并根据离散化后的特点讲述位置型PID和增量型PID的用法和C语言实现过程。

 

 

PID控制算法的C语言实现二 PID算法的离散化

上一节中,我论述了PID算法的基本形式,并对其控制过程的实现有了一个简要的说明,通过上一节的总结,基本已经可以明白PID控制的过程。这一节中先继续上一节内容补充说明一下。 

   1.说明一下反馈控制的原理,通过上一节的框图不难看出,PID控制其实是对偏差的控制过程

  

 2.如果偏差为0,则比例环节不起作用,只有存在偏差时,比例环节才起作用。   

 

 3.积分环节主要是用来消除静差,所谓静差,就是系统稳定后输出值和设定值之间的差值,积分环节实际上就是偏差累计的过程,把累计的误差加到原有系统上以抵消系统造成的静差。 

  

 4.而微分信号则反应了偏差信号的变化规律,或者说是变化趋势,根据偏差信号的变化趋势来进行超前调节,从而增加了系统的快速性。 

   好了,关于PID的基本说明就补充到这里,下面将对PID连续系统离散化,从而方便在处理器上实现。下面把连续状态的公式再贴一下:

https://i-blog.csdnimg.cn/blog_migrate/dfdc67b98138140c6658802d9db57647.png

假设采样间隔为T,则在第K T时刻: 

偏差err(K)=rin(K)-rout(K); 

积分环节用加和的形式表示,即err(K)+err(K+1)+„„

微分环节用斜率的形式表示,即[err(K)-err(K-1)]/T; 

从而形成如下PID离散表示形式:

https://i-blog.csdnimg.cn/blog_migrate/4a680aa768cd5a18bdaf143089d65ad6.png

至于说KpKiKd三个参数的具体表达式,我想可以轻松的推出了,这里节省时间,不再详细表示了。

 

其实到这里为止,PID的基本离散表示形式已经出来了。目前的这种表述形式属于位置型PID另外一种表述方式为增量式PID,由U上述表达式可以轻易得到:

https://i-blog.csdnimg.cn/blog_migrate/91d4b8fb906cd4fb8a1a6867793e6ef8.png

这就是离散化PID的增量式表示方式,由公式可以看出,增量式的表达结果和最近三次的偏差有关,这样就大大提高了系统的稳定性。需要注意的是最终的输出结果应该为 

       

    u(K)+增量调节值

 

PID的离散化过程基本思路就是这样,下面是将离散化的公式转换成为C语言,从而实现微控制器的控制作用。

 

PID控制算法的C语言实现三 位置型PIDC语言实现

  上一节中已经抽象出了位置性PID和增量型PID的数学表达式,这一节,重点讲解C语言代码的实现过程,算法的C语言实现过程具有一般性,通过PID算法的C语言实现,可以以此类推,设计其它算法的C语言实现。

 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

/*-------------------------------------------

       位置型PID C实现(控制电机转速)

--------------------------------------------*/

 

#include <iostream>

 

using namespace std;

 

void pid_value_init(void);

float PID_realize(float speed);

 

 

//(1)定义PID 结构体变量

 

struct pid

{

    float SetSpeed;    //设定速度

    float ActualSpeed;      //实际值

    float err;      //定义偏差值

    float err_last;       //上一个偏差值

    float Kp, Ki, Kd;     //p,i,d系数

    float voltage;    //电压值

    float integral;     //积分值,即积分部分的累计值

}pid;

 

 

 

int main()

{

    int count = 0;

 

    cout << "Please begin \n";

    pid_value_init();

 

    while (count < 1000)

    {

        float speed = PID_realize(200.0);

 

        cout <<"value is " <<speed<<endl ;

        count++;

    }

 

    system("pause");

}

 

//(3) 控制算法注意:这里用了最基本的算法实现形式,没有考虑死区问题,

//没有设定上下限,只是对公式的一种直接的实现,后面的介绍当中还会逐渐的对此改进。

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;

}

 

//(2) 初始化变量

void pid_value_init(void)

{

    cout << "pid_value_init begin \n" << endl;

    system("pause");

 

    pid.SetSpeed = 0;

    pid.ActualSpeed = 0;

    pid.err = 0;

    pid.err_last = 0;

    pid.integral = 0;

    pid.voltage = 0;

 

    pid.Kp = 0.1;

    pid.Ki = 0.1;

    pid.Kd = 0.1;

 

    cout << "pid_value_init end \n" << endl;

    system("pause");

}

 

PID控制算法的C语言实现四 增量型PIDC语言实现

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

/*-------------------------------------------

    2 位置型PID C实现(控制电机转速)

--------------------------------------------*/

 

//(1)定义PID 结构体变量

struct pid

{

    float SetSpeed;    //设定速度

    float ActualSpeed;      //实际值

    float err;      //k,定义偏差值

    float err_last;       //k-1,上一个偏差值

    float err_last_next;  //k-2

    float Kp, Ki, Kd;     //p,i,d系数

     

}pid;

 

 

 

int main()

{

    int count = 0;

 

    cout << "Please begin \n";

    pid_value_init();

 

    while (count < 100)

    {

        float speed = PID_realize(200.0);

 

        cout << "value is " << speed << endl;

        count++;

    }

 

    system("pause");

}

 

 

 

//(3) 控制算法注意:这里用了最基本的算法实现形式,没有考虑死区问题,

//没有设定上下限,只是对公式的一种直接的实现,后面的介绍当中还会逐渐的对此改进。

float PID_realize(float speed)

{

    float incrementSpeed;

    pid.SetSpeed = speed;

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

     

 

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

 

    pid.ActualSpeed += incrementSpeed;

    pid.err_last = pid.err;

    pid.err_last_next = pid.err_last;

    return pid.ActualSpeed;

}

 

//(2) 初始化变量

void pid_value_init(void)

{

    cout << "pid_value_init begin \n" << endl;

    system("pause");

 

    pid.SetSpeed = 0;

    pid.ActualSpeed = 0;

    pid.err = 0;

    pid.err_last = 0;

    pid.err_last_next = 0;

 

    pid.Kp = 0.1;

    pid.Ki = 0.15;

    pid.Kd = 0.1;

 

    cout << "pid_value_init end \n" << endl;

    system("pause");

}

  

PID控制算法的C语言实现五 积分分离的PID控制算法C语言实现

   在普通PID控制中,引入积分环节的目的主要是为了消除静差,提高控制精度。但在过程的启动、结束或大幅度增减设定时,短时间内系统输出有很大的偏差,会造成PID运算的积分积累,致使控制量超过执行机构可能允许的最大动作范围对应的极限控制量,引起系统较大的振荡,这在生产中是绝对不允许的。 

积分分离控制基本思路是,当被控量与设定值偏差较大时,取消积分作用,以免由于积分作用使系统稳定性降低,超调量增大;当被控量接近给定量时,引入积分控制,以便消除静差,提高控制精度

具体实现的步骤是: 

1、根据实际情况,人为设定阈值ε0 

2、当e (k)ε时,采用PD控制,可避免产生过大的超调,又使系统有较快的响应; 

3、当e (k)≤ε时,采用PID控制,以保证系统的控制精度 

 

<体现的思想就是分段控制

积分分离控制算法可表示为:

https://i-blog.csdnimg.cn/blog_migrate/be1b07c900ac38e2211d8562a42ab70a.png

https://i-blog.csdnimg.cn/blog_migrate/2c1f02430da340d75736e98cd4bbaa86.png

为了克服这一问题,引入了积分分离的概念,其基本思路是 当被控量与设定值偏差较大时,取消积分作用当被控量接近给定值时,引入积分控制,以消除静差,提高精度。其具体实现代码如下

 

1

2

3

4

5

6

7

8

9

10

11

12

13

if (abs(pid.err) > 200)

    {

        index = 0;

 

    }

    else

    {

        index = 1;

        pid.integral += pid.err;

    }

     

     

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

  

系统到199所有的时间是原来时间的1/2(这里我没有算时间,不过运算次数确实是减少了),系统的快速性得到了提高。

 

PID控制算法的C语言实现六 抗积分饱和的PID控制算法C语言实现

    所谓的积分饱和现象是指如果系统存在一个方向的偏差,PID控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置,若控制器输出U(k)继续增大,执行器开度不可能再增大,此时计算机输出控制量超出了正常运行范围而进入饱和区。一旦系统出现反向偏差,u(k)逐渐从饱和区退出。进入饱和区越深则退出饱和区时间越长。在这段时间里,执行机构仍然停留在极限位置而不随偏差反向而立即做出相应的改变,这时系统就像失控一样,造成控制性能恶化,这种现象称为积分饱和现象或积分失控现象。 

     防止积分饱和的方法之一就是抗积分饱和法,该方法的思路是在计算u(k)时,首先判断上一时刻的控制量u(k-1)是否已经超出了极限范围:如果u(k-1)>umax,则只累加负偏差如果u(k-1)<umin,则只累加正偏差。从而避免控制量长时间停留在饱和区。直接贴出代码,不懂的看看前面几节的介绍。

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

//(1)定义PID 结构体变量

struct pid

{

    float SetSpeed;    //设定速度

    float ActualSpeed;      //实际值

    float err;      //定义偏差值

    float err_last;       //上一个偏差值

    float Kp, Ki, Kd;     //p,i,d系数

    float voltage;    //电压值

    float integral;     //积分值,即积分部分的累计值

 

    //抗积分饱和

    float umax;

    float umin;

}pid;

 

 

 

int main()

{

    int count = 0;

 

    cout << "Please begin \n";

    pid_value_init();

 

    while (count < 100)

    {

        float speed = PID_realize(200.0);

 

        cout <<"value is " <<speed<<endl ;

        cout << "   " << endl;

        count++;

 

        system("pause");

    }

 

    system("pause");

}

 

 

 

//(3) 控制算法注意:这里用了最基本的算法实现形式,没有考虑死区问题,

//没有设定上下限,只是对公式的一种直接的实现,后面的介绍当中还会逐渐的对此改进。

float PID_realize(float speed)

{

    int index;

    pid.SetSpeed = speed;

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

     

    //抗积分饱和过程

    if (pid.ActualSpeed > pid.umax)

    {

        if (abs(pid.err) > 200)

        {

            index = 0;

 

        }

        else

        {

            index = 1;

            if (pid.err < 0)    //向反向积分

            {

                pid.integral += pid.err;

            }

        }

    }

 

    else if (pid.ActualSpeed < pid.umin)

    {

        if (abs(pid.err) > 200)

        {

            index = 0;

 

        }

        else

        {

            index = 1;

            if (pid.err < 0)

            {

                pid.integral += pid.err;

            }

        }

    }

 

    else

    {

        if (abs(pid.err) > 200)

        {

            index = 0;

 

        }

        else

        {

            index = 1;

            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;

}

 

//(2) 初始化变量

void pid_value_init(void)

{

    cout << "pid_value_init begin \n" << endl;

    system("pause");

 

    pid.SetSpeed = 0;

    pid.ActualSpeed = 0;

    pid.err = 0;

    pid.err_last = 0;

    pid.integral = 0;

    pid.voltage = 0;

 

    pid.Kp = 0.1;

    pid.Ki = 0.15;

    pid.Kd = 0.1;

 

    pid.umax = 400;

    pid.umin = -200;

 

    cout << "pid_value_init end \n" << endl;

    system("pause");

}

  

PID控制算法的C语言实现八 变积分的PID控制算法C语言实现

     变积分PID可以看成是积分分离的PID算法的更一般的形式。在普通的PID控制算法中,由于积分系数ki是常数,所以在整个控制过程中,积分增量是不变的。但是,系统对于积分项的要求是,系统偏差大时,积分作用应该减弱甚至是全无,而在偏差小时,则应该加强。积分系数取大了会产生超调,甚至积分饱和,取小了又不能短时间内消除静差。因此,根据系统的偏差大小改变积分速度是有必要的。

    变速积分的基本思想是,设法改变积分项的累加速度,使其与偏差大小相对应:偏差越大,积分越慢;反之则越快,有利于提高系统品质。 

     设置系数f(e(k)),它是e(k)的函数。当e(k)增大时,f减小,反之增大。变速积分的PID积分项表达式为:

https://i-blog.csdnimg.cn/blog_migrate/3de1a44d4d2c6708eefacc3d3c3c4db4.png

 系数f与偏差当前值∣e(k)∣的关系可以是线性的或是非线性的,例如,可设为:

https://i-blog.csdnimg.cn/blog_migrate/5932cf7e09e815cc1c19464cdccf0c1a.png

 

这里给积分系数前加上一个比例值index   

 abs(err)<180时,index=1; 

      180<abs(err)<200时,index=200-abs(err)/20;    

    abs(err)>200时,index=0; 

   最终的比例环节的比例系数值为ki*index; 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

//变积分过程

    if (abs(pid.err) > 200){

        index = 0;

    }

    else if (abs(pid.err) < 180){

        index = 1;

        pid.integral += pid.err;

    }

    else{

        index = (200 - abs(pid.err) / 20);

        pid.integral += pid.err;

    }

     

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

  

稳定速度貌似确实快。。。。。。。。。

运算值有负值,这是怎么回事????(一脸闷比)

 

PID控制算法的C语言实现九

1微分先行PID控制算法 

微分先行PID控制的特点是只对输出量yout(k)进行微分,而对给定值rin(k)不进行微分。这样,在改变给定值时,输出不会改变,而被控量的变化通常是比较缓和的。这种输出量先行微分控制适用于给定值rin(k)频繁升降的场合,可以避免给定值升降时引起系统振荡,从而明显地改善了系统的动态特性 

  https://i-blog.csdnimg.cn/blog_migrate/c65861344f16bc2deb18f9076aa856e6.png

 

2不完全微分PID控制算法

    PID控制中,微分信号的引入可改善系统的动态特性,但也易引进高频

干扰,在误差扰动突变时尤其显出微分项的不足。若在控制算法中加入低通滤波器,则可使系统性能得到改善 

     不完全微分PID的结构如下图。左图将低通滤波器直接加在微分环节上,右图是将低通滤波器加在整个PID控制器之后 

 

https://i-blog.csdnimg.cn/blog_migrate/cc094eadfddb2eb916de934866785d5d.png

3带死区的PID控制算法

   

在计算机控制系统中,某些系统为了避免控制作用过于频繁,消除由于频繁动作所引起的振荡,可采用带死区的PID控制算法,控制算式为:

 https://i-blog.csdnimg.cn/blog_migrate/c30fe91082bb639f646a953c5562a90a.png

式中,e(k)为位置跟踪偏差,e0是一个可调参数,其具体数值可根据实际控制对象由实验确定。若e0值太小,会使控制动作过于频繁,达不到稳定被控对象的目的;若e0太大,则系统将产生较大的滞后  控制算法流程:

https://i-blog.csdnimg.cn/blog_migrate/423784c367a0d9df339af63731461732.png

 

 

注:<我们电子设计竞赛里,在简易倒立摆控制装置中就采用了带死区的PID控制算法,当时并不知道这个名称,这也就是在现场测试的时候为什么老师会问我们摆能够保持倒立静止不动,而不是靠左右抖动来控制平衡,就是因为我在里面设置了死区:好像是5度的角度>

 

PID控制算法的C语言实现十 专家PID与模糊PIDC语言实现

本节是PID控制算法的C语言实现系列的最后一节,前面8节中,已经分别从PID的实现到深入的过程进行了一个简要的讲解,从前面的讲解中不难看出,PID的控制思想非常简单,其主要问题点和难点在于比例、积分、微分环节上的参数整定过程,对于执行器控制模型确定或者控制模型简单的系统而言,参数的整定可以通过计算获得,对于一般精度要求不是很高的执行器系统,可以采用拼凑的方法进行实验型的整定。

 

然而,在实际的控制系统中,线性系统毕竟是少数,大部分的系统属于非线性系统,或者说是系统模型不确定的系统,如果控制精度要求较高的话,那么对于参数的整定过程是有难度的。专家PID和模糊PID就是为满足这方面的需求而设计的。专家算法和模糊算法都归属于智能算法的范畴,智能算法最大的优点就是在控制模型未知的情况下,可以对模型进行控制。这里需要注意的是,专家PID也好,模糊PID也罢,绝对不是专家系统或模糊算法与PID控制算法的简单加和他是专家系统或者模糊算法在PID控制器参数整定上的应用。也就是说,智能算法是辅助PID进行参数整定的手段

其实在前面几节的讲述中,已经用到了专家PID的一些特例行为了,从第五节到第八节都是专家系统一些特列化的算法,对某些条件进行了局部的判定,比如如果偏差太大的话,就去除积分项,这本身就是含有经验的专家系统。

 

专家系统、模糊算法,需要参数整定就一定要有整定的依据,也就是说什么情况下整定什么值是要有依据的,这个依据是一些逻辑的组合,只要找出其中的逻辑组合关系来,这些依据就再明显不过了。下面先说一下专家PIDC语言实现。正如前面所说,需要找到一些依据,还得从PID系数本身说起。 

 

1.比例系数Kp的作用是加快系统的响应速度,提高系统的调节精度。Kp越大,系统的响应速度越快,系统的调节精度越高,但是容易产生超调,甚至会使系统不稳定。Kp取值过小,则会降低调节精度,使响应速度缓慢,从而延长调节时间,是系统静态、动态特性变差;

   

   2.积分作用系数Ki的作用是消除系统的稳态误差。Ki越大,系统的静态误差消除的越快,但是Ki过大,在响应过程的初期会产生积分饱和的现象,从而引起响应过程的较大超调。若Ki过小,将使系统静态误差难以消除,影响系统的调节精度;

   

3.微分系数Kd的作用是改善系统的动态特性,其作用主要是在响应过程中抑制偏差向任何方向的变化,对偏差变化进行提前预报。但是kd过大,会使响应过程提前制动,从而延长调节时间,而且会降低系统的抗干扰性。

 

首先我们规定一个误差的极限值,假设为Mmax;规定一个误差的比较大的值,假设为Mmid;规定一个误差的较小值,假设为Mmin 

 

abse>Mmax时,说明误差的绝对值已经很大了,不论误差变化趋势如何,都应该考虑控制器的输入应按最大(或最小)输出,以达到迅速调整误差的效果,使误差绝对值以最大的速度减小。此时,相当于实施开环控制。    

e*ec>0时,说明误差在朝向误差绝对值增大的方向变化,此时,如果abs(e)>Mmid,说明误差也较大,可考虑由控制器实施较强的控制作用,以达到扭转误差绝对值向减小的方向变化,并迅速减小误差的绝对值。此时如果abs(e)<Mmid,说明尽管误差是向绝对值增大的方向变化,但是误差绝对值本身并不是很大,可以考虑控制器实施一般的控制作用,只需要扭转误差的变化趋势,使其向误差绝对值减小的方向变化即可。 

   

e*err<0e*err(k-1)>0或者e=0时,说明误差的绝对值向减小的方向变化,或者已经达到平衡状态,此时保持控制器输出不变即可。 

   e*err<0e*err(k-1)<0时,说明误差处于极限状态。如果此时误差的绝对值较大,大于Mmin,可以考虑实施较强控制作用。如果此时误差绝对值较小,可以考虑实施较弱控制作用。 

   abs(e)<Mmin时,说明误差绝对值很小,此时加入积分,减小静态误差。 上面的逻辑判断过程,实际上就是对于控制系统的一个专家判断过程。

 

PID控制算法的c语言实现十二 模糊PID的参数整定

这几天一直在考虑如何能够把这一节的内容说清楚,对于PID而言应用并没有多大难度,按照基本的算法设计思路和成熟的参数整定方法,就算是没有经过特殊训练和培训的人,也能够在较短的时间内容学会使用PID算法。可问题是,如何能够透彻的理解PID算法,从而能够根据实际的情况设计出优秀的算法呢。

通过讲述公式和基本原理肯定是最能说明问题的,可是这样的话怕是犯了专家的错误了。对于门槛比较低的技术人员来讲,依然不能透彻理解。可是说的入耳了,能不能透彻说明也是一个问题,所以斟酌了几天,整理了一下思路才开始完成PID系列文章的最后一篇。

我所说的最后一篇不代表PID的功能和发展就止步与此,仅仅是说明,透过这一些列的文章,基本上已经可以涵盖PID设计的要点,至于更深入的研究,就交给有需要的读者去做。

上一节中大致讲述了一下模糊算法。实际上模糊算法的很多概念在上一节中并没有深入的解释。举的例子也只是为了说明模糊算法的基本含义,真正的模糊算法是不能这么设计的,当然也不会这么简单。模糊算法的核心是模糊规则,如果模糊规则制定的出色,那么模糊算法的控制效率就高。其实这是智能算法的一般特性,规则是系统判断和处理的前提。那么就说说PID的规则该怎么制定。

我们知道,模糊算法的本质是对PID的三个参数进行智能调节。那么首先要提出的问题是如何对PID的参数进行调节?这个问题其实是参数整定的问题,现实当中有很多整定方法。可是我们需要从根本上了解为什么这么整定,才能知道该如何建立数学模型进行分析。那么要回答如何整定参数的问题,就需要先明白PID参数的作用都是什么?对系统有什么影响?

 

我们从作用和副作用两个方面说明参数对系统的影响。

 1.比例环节Kp,作用是加快系统的响应速度,提高系统的调节精度,副作用是会导致超调

 2.积分环节Ki,作用是消除稳态误差,副作用是导致积分饱和现象;   

 3.微分环节Kd,作用是改善系统的动态性能,副作用是延长系统的调节时间。 

 

理解了上述问题,那么就可以辩证施治,对症下药了。比如说,如果系统响应速度慢,我们就加大Kp的取值,如果超调量过大我们就减小Kp的取值等等。可是问题这些语言的描述该如何用数学形式表达出来呢。我们所知道的,反馈系统的实质就是系统的输出量作为反馈量与系统的输入量进行作差,从而得到系统的误差e,那么这个误差e就能够反应目前系统所处的状态。误差e可以表明目前系统的输出状态到底偏离要求多少。而误差e的变化律ec,表示误差变化的速度。这样,我们可以根据这两个量的状态来分析三个参数此时应该如何取值,假如e为负方向比较大,ec也为负方向增大状态,此时比例环节要大一些,从而加快调节速度,而积分环节要小一些,甚至不加积分环节,从而防止负方向上出现饱和积分的现象。微分环节可以稍加一些,在不影响调节时间的情况下,起到改善系统动态性能的作用。

 

  • 44
    点赞
  • 250
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
PID是一种常见的控制算法,用于控制系统的稳定性和精度。它的核心思想是通过比较实际输出值和设定值确定反馈方向和强度,进一步调整输出值。由于该算法实现过程相对较复杂,编写PID控制器的代码需要了解一定的数学和电子技术知识。 在C语言实现PID控制器时,可以分为三个部分:输入、处理和输出。输入阶段是通过传感器获取反馈信号,并将其转化为数字信号进行处理。处理阶段主要包括比较反馈信号和设定值,计算PID控制器的各项参数,并输出控制指令。最后,控制指令通过执行器转化为物理输出信号,实现对待控制对象的控制。 具体而言,在C语言实现PID控制器的代码,需要进行如下步骤: 1.定义变量和常量:在定义阶段,需要定义存储输入和输出信号的变量,以及控制器常量和参数。 2.获取输入信号:通过传感器获取反馈信号,并将其转换成数字信号,保存在输入变量中。 3.计算误差:将输入信号与给定的目标值进行比较,计算误差并存储。 4.计算控制指令:根据P、I、D三个参数,计算出控制指令,将其存储在输出变量中。 5.输出信号:通过执行器将输出信号转化为物理信号,实现对监控对象的控制。 需要特别注意的是,PID控制器的P、I、D三个参数需要经过调优才能达到较好的控制效果。在实际的C语言程序中,一般通过试错法来优化这些参数,并不断更新算法实现的代码。 总而言之,PID控制算法是一种经典的控制算法,在工业控制和电子技术领域得到了广泛的应用。在实现PID控制器的C语言代码时,需要引用相关库函数并掌握基本的数学和程序语言知识。优化PID参数可以进一步提高算法的控制效果,实现系统的高精度和稳定性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值