一、什么是PID 控制算法

PID 控制算法是比例(Proportional)- 積分(Integral)- 微分(Derivative) 控制的簡稱,是工業控制、嵌入式系統中最經典、應用最廣泛的閉環控制算法。它的核心思想是通過偏差(設定值與實際值的差值)的比例、積分、微分三個環節的加權組合,計算出控制量,使系統的實際輸出快速、穩定地逼近設定值。
二、核心公式(連續域)


比例環節(P)
核心作用:即時響應偏差,偏差越大,控制量越大。
缺點:僅用 P 控制會存在穩態誤差(系統穩定后,實際值與設定值仍有差距);Kp過大會導致系統震蕩。
積分環節(I)
核心作用:累積歷史偏差,只要存在偏差,積分項就會持續增大,直到偏差為 0,從而消除穩態誤差。
缺點:積分累積會導致系統超調(實際值超過設定值),甚至震蕩;系統啟動初期積分飽和會影響響應速度。
微分環節(D)
核心作用:預測偏差變化趨勢,偏差變化越快,微分項輸出越大,提前抑制偏差的變化(類似 “阻尼” 作用)。
缺點:對噪聲敏感(傳感器的微小波動會被放大);Kd過大會導致系統響應遲緩。
離散化公式(嵌入式系統常用)
嵌入式 MCU 是離散采樣系統,無法直接計算連續的積分和微分,需要將上述的連續域PID 公式離散化,用數值積分和數值微分替代連續運算,得到離散 PID 公式。
設系統采樣周期為 Ts,第 k 次采樣時刻的偏差為 e(k)=r(k)-y(k)(設定值-實際采樣值),則離散 PID 有兩種常用形式:
位置式PID

特點:輸出 u(k) 是絕對控制量,也就是閥門開度(如電機的目標占空比、舵機的目標角度)。
C語言代碼(通用):
typedef struct {
float kp; // 比例系數
float ki; // 積分系數
float kd; // 微分系數
float set_point; // 設定值
float feedback; // 反饋值
float error; // 當前誤差 (set_point - feedback)
float error_sum; // 誤差積分和(防止積分飽和)
float error_prev; // 上一次誤差(微分用)
float output_max; // 輸出最大值
float output_min; // 輸出最小值
} PID_Positional;
/**
- @brief 位置式 PID 核心計算(無初始化函數,參數需外部賦值)
- @param pid: 位置式 PID 結構體指針
- @param set_point: 設定值
- @param feedback: 反饋值
- @return 位置式 PID 輸出值
*/
float PID_Positional_Calc(PID_Positional *pid, float set_point, float feedback) {
if (pid == NULL) return 0.0f;
// 更新設定值和反饋值
pid->set_point = set_point;
pid->feedback = feedback;
// 計算當前誤差
pid->error = pid->set_point - pid->feedback;
// 積分項(帶積分限幅,防止積分飽和)
pid->error_sum += pid->error;
// 積分限幅:根據輸出限幅和 ki 動態約束(也可直接賦值固定值)
float integral_max = (pid->output_max / pid->ki) * 0.8f;
float integral_min = (pid->output_min / pid->ki) * 0.8f;
if (pid->error_sum > integral_max) pid->error_sum = integral_max;
if (pid->error_sum < integral_min) pid-?>error_sum = integral_min;
// 位置式 PID 核心公式
float output = pid->kp * pid->error + // 比例項
pid->ki * pid->error_sum + // 積分項
pid->kd * (pid->error - pid->error_prev); // 微分項
// 輸出限幅
if (output > pid->output_max) output = pid->output_max;
if (output < pid-?>output_min) output = pid->output_min;
// 更新上一次誤差
pid->error_prev = pid->error;
return output;
}
2.增量式 PID
計算相鄰兩次控制量的差值 Δ u(k),公式推導:

