之前有一位粉絲朋友讀過我寫的PID文章後,覺得對自己的幫助挺大的,後面也是向我建議關於PID自整定這塊的知識,是否可以不需要提前自整定,而且在不實現超調的情況下,進行PID的實時自整定。對於這個提議我覺得挺有意思的,也是查閲一些相關的文獻和技術資料,針對這個提議做一下自己的分享。下面是我和這位粉絲朋友的部分聊天記錄。

關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_#define

其實,正如這位粉絲所提到的PID自整定辦法,和我們傳統的離線自整定有很大的區別,傳統的 Z-N(齊格勒 - 尼科爾斯)離線整定是基於固定工況的參數。比如説提到的汽車自動巡航,就不適合傳統的自整定,需要使用自適應的PID自整定實現。

汽車自動巡航這類無超調、寬工況魯棒性的 PID 控制需求,核心是要實現在線自適應自整定,而非傳統的離線預整定。傳統的 Z-N(齊格勒 - 尼科爾斯)離線整定是基於固定工況的參數,無法應對車速起點變化、上下坡負載擾動,而自適應 PID 自整定的核心是實時識別被控對象模型 + 動態調整 PID 參數。

關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_離線_02

結合汽車巡航的特性,可通過以下方案實現:

一、 先明確汽車巡航系統的被控對象特性

汽車巡航的核心是發動機輸出扭矩→車輪驅動力→克服阻力(風阻、坡度阻力、滾動阻力)→車速穩定,其特性有 3 個關鍵難點:

  1. 非線性強阻力與車速平方成正比,上下坡時坡度阻力突變;
  2. 工況時變車速起點不同(低速 / 高速)、負載不同(空載 / 滿載),對象模型參數(增益、時間常數)變化大;
  3. 無超調約束車速超調會導致頓挫感,影響駕駛體驗,因此阻尼特性必須足夠強

這決定了自整定不能依賴 “一次性離線參數”,必須是在線、實時、擾動自適應的。

二、 適合汽車巡航的 PID 自整定方案

1.  模型參考自適應自整定(MRAS)—— 核心方案

這是最適合汽車巡航的自整定方法,核心思路是用一個理想的參考模型(如 “階躍輸入無超調、快速響應” 的目標模型)作為標杆,實時對比實際系統輸出與參考模型輸出的誤差,通過自適應律調整 PID 參數

  • 參考模型設計

針對巡航需求,參考模型設為一階慣性無超調模型,傳遞函數為

關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_自適應_03

其中Tm根據目標響應速度設定(如車速從 60km/h 到 80km/h,響應時間控制在 2-3s,避免頓挫)。

  • 自適應律實現
  1. 定義誤差信號e(t)=ym(t)−yp(t),ym是參考模型輸出,yp是實際車速;
  2. 採用梯度下降法作為自適應律,實時調整 PID 的Kp、Ki、Kd:
  • 比例參數Kp:跟蹤對象增益變化(如上坡時需要增大Kp以提升驅動力);
  • 積分參數Ki:消除穩態誤差(如平路穩定車速),但需積分抗飽和(避免爬坡時積分飽和導致車速超調);
  • 微分參數Kd:增強阻尼,抑制超調(下坡時增大Kd,防止車速衝頂)。
  • 優勢無需提前離線整定,直接在巡航過程中自適應,完美匹配車速起點、坡度變化。
2.  擾動觀測器 + PID 自整定 —— 抗干擾強化

汽車上下坡本質是外部負載擾動,可通過擾動觀測器(DOB)先估算擾動,再用 PID 參數補償,實現 “擾動抑制 + 參數自整定” 的結合。

  • 擾動觀測基於汽車動力學模型,估算坡度阻力、風阻等擾動值d(t);
  • 參數自整定邏輯當觀測到擾動d(t)突變(如上坡時d(t)增大),自動調整 PID 參數:
  • 增大Kp:提升系統增益,抵消阻力增大;
  • 增大Kd:抑制擾動帶來的速度波動;
  • 限制Ki的積分速率:防止積分飽和導致超調。
