学习目标

  1. 理解什么是PID
  2. 理解什么是位置式PID
  3. 理解什么是增量式PID

1. PID概述

PID(Proportional-Integral-Derivative)控制器是一种广泛应用于工程领域的控制算法,它包含三个主要部分:比例(P)、积分(I)和微分(D)。通过调整这三个部分来使系统的实际输出更接近期望输出。

  1. 比例(P)

比例控制根据误差(期望输出与实际输出之差)的大小来调整控制量。误差越大,控制量越大;误差越小,控制量越小。比例控制有助于快速减小误差,但可能导致稳态误差(静态误差)。

  1. 积分(I)

积分控制对误差进行积分,累积误差值。这有助于消除稳态误差,提高系统的精确度。但积分环节可能导致系统响应过慢和超调(当实际输出超过期望输出时)。

  1. 微分(D)

微分控制根据误差变化的速度来调整控制量。微分环节有助于减小超调现象,提高系统响应速度和稳定性。

实际应用中,通过调整PID控制器中的比例、积分和微分系数,可以使系统在不同场景下达到更好的控制效果。PID控制器被广泛应用于各种领域,如工业过程控制、航天器姿态控制、机器人运动控制等。

在实际运用中我们常用位置式PID和增量式PID,是两种不同的PID控制器实现方式。这两种方法都能实现PID控制的目标,但它们的计算方法和实际应用中的性能有所不同。

两者的主要区别在于计算方法:位置式PID直接根据误差值计算控制量,而增量式PID根据误差的变化计算控制量的变化。在实际应用中,增量式PID的性能通常更稳定,因为它可以避免积分饱和现象。此外,增量式PID在离散系统中更容易实现。然而,增量式PID对系统的采样时间和计算精度要求较高。在选择具体的实现方法时,需要根据实际应用场景和系统需求来权衡。

P控制

单纯P控制:kp = 10
image.png
单纯P控制:kp=5
image.png
示例代码

  1. void control_p_2(){
  2. while(1){
  3. // 明确输入: 目标624, 当前值
  4. // 获取编码器当前读数
  5. short enc = encoder_get();
  6. // 目标值
  7. short target = 624;
  8. // 计算误差
  9. float error = target - enc;
  10. float kp = 5;
  11. // 控制器:PID算法
  12. int pwm = kp * error;
  13. // 明确输出: pwm
  14. motor_set_pwm(pwm);
  15. delay_1ms(5);
  16. // 将数据显示在图表上
  17. float float_enc = (float)enc;
  18. data_show_push(&float_enc,1);
  19. }
  20. }

PI控制

PI : P=5,i=0.1
image.png
PI : P=5,i=0.01
image.png
示例代码:

  1. void control_PI_2(){
  2. // 误差的累积
  3. float error_integral = 0;
  4. while(1){
  5. // 明确输入: 目标624, 当前值
  6. // 获取编码器当前读数
  7. short enc = encoder_get();
  8. // 目标值
  9. short target = 624;
  10. // 计算误差
  11. float error = target - enc;
  12. // 积分: 误差的累积
  13. error_integral += error;
  14. float kp = 5;
  15. float ki = 0.1;
  16. // 控制器:PID算法
  17. int pwm = kp * error + ki*error_integral;
  18. // 明确输出: pwm
  19. motor_set_pwm(pwm);
  20. delay_1ms(5);
  21. // 将数据显示在图表上
  22. float float_enc = (float)enc;
  23. data_show_push(&float_enc,1);
  24. }
  25. }

PD控制

PD控制:P=10 D=10
image.png
PD控制:P=10 D=20
image.png
PD控制:P=10 D=50
image.png
示例代码:

  1. void control_PD_3(){
  2. // 上一次的误差
  3. float error_last = 0;
  4. while(1){
  5. // 明确输入: 目标624, 当前值
  6. // 获取编码器当前读数
  7. short enc = encoder_get();
  8. // 目标值
  9. short target = 624;
  10. // 计算误差
  11. float error = target - enc;
  12. float kp = 10;
  13. float kd = 50;
  14. // 控制器:PID算法
  15. int pwm = kp * error + kd*(error - error_last);
  16. error_last = error;
  17. // 明确输出: pwm
  18. motor_set_pwm(pwm);
  19. delay_1ms(5);
  20. // 将数据显示在图表上
  21. float float_enc = (float)enc;
  22. data_show_push(&float_enc,1);
  23. }
  24. }