特點:輸出Δ u(k)是控制量增量,只需疊加到上一次的控制量上(在上一次的控制輸出上進行加減):u(k)=u(k-1)+Δ u(k)。
C語言代碼(通用):
typedef struct {
float kp; // 比例系數
float ki; // 積分系數
float kd; // 微分系數
float set_point; // 設定值
float feedback; // 反饋值
float error; // 當前誤差 (set_point - feedback)
float error_prev1; // 前1次誤差
float error_prev2; // 前2次誤差
float output_inc; // 增量輸出
float output_max; // 輸出最大值(用于增量限幅)
float output_min; // 輸出最小值(用于增量限幅)
} PID_Incremental;
/**
@brief 增量式 PID 核心計算(無初始化函數,參數需外部賦值)
@param pid: 增量式 PID 結構體指針
@param set_point: 設定值
@param feedback: 反饋值
@return 增量式 PID 輸出增量
*/
float PID_Incremental_Calc(PID_Incremental *pid, float set_point, float feedback) {
if (pid == NULL) return 0.0f;
// 更新設定值和反饋值
pid->set_point = set_point;
pid->feedback = feedback;
// 計算當前誤差
pid->error = pid->set_point - pid->feedback;
// 增量式 PID 核心公式
pid->output_inc = pid->kp * (pid->error - pid->error_prev1) + // 比例增量
pid->ki * pid->error + // 積分增量
pid->kd * (pid->error - 2*pid->error_prev1 + pid->error_prev2); // 微分增量
// 增量限幅(避免單次增量過大)
float inc_max = (pid->output_max - pid->output_min) / 2;
if (pid->output_inc > inc_max) pid->output_inc = inc_max;
if (pid->output_inc < -inc_max) pid-?>output_inc = -inc_max;
// 更新誤差歷史(前2次 → 前1次,前1次 → 當前)
pid->error_prev2 = pid->error_prev1;
pid->error_prev1 = pid->error;
return pid->output_inc;
}
三、嵌入式系統如何使用PID控制算法?
建立閉環反饋
明確被控對象
被控對象:比如溫度、機器人關節、直流電機轉速等;
選擇合適的采樣周期對被控變量進行采樣
采集能反應被控對象當前狀態的信號
采樣周期的選擇依據:
香農采樣定理:采樣頻率至少是被控對象最高變化頻率的 2 倍,避免信號混疊;
被控對象響應速度:比如直流電機響應速度為 ms 級,采樣周期設置為1~10ms;溫度這類慢響應對象,采樣周期設置為1~5s;
由此我們得到了被控對象溫度的實際溫度
PID運算出輸出量
將目標值和采樣值送入PID公式進行計算
需要注意:
抗積分飽和:當 PID 輸出達到執行器最大 / 最小量程時,停止積分累加;
積分分離:當誤差|ek|大于設定閾值時,暫停積分項運算,避免積分飽和導致的超調;
輸出到執行器
將PID公式運算出來的結果作用到輸出執行器
需要注意:
數值限幅:運算后必須將輸出量限制在執行器的有效范圍(比如 PWM 占空比 0~100%、DAC 輸出 0~4095),避免輸出超限損壞執行器;
PID參數的調參(Kp,Ki,Kd)
建立好閉環反饋環節后就可以對PID參數進行整定了,我們實際最多使用的是經驗試湊法,這里只分享試湊法:
試湊法的核心邏輯:先調 P,再調 I,最后調 D,每次只改一個參數,觀察系統響應,逐步逼近最優值。
只調比例環節(P),關閉 I 和 D
Ki=0,Kd=0,K_p 從 0 開始緩慢增大;直到響應較快,實際值快速接近設定值,輕微震蕩后穩定,穩態誤差較小

(此時可能會有靜態誤差,即輸出一直達不到目標值這種情況)
Kp過大-->系統可能會震蕩
Kp過小-->系統響應較慢, 可能達不到目標值
加入積分環節(I),消除穩態誤差
為了消除靜態誤差,加入積分環節,在Kp已有的基礎上,Kd=0,加入Ki,Ki 從 0 開始緩慢增大,直到系統能消除靜態誤差,并且不發生震蕩


(要注意抗積分飽和,不然系統極易發生震蕩)
Ki過大-->系統可能會震蕩
Ki過小-->系統依舊有靜差
加入微分環節(D),加快響應
若已達到預期的控制效果可不引入微分環節。
若未達到預期的控制效果,可以在前面的基礎上使Kid從 0 開始緩慢增大,直到超調大幅減小,響應速度基本不變,系統快速穩定。
-
溫度控制
+關注
關注
7文章
310瀏覽量
39084 -
PID
+關注
關注
38文章
1499瀏覽量
91162 -
控制算法
+關注
關注
4文章
171瀏覽量
22739
發布評論請先 登錄
FOC控制中如何利用芯片內部的運放設計電流采樣電路?
堅持繼續布局32位MCU,進一步完善產品陣容,96Mhz主頻CW32L012新品發布!
**CW32L012****開發評估板的第一個程序**
CW32L012小型機器人控制評估板活動 四足機器人+智能小車 開箱評測
堅持繼續布局32位MCU,進一步完善產品陣容,96Mhz主頻CW32L012新品發布!
使用芯源CW32的CW32L012開發評估板做了spi屏幕驅動
CW32L012小機器人的電機控制
CW32L012與STM32F103的三角運算性能對比
CW32L012與STM32G431的CORDIC三角函數運算性能對比
CW32L012的PID溫度控制——算法基礎
評論