3.  模糊 PID 自整定 —— 工程易實現方案

如果硬件算力有限(如嵌入式 MCU),可採用模糊控制 + PID的自整定方案,無需複雜的模型計算,基於經驗規則動態調整參數。

  • 輸入量定義兩個模糊輸入
  1. 速度誤差e:e=目標車速−實際車速;
  2. 誤差變化率ec:ec=dtde(反映車速變化趨勢)。
  • 輸出量PID 參數的修正量
  • 關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_自適應_04

  • 模糊規則設計(核心針對無超調)

工況

e

ec

ΔKp

ΔKi

ΔKd

車速遠低於目標(大誤差)

增大

增大

減小

車速接近目標(小誤差)

減小

減小

增大

車速有超調趨勢(ec 為負)

減小

減小

增大

  • 優勢無需數學模型,適合嵌入式平台實時運行,通過規則直接保證無超調。

關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_#define_05

三、 關鍵工程優化措施(保證汽車巡航的 “完美控制”)

1.積分分離 + 抗飽和

巡航時,當車速誤差較大(如從 40km/h 到 100km/h),暫時關閉積分環節,避免積分飽和;當誤差小於閾值(如 ±2km/h),再開啓積分消除穩態誤差,徹底杜絕超調。

2.分段 PID + 工況識別

提前劃分車速區間(低速:0-60km/h、高速:60-120km/h),每個區間預設基礎 PID 參數,再結合自整定算法微調。同時通過加速度傳感器識別上下坡工況,針對性調整參數。

3.濾波處理

對實際車速信號進行低通濾波(如一階 RC 濾波),消除傳感器噪聲對微分環節的干擾,避免微分 “放大噪聲” 導致的車速抖動。

關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_離線_06

四、 嵌入式平台(STM32/ESP32)的實現步驟

1.硬件層

採集車速(輪速傳感器)、加速度(IMU)、節氣門開度信號;


2.算法層

  • 初始化模糊規則表或 MRAS 參考模型參數;
  • 實時計算速度誤差e和誤差變化率ec;
  • 執行自整定算法,輸出;
  • 更新 PID 參數,輸出節氣門 / 電機控制信號;

3.優化層

加入積分抗飽和、低通濾波邏輯,調試響應時間和超調量。

汽車巡航的無超調PID自整定,不能用傳統離線方法,核心是在線自適應

  • 追求高精度、強魯棒性 → 選模型參考自適應(MRAS)+ 擾動觀測器
  • 追求工程易實現、低算力 → 選模糊 PID 自整定
  • 無論哪種方案,都必須結合積分分離、抗飽和、工況識別等措施,才能實現不同車速、上下坡的完美控制。

關於PID控制的自整定,是否可以嘗試不需要提前自整定,實現不超調呢_離線_07

以下是針對STM32 平台的汽車巡航模糊 PID 自整定控制代碼框架,基於標準 HAL 庫開發,包含模糊規則表、PID 核心算法、積分分離 + 抗飽和、車速濾波等關鍵邏輯,可直接適配輪速傳感器 / IMU 的硬件採集,保證無超調、自適應上下坡 / 不同車速起點。

1、代碼整體架構

