PID算法簡單剖析如下:
1、首先我們來看一下PID系統的基本組成模塊:

如圖所示,圖中相關參數的表示如下:
r(t):系統實際上需要的輸出值,這是一個標准值,在我們設定了之后讓這個系統去逼近的一個值(隨時間變化的原因是,我們對系統的需求不同才會改變!)
y(t):系統當前的輸出值,這個值應該需要趨近於我們設定的值,當我們沒有增加PID控制模塊之前,它是由被控對象通過r(t)輸入直接產生的。
e(t):系統由於某些擾動,導致的系統產生的偏差,實際輸出的值和想要設定的初始值r(t)的差值。
u(t):系統通過PID控制器輸出的新的輸入值,實際上他是在r(t)的基礎上,針對當前的實際情況做出的改變。
Kp比例模塊:系統PID比例因子,Kp能夠對於產生的偏差e(t)能夠迅速的作出反應,減少偏差。
Ki積分模塊:系統PID積分因子,Ki能夠用於消除靜差,由於前面的誤差有正有負,所以當前偏差的加入能夠抵消部分,保持系統的穩定性,讓系統有記憶功能。
Kd微分模塊:系統微分因子,Kd能夠體現出當前誤差的變化趨勢,引入有效早期修正信號,從而加快系統的動作速度,減少調節時間。
圖中所示的信號關系公式如下所示:
信號誤差公式:![]()
模擬信號的PID控制器公式: ![]()
離散信號的PID控制器公式:![]()
被控對象的信號公式:
(簡單的線性系統,比如電機的PWM調速系統)
上述公式參數描述:
Kp控制器比例系數、Ti控制器積分時間(積分系數)、Td控制器微分時間(微分系數)
k采樣序列號,k=0,1,2,3...、Uk第k次采樣時刻系統輸出值、ek第k次采樣時刻偏差值、ek-1第k-1次采樣時刻偏差值、Ki=Kp*T/Ti、Kd=Kp*Td/T
2、離散信號的PID控制器算法仿真:
1、位置式PID算法:
![]()
PID系統產生的值,完全作為系統的輸入參數,即采用u(k)代替了r(k),如果計算機出現故障時,位置式PID控制將導致Uk的劇烈變化,這會引起執行機構的大幅度變化,造成巨大損失。
仿真代碼如下(python):
import matplotlib.pyplot as plt import numpy as np import random import sys import os time_length = 600 time_sample = 100 time_interval = float(time_length/time_sample) error_coeff = 3 t = np.linspace(0,time_length,time_sample) Slope = 1 Intercept = 0 standard_in = 20 # The system model system_model = lambda i : Slope*i + Intercept standard_out = system_model(standard_in) print("The Standard Output:%d" % standard_out) Kp = 0.08 # average Ki = -0.7 # intergre Kd = 0.01 # diff error_bef = [] real_out_ajust = [] real_out_ajust.append(70) real_out_ajust.append(75) error_bef.append(real_out_ajust[0]-standard_out) Out_plt = np.linspace(standard_out,standard_out,time_sample) # 標准直接計算公式1:Pout=Kp*e(t) + Ki*Sum[e(t)] + Kd*[e(t) - e(t-1)] def PID_Controller_Direct_Mem(standard_out,t): global time_sample,Kp,Ki,Kd,error_bef,real_out_ajust if t > time_sample: print("Time Out! Quit!") return -1 error_now = real_out_ajust[t] - standard_out error_bef.append(error_now) # 記錄了所有的誤差 integrate_res = np.sum(error_bef) Diffirent_res = error_now - error_bef[t-1] return Kp*error_now + Ki*integrate_res + Kd*Diffirent_res for t_slice in range(1,time_sample-1): Pout = PID_Controller_Direct_Mem(standard_out,t_slice) real_out_ajust.append(system_model(Pout)) plt.figure('PID_Controller_Direct_Mem') plt.xlim(0,time_length) plt.ylim(0,2*standard_out) plt.plot(t,real_out_ajust) plt.plot(t,Out_plt)
仿真結果如下所示:
圖中所示,系統最終收斂於我們設定的紅線的位置r(t)
2、增量式PID算法:
![]()
當執行機構需要的控制量是增量而不是位置量的絕對數值是,可以采用增量式PID控制算法。
代碼如下(python):
import matplotlib.pyplot as plt import numpy as np import random import sys import os class PID_Prama: def __init__(self): self.Kp = 0 self.Ki = 0 self.Kd = 0 self.set_val = 0 self.error_last = 0 self.error_prev = 0 self.error_sum = 0 # 增量計算公式: # Pout=Kp*[e(t) - e(t-1)] + Ki*e(t) + Kd*[e(t) - 2*e(t-1) +e(t-2)] def PID_Controller_Increa(pid,out_now): error = pid.set_val - out_now Res = pid.Kp*(error-pid.error_last) + pid.Ki*error + \ pid.Kd*(error-2*pid.error_last+pid.error_prev) pid.error_prev = pid.error_last pid.error_last = error return Res standard_out = 100 PID_val = PID_Prama() # PID參數 PID_val.Kp = 0.01 PID_val.Ki = 0.1 PID_val.Kd = 0.05 PID_val.set_val = standard_out # 標准輸出值 # 增量型PID控制器輸出值 PID_Controller_Increa_Out = [] Sys_In = [] # 0時刻系統輸入值 Sys_In.append(5) # 系統響應函數 SystemFunc = lambda x : 5*x + np.random.normal(0,0.5,1)[0] Sys_Out = [] # 0時刻系統輸出值 Sys_Out.append(SystemFunc(Sys_In[0])) for t_slice in range(Time): Diff = PID_Controller_Increa(PID_val,Sys_Out[t_slice]) #系統誤差 PID_Controller_Increa_Out.append(Diff) # 記錄所有的系統誤差 Sys_In.append(Sys_In[0]+np.sum(PID_Controller_Increa_Out)) # 計算增量之后的新的系統輸入 Sys_Out.append(SystemFunc(Sys_In[t_slice+1])) # 計算下一時刻系統新的輸出值 standard = np.linspace(PID_val.set_val,PID_val.set_val,Time) plt.figure('PID_Controller_Increa') plt.xlim(0,Time) plt.ylim(0,2*standard_out) plt.plot(Sys_Out) plt.plot(standard) plt.show()
這里對增量式PID算法進行深入的分析和計算:
No1:class PID_Param類保存了PID算法中的三個參數,Kp Ki Kd,同時類當中也記錄了上一次系統存在的誤差error_last,以及上上一次系統的誤差error_prev,這樣就能夠完成增量式誤差的公式計算。
No2:上述算法中在循環體中記錄了所有的誤差變量PID_Controller_Increa_Out,這是為了仿真的目的,實際上我們比不需要存儲所有的誤差參數。
No3:系統的響應system_model:
,系統后面添加了高斯噪聲,這表示了系統在運行過程中的不穩定的過程,同時系統本身是一個線性系統,例如控制電機轉速的系統:PWM--ctl--Speed
系統仿真結果:

其他的相關參考資料見我的cnblog文件中,下一篇介紹PID實戰,基於STM32微控制器的C語言控制PWM電機力矩調節系統!
