PID控制器(比例-积分-微分控制器),由比例单元(Proportional)、积分单元(Integral)和微分单元(Derivative)组成。可以透过调整这三个单元的增益,
和
来调定其特性。PID控制器主要适用于基本上线性,且动态特性不随时间变化的系统。具体的PID介绍可以参考相关资料。
本文只要给出位置式PID控制算法的python代码及其实现,增量式PID控制算法的python代码实现将在下一篇文章中分布。
位置式PID离散公式为
其中,表示每一步的输出值,
表示每一步的误差,根据上述公式,PID算法的代码如下。
class PID:
def __init__(self, P=0, I=0, D=0, initValue=0):
self.Kp = P
self.Ki = I
self.Kd = D
'''
self.curValue表示现在的值
self.ErrorSum表示前面所有误差之和
self.PreError表示前一次的误差
self.CurError表示现在的误差
'''
self.curValue = initValue
self.ErrorSum = 0.0
self.PreError = 0.0
self.CurError = 0.0
def PID_output(self, Target):
self.PreError = self.CurError
self.CurError = Target - self.curValue
dErr = self.CurError - self.PreError
self.ErrorSum += self.CurError
# PID算法公式
output = self.Kp * self.CurError + self.Ki * self.ErrorSum + self.Kd * dErr
self.curValue += output
return self.curValue
设置一个测试函数,用于验证PID控制算法,其中需要引入第三方库用于作图。
import numpy as np
import matplotlib.pyplot as plt
测试函数如下:
def test_PID(P=0, I=0, D=0, initValue=0, len=1, target=0):
pid = PID(P, I, D, initValue)
pid_list = []
time_list = []
pid_list.append(pid.curValue)
time_list.append(0)
for i in range(1, len + 1):
output = pid.PID_output(target)
pid_list.append(output)
time_list.append(i)
time_list = np.array(time_list)
pid_list = np.array(pid_list)
plt.figure()
plt.style.use('seaborn-v0_8')
plt.plot(time_list, pid_list)
plt.axhline(target, c='green')
plt.xlim((0, len))
plt.ylim((min(pid_list) - 1, max(pid_list) + 1))
plt.xlabel('time(s)')
plt.ylabel('value')
plt.title('PID control')
plt.grid(True)
plt.show()
完整代码如下:
import numpy as np
import matplotlib.pyplot as plt
class PID:
def __init__(self, P=0, I=0, D=0, initValue=0):
self.Kp = P
self.Ki = I
self.Kd = D
'''
self.curValue表示现在的值
self.ErrorSum表示前面所有误差之和
self.PreError表示前一次的误差
self.CurError表示现在的误差
'''
self.curValue = initValue
self.ErrorSum = 0.0
self.PreError = 0.0
self.CurError = 0.0
def PID_output(self, Target):
self.PreError = self.CurError
self.CurError = Target - self.curValue
dErr = self.CurError - self.PreError
self.ErrorSum += self.CurError
# PID算法公式
output = self.Kp * self.CurError + self.Ki * self.ErrorSum + self.Kd * dErr
self.curValue += output
return self.curValue
def test_PID(P=0, I=0, D=0, initValue=0, len=1, target=0):
pid = PID(P, I, D, initValue)
pid_list = []
time_list = []
pid_list.append(pid.curValue)
time_list.append(0)
for i in range(1, len + 1):
output = pid.PID_output(target)
pid_list.append(output)
time_list.append(i)
time_list = np.array(time_list)
pid_list = np.array(pid_list)
plt.figure()
plt.style.use('seaborn-v0_8')
plt.plot(time_list, pid_list)
plt.axhline(target, c='green')
plt.xlim((0, len))
plt.ylim((min(pid_list) - 1, max(pid_list) + 1))
plt.xlabel('time(s)')
plt.ylabel('value')
plt.title('PID control')
plt.grid(True)
plt.show()
if __name__ == '__main__':
test_PID(P=0.1, I=0.1, D=0.1, initValue=0, len=200, target=100)