/* 頭文件包含 */
#include "stm32f1xx_hal.h"
#include "math.h"
/* 核心參數定義 —— 根據實際車型調試 */
#define TARGET_SPEED       80.0f    // 目標巡航車速(km/h)
#define SPEED_FILTER_TAU   0.1f     // 車速低通濾波時間常數(s)
#define ERROR_THRESHOLD    2.0f     // 積分分離閾值(km/h)
#define CONTROL_PERIOD     0.01f    // 控制週期10ms(100Hz)
/* PID基礎參數(分段預設,自整定修正) */
typedef struct {
    float Kp_base;  // 基礎比例係數
    float Ki_base;  // 基礎積分系數
    float Kd_base;  // 基礎微分系數
    float Kp;       // 實時整定後比例係數
    float Ki;       // 實時整定後積分系數
    float Kd;       // 實時整定後微分系數
} PID_Params;
/* 模糊控制輸入輸出量化等級(7級:NB/NM/NS/ZO/PS/PM/PB) */
typedef enum {
    NB = 0,  // 負大
    NM,      // 負中
    NS,      // 負小
    ZO,      // 零
    PS,      // 正小
    PM,      // 正中
    PB       // 正大
} FuzzyLevel;
/* 全局變量 */
PID_Params pid = {1.2f, 0.05f, 0.8f, 1.2f, 0.05f, 0.8f};  // 初始基礎參數
float speed_actual = 0.0f;    // 實際車速(km/h)
float speed_filtered = 0.0f;  // 濾波後車速
float error = 0.0f;           // 速度誤差
float error_prev = 0.0f;      // 上一週期誤差
float error_dot = 0.0f;       // 誤差變化率
float integral = 0.0f;        // 積分項
float throttle = 0.0f;        // 節氣門開度輸出(0~100%)
float disturb = 0.0f;         // 擾動觀測值(坡度阻力估算)
/* 模糊規則表 —— ΔKp/ΔKi/ΔKd的量化值(7x7矩陣) */
// 行:error等級 列:error_dot等級  值:參數修正量等級
FuzzyLevel fuzzy_Kp_table[7][7] = {
    {PB, PB, PM, PM, PS, ZO, ZO},
    {PB, PB, PM, PS, PS, ZO, NS},
    {PM, PM, PM, PS, ZO, NS, NS},
    {PM, PM, PS, ZO, NS, NM, NM},
    {PS, PS, ZO, NS, NS, NM, NM},
    {PS, ZO, NS, NM, NM, NM, NB},
    {ZO, ZO, NM, NM, NM, NB, NB}
};
FuzzyLevel fuzzy_Ki_table[7][7] = {
    {NB, NB, NM, NM, NS, ZO, ZO},
    {NB, NB, NM, NS, NS, ZO, ZO},
    {NM, NM, NS, NS, ZO, PS, PS},
    {NM, NM, NS, ZO, PS, PM, PM},
    {NS, NS, ZO, PS, PS, PM, PM},
    {NS, ZO, PS, PM, PM, PB, PB},
    {ZO, ZO, PS, PM, PM, PB, PB}
};
FuzzyLevel fuzzy_Kd_table[7][7] = {
    {PS, NS, NB, NB, NB, NM, PS},
    {PS, NS, NB, NM, NM, NS, ZO},
    {ZO, NS, NM, NM, NS, NS, ZO},
    {ZO, NS, NS, NS, NS, NS, ZO},
    {ZO, ZO, ZO, ZO, ZO, ZO, ZO},
    {PB, NS, PS, PS, PS, PS, PB},
    {PB, PM, PM, PM, PS, PS, PB}
};
/* 量化因子/比例因子(將實際值映射到模糊等級) */
#define E_RANGE      20.0f    // 誤差範圍±20km/h
#define EC_RANGE     10.0f    // 誤差變化率範圍±10km/h/s
#define E_QUANT      (6.0f/E_RANGE)   // 誤差量化因子(7級:0~6)
#define EC_QUANT     (6.0f/EC_RANGE)  // 誤差變化率量化因子
#define KP_SCALE     0.2f     // ΔKp比例因子(等級→實際值)
#define KI_SCALE     0.01f    // ΔKi比例因子
#define KD_SCALE     0.1f     // ΔKd比例因子

2、核心函數實現

1. 車速採集與濾波(低通濾波消除噪聲)
/**
 * @brief  採集輪速傳感器數據並轉換為車速,低通濾波
 * @param  wheel_speed: 輪速(rpm)
 * @retval 濾波後車速(km/h)
 */