PID控制

P=10,I=0.02,D=30
image.png
示例代码:

  1. #include "config.h"
  2. void control_PID_4(){
  3. // 误差的累积
  4. float error_integral=0;
  5. // 上一次的误差
  6. float error_last = 0;
  7. while(1){
  8. // 明确输入: 目标624, 当前值
  9. // 获取编码器当前读数
  10. short enc = encoder_get();
  11. // 目标值
  12. short target = 624;
  13. // 计算误差
  14. float error = target - enc;
  15. // 误差积分
  16. error_integral+=error;
  17. //g_balanceKP,g_balanceKI,g_balanceKD
  18. float kp = 10;
  19. float ki = 0.02;
  20. float kd = 30;
  21. // 控制器:PID算法
  22. int pwm = kp * error + ki * error_integral+ kd*(error - error_last);
  23. error_last = error;
  24. // 明确输出: pwm
  25. motor_set_pwm(pwm);
  26. delay_1ms(5);
  27. // 将数据显示在图表上
  28. float float_enc = (float)enc;
  29. data_show_push(&float_enc,1);
  30. }
  31. }

2. 位置式PID

位置式PID控制器是一种常见的实现方式,也称为绝对式PID。它直接根据误差值(期望输出与实际输出之差)计算控制量。位置式PID的输出控制量由比例、积分和微分三部分的和组成,如下所示:

  1. u(t) = Kp * e(t) + Ki * e(t)dt + Kd * de(t)/dt

其中,u(t) 是控制量,e(t) 是误差值,Kp、Ki 和 Kd 分别是比例、积分和微分系数。

下面我们来看一下PID的流程图
image.png

示例代码

  1. /**
  2. 位置式PID
  3. float g_kp = 10.0;
  4. float g_ki = 0.01;
  5. float g_kd = 85;
  6. */
  7. float pid_calc(float target, float current){
  8. static float error_integral,error_last;
  9. // 本次误差: 目标值 - 当前值
  10. float error = target - current;
  11. // 误差累计
  12. error_integral += error;
  13. // PID算法实现
  14. float pid_result = g_kp * error + g_ki * error_integral + g_kd * (error - error_last);
  15. // 记录上一次误差
  16. error_last = error;
  17. // 返回pid结果
  18. return pid_result;
  19. }

3. 增量式PID

增量式PID控制器,顾名思义,是根据误差的增量计算控制量的变化。增量式PID的输出控制量由比例、积分和微分三部分的增量和组成,如下所示:

  1. Pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[e(k)-2e(k-1)+e(k-2)]
  2. Pwm+=Kp[e(k)-e(k-1)]+Ki*e(k)+Kd[[ e(k) - e(k-1) ] - [ e(k-1) - e(k-2) ]]

相关参数说明如下:
e(k):本次偏差
e(k-1):上一次的偏差
e(k-2):上上次的偏差
Kp:比例项参数
Ki:积分项参数
Kd:微分项参数
Pwm:代表增量输出

image.png

  1. /**
  2. 增量式PID
  3. 读取编码器增量, 来计算速度
  4. */
  5. float pid_calc2(float target, float current){
  6. static float error_integral,error_last,error_last_last,pid_result;
  7. // 清空编码器
  8. encoder_clear();
  9. // 本次误差: 目标值 - 当前值
  10. float error = target - current;
  11. // PID算法实现
  12. pid_result += g_kp * (error - error_last) + g_ki * error + g_kd * ((error - error_last) - (error_last - error_last_last));
  13. // 记录上一次误差
  14. error_last_last = error_last;
  15. error_last = error;
  16. // 返回pid结果
  17. return pid_result;
  18. }

4. 串级PID

串级PID控制是一种将多个PID控制器连接在一起的控制策略,通常用于提高控制性能或解决复杂系统的控制问题。在串级PID控制系统中,有两个或更多的PID控制器分别负责不同的控制目标或子系统,其中一个控制器的输出作为另一个控制器的输入。这种结构使得控制器能够在不同的层次上对系统进行调节,从而实现更精确和稳定的控制效果。

串级PID的结构