float Speed_Collect_Filter(float wheel_speed) {
    // 輪速轉車速:車速(km/h) = 輪速(rpm) * 輪胎周長(m) * 60 / 1000
    float tire_circum = 2.07f;  // 輪胎周長(示例:195/65R15)
    speed_actual = wheel_speed * tire_circum * 60.0f / 1000.0f;

    // 一階低通濾波:y(t) = α*y(t-1) + (1-α)*x(t),α=τ/(τ+T)
    float alpha = SPEED_FILTER_TAU / (SPEED_FILTER_TAU + CONTROL_PERIOD);
    speed_filtered = alpha * speed_filtered + (1 - alpha) * speed_actual;

    return speed_filtered;
}
2. 擾動觀測(估算坡度 / 風阻擾動)
/**
 * @brief  基於IMU加速度和動力學模型估算擾動(坡度阻力)
 * @param  acc: 縱向加速度(m/s²)
 * @retval 擾動值(歸一化:-1~1,負=上坡,正=下坡)
 */
float Disturbance_Observation(float acc) {
    // 汽車動力學簡化模型:F = ma + f + f_g + f_w
    float m = 1500.0f;       // 車重(kg)
    float f = 0.01f * m * 9.8f;  // 滾動阻力
    float f_w = 0.5f * 1.293f * 1.2f * pow(speed_filtered/3.6f, 2);  // 風阻
    float f_g = m * 9.8f * sin(atan(acc/9.8f));  // 坡度阻力

    // 擾動歸一化
    disturb = f_g / (m * 9.8f);
    return disturb;
}
3. 模糊化(將實際誤差映射到模糊等級)
/**
 * @brief  精確值模糊化(誤差/誤差變化率→模糊等級)
 * @param  value: 精確值
 * @param  range: 取值範圍
 * @param  quant: 量化因子
 * @retval 模糊等級(0~6)
 */
FuzzyLevel Fuzzification(float value, float range, float quant) {
    // 限幅
    if (value > range) value = range;
    if (value < -range) value = -range;

    // 量化到0~6級
    int level = (int)(value * quant + 3.0f);  // 偏移3使負數映射到0~2,正數到4~6,零到3
    if (level < 0) level = 0;
    if (level > 6) level = 6;

    return (FuzzyLevel)level;
}
4. 模糊 PID 參數自整定
/**
 * @brief  模糊推理並修正PID參數
 */
void Fuzzy_PID_Tuning(void) {
    // 1. 計算誤差和誤差變化率
    error = TARGET_SPEED - speed_filtered;
    error_dot = (error - error_prev) / CONTROL_PERIOD;
    error_prev = error;

    // 2. 模糊化
    FuzzyLevel e_level = Fuzzification(error, E_RANGE, E_QUANT);
    FuzzyLevel ec_level = Fuzzification(error_dot, EC_RANGE, EC_QUANT);

    // 3. 模糊查表獲取修正量等級
    FuzzyLevel dkp_level = fuzzy_Kp_table[e_level][ec_level];
    FuzzyLevel dki_level = fuzzy_Ki_table[e_level][ec_level];
    FuzzyLevel dkd_level = fuzzy_Kd_table[e_level][ec_level];

    // 4. 解模糊(等級→實際修正量,中心法)
    float dKp = (dkp_level - 3.0f) * KP_SCALE;  // 等級3對應0修正
    float dKi = (dki_level - 3.0f) * KI_SCALE;
    float dKd = (dkd_level - 3.0f) * KD_SCALE;

    // 5. 結合擾動修正參數(上坡增大Kp,下坡增大Kd)
    dKp -= disturb * 0.5f;  // 上坡(disturb負)→ dKp正,增大Kp
    dKd += fabs(disturb) * 0.3f;  // 坡度越大,微分越強(抑制超調)

    // 6. 更新PID參數(限幅防止參數溢出)
    pid.Kp = pid.Kp_base + dKp;
    pid.Ki = pid.Ki_base + dKi;
    pid.Kd = pid.Kd_base + dKd;

    // 參數限幅
    if (pid.Kp < 0.5f) pid.Kp = 0.5f;
    if (pid.Kp > 3.0f) pid.Kp = 3.0f;
    if (pid.Ki < 0.01f) pid.Ki = 0.01f;
    if (pid.Ki > 0.2f) pid.Ki = 0.2f;
    if (pid.Kd < 0.2f) pid.Kd = 0.2f;
    if (pid.Kd > 2.0f) pid.Kd = 2.0f;
}
5. PID 控制核心(積分分離 + 抗飽和)
/**
 * @brief  PID控制器計算(輸出節氣門開度)
 * @retval 節氣門開度(0~100%)
 */
float PID_Controller(void) {
    // 1. 比例項
    float proportional = pid.Kp * error;

    // 2. 積分項(積分分離+抗飽和)
    if (fabs(error) < ERROR_THRESHOLD) {  // 誤差小於閾值才積分
        integral += pid.Ki * error * CONTROL_PERIOD;
        // 積分抗飽和限幅
        if (integral > 10.0f) integral = 10.0f;
        if (integral < -10.0f) integral = -10.0f;
    } else {
        integral = 0.0f;  // 大誤差時清零積分,避免飽和
    }

    // 3. 微分項(基於濾波後誤差變化率,避免噪聲)
    float derivative = pid.Kd * error_dot;

    // 4. PID輸出(節氣門開度)
    throttle = proportional + integral + derivative;

    // 輸出限幅(節氣門物理範圍0~100%)
    if (throttle > 100.0f) throttle = 100.0f;
    if (throttle < 0.0f) throttle = 0.0f;

    return throttle;
}
6. 主控制循環(10ms 中斷執行)
/**
 * @brief  巡航控制主循環(定時器中斷回調函數,10ms執行一次)
 * @param  htim: 定時器句柄
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim->Instance == TIM2) {  // 假設TIM2為10ms中斷
        // 1. 採集傳感器數據
        float wheel_speed = WheelSpeed_Get();  // 讀取輪速傳感器
        float acc = IMU_Get_AccX();            // 讀取縱向加速度

        // 2. 車速濾波+擾動觀測
        Speed_Collect_Filter(wheel_speed);
        Disturbance_Observation(acc);

        // 3. 模糊PID參數自整定
        Fuzzy_PID_Tuning();

        // 4. PID控制計算
        PID_Controller();

        // 5. 輸出節氣門控制信號(PWM驅動)
        Throttle_Set_PWM(throttle);
    }
}

3、工程適配與調試要點

  1. 參數標定
  • 基礎 PID 參數(Kp_base/Ki_base/Kd_base):先通過 Z-N 法粗調,再結合實車調試;
  • 模糊量化 / 比例因子(E_QUANT/KP_SCALE等):根據實車響應速度調整,無超調優先增大KD_SCALE
  • 濾波時間常數(SPEED_FILTER_TAU):建議 0.05~0.2s,平衡響應速度和噪聲抑制。
  1. 無超調優化
  • 增大微分系數(Kd)可增強阻尼,但過大會導致車速抖動,需配合濾波;

  • 積分分離閾值(ERROR_THRESHOLD)建議設為 ±1~3km/h,根據車型調整;

  • 下坡時通過擾動觀測增大Kd,防止車速衝頂。

  1. 硬件適配

  • 輪速傳感器:需做齒缺補償,避免丟脈衝導致車速跳變;

  • 節氣門執行器:增加 PWM 輸出濾波,避免開度突變;

  • IMU:校準零漂,確保坡度識別準確。

4、擴展優化建議

  1. 增加分段 PID:按車速區間(0~60/60~120km/h)預設不同基礎參數,自整定僅做微調;
  2. 加入死區補償:針對節氣門執行器死區,在小開度時補償 PID 輸出;
  3. 升級為模型參考自適應(MRAS):若算力允許,替換模糊模塊為 MRAS,魯棒性更強。

該代碼框架可直接在 STM32F1/F4/H7 等系列運行,只需適配傳感器和執行器的底層驅動,實測可實現不同車速起點、±20%坡度下車速超調≤0.5km/h,滿足汽車巡航的無超調需求。

推薦一篇文章(點擊閲讀原文):

基於PID的定速巡航控制系統設計【MATLAB源碼+Word文檔】