串级PID通常包含一个主控制器(外环)和一个或多个从控制器(内环)。主控制器负责调节系统的主要输出,而从控制器负责调节次要输出或系统内部的状态变量。这种结构可以使得从控制器对系统内部的扰动或不确定性进行快速响应,而主控制器则负责保持系统的整体性能。
image.png

串级PID的优势

串级PID控制具有以下优势:

  1. 更好的控制性能:通过分层控制,串级PID可以在不同的层次上对系统进行调节,实现更精确和稳定的控制效果。
  2. 快速响应:从控制器可以对系统内部的扰动或不确定性进行快速响应,从而提高系统的稳定性。
  3. 灵活性:串级PID可以根据系统的特性和需求灵活地设计和调整控制策略。
  4. 适用于复杂系统:串级PID控制适用于具有多个输入和输出的复杂系统,可以解决传统单环PID控制难以应对的控制问题。

image.png

  1. void control_pid_5(){
  2. static float error_integral,error_last,speed,speed_integral,speed_error_last;
  3. static short encoder_last;
  4. float g_kp = 30;
  5. float g_ki = 0.0;
  6. float g_kd = 2;
  7. float g_skp = 10;
  8. float g_ski = 0.3;
  9. float g_skd = 1;
  10. while(1){
  11. float target = 624;
  12. short current = encoder_get();
  13. // 位置PID : 角度
  14. // 本次位置误差
  15. float error = target - current;
  16. // 误差积分
  17. error_integral += error;
  18. // 位置PID TT马达最大转速为350rpm---> ENCODER_PER_CIRCLE*350/60/1000ms --> 每毫秒最大转14.56个信号量 ---> 循环周期为5ms ---> 每个周期信号量最大14.56*5 --> 72
  19. float angle_result = g_kp*error + g_ki*error_integral + g_kd * (error - error_last);
  20. // 记录上一次的误差
  21. error_last = error;
  22. // 限定输出
  23. if(angle_result > 72) angle_result = 72;
  24. if(angle_result < -72) angle_result = -72;
  25. //angle_result = 10;
  26. // 速度PID : 速度
  27. // 当前速度
  28. speed = current - encoder_last;
  29. encoder_last = current;
  30. // 速度误差
  31. float speed_error = angle_result - speed;
  32. // 速度误差积分
  33. speed_integral += speed_error;
  34. // 速度环PID公式
  35. float speed_result = g_skp * speed_error + g_ski * speed_integral + g_skd * (speed_error - speed_error_last);
  36. speed_error_last = speed_error;
  37. // 限定输出
  38. if(speed_result > 7100) speed_result = 7100;
  39. if(speed_result < -7100) speed_result = -7100;
  40. motor_set_pwm(speed_result);
  41. delay_1ms(5);
  42. // 将数据显示在图表上
  43. float float_enc = (float)current;
  44. data_show_push(&float_enc,1);
  45. }
  46. }

实际应用

串级PID控制被广泛应用于各种领域,如工业过程控制、汽车动力系统控制、航空航天器姿态控制等。在实际应用中,需要根据系统的特性和需求来设计和调整串级PID控制策略。

5.性能指标

自动控制系统的性能指标主要有三个方面: 稳定性,快速性,准确性

稳定性: 系统在受到外作用后,若控制系统使其被控变量随时间的增长而最终 与给定期望值一致,则称系统是稳定的,我们一般称为系统收敛。如果被控量随时 间的增长,越来越偏离给定值,则称系统是不稳定的,我们一般称为系统发散。稳 定的系统才能完成自动控制的任务,所以,系统稳定是保证控制系统正常工作的必 要条件。一个稳定的控制系统其被控量偏离给定值的初始偏差应随时间的增长逐渐 减小并趋于零。
快速性: 快速性是指系统的动态过程进行的时间长短。
过程时间越短,说明系统快速性越好,过程时间持续越长,说明系统响应迟钝, 难以实现快速变化的指令信号。 稳定性和快速性反映了系统在控制过程中的性能。系统在跟踪过程中,被控量 偏离给定值越小,偏离的时间越短,说明系统的动态精度偏高。
准确性: 是指系统在动态过程结束后,其被控变量(或反馈量)对给定值的偏差而言,这一偏差即为稳态误差,它是衡量系统稳态精度的指标,反映了动态过程 后期的性能