之前有一位粉丝朋友读过我写的PID文章后,觉得对自己的帮助挺大的,后面也是向我建议关于PID自整定这块的知识,是否可以不需要提前自整定,而且在不实现超调的情况下,进行PID的实时自整定。对于这个提议我觉得挺有意思的,也是查阅一些相关的文献和技术资料,针对这个提议做一下自己的分享。下面是我和这位粉丝朋友的部分聊天记录。

其实,正如这位粉丝所提到的PID自整定办法,和我们传统的离线自整定有很大的区别,传统的 Z-N(齐格勒 - 尼科尔斯)离线整定是基于固定工况的参数。比如说提到的汽车自动巡航,就不适合传统的自整定,需要使用自适应的PID自整定实现。

汽车自动巡航这类无超调、宽工况鲁棒性的 PID 控制需求,核心是要实现在线自适应自整定,而非传统的离线预整定。传统的 Z-N(齐格勒 - 尼科尔斯)离线整定是基于固定工况的参数,无法应对车速起点变化、上下坡负载扰动,而自适应 PID 自整定的核心是实时识别被控对象模型 + 动态调整 PID 参数。

结合汽车巡航的特性,可通过以下方案实现:

一、 先明确汽车巡航系统的被控对象特性

汽车巡航的核心是发动机输出扭矩→车轮驱动力→克服阻力(风阻、坡度阻力、滚动阻力)→车速稳定,其特性有 3 个关键难点:

  1. 非线性强

    阻力与车速平方成正比,上下坡时坡度阻力突变;

  2. 工况时变

    车速起点不同(低速 / 高速)、负载不同(空载 / 满载),对象模型参数(增益、时间常数)变化大;

  3. 无超调约束

    车速超调会导致顿挫感,影响驾驶体验,因此阻尼特性必须足够强

这决定了自整定不能依赖 “一次性离线参数”,必须是在线、实时、扰动自适应的。

二、 适合汽车巡航的 PID 自整定方案

1.  模型参考自适应自整定(MRAS)—— 核心方案

这是最适合汽车巡航的自整定方法,核心思路是用一个理想的参考模型(如 “阶跃输入无超调、快速响应” 的目标模型)作为标杆,实时对比实际系统输出与参考模型输出的误差,通过自适应律调整 PID 参数

  • 参考模型设计

针对巡航需求,参考模型设为一阶惯性无超调模型,传递函数为

其中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 参数的修正量

  • 模糊规则设计(核心针对无超调)

工况

e

ec

ΔKp

ΔKi

ΔKd

车速远低于目标(大误差)

增大

增大

减小

车速接近目标(小误差)

减小

减小

增大

车速有超调趋势(ec 为负)

减小

减小

增大

  • 优势

    无需数学模型,适合嵌入式平台实时运行,通过规则直接保证无超调。

三、 关键工程优化措施(保证汽车巡航的 “完美控制”)

1.积分分离 + 抗饱和

巡航时,当车速误差较大(如从 40km/h 到 100km/h),暂时关闭积分环节,避免积分饱和;当误差小于阈值(如 ±2km/h),再开启积分消除稳态误差,彻底杜绝超调。

2.分段 PID + 工况识别

提前划分车速区间(低速:0-60km/h、高速:60-120km/h),每个区间预设基础 PID 参数,再结合自整定算法微调。同时通过加速度传感器识别上下坡工况,针对性调整参数。

3.滤波处理

对实际车速信号进行低通滤波(如一阶 RC 滤波),消除传感器噪声对微分环节的干扰,避免微分 “放大噪声” 导致的车速抖动。

四、 嵌入式平台(STM32/ESP32)的实现步骤

1.硬件层

采集车速(轮速传感器)、加速度(IMU)、节气门开度信号;

2.算法层

    • 初始化模糊规则表或 MRAS 参考模型参数;

    • 实时计算速度误差e和误差变化率ec;

    • 执行自整定算法,输出;

    • 更新 PID 参数,输出节气门 / 电机控制信号;

3.优化层

加入积分抗饱和、低通滤波逻辑,调试响应时间和超调量。

汽车巡航的无超调PID自整定,不能用传统离线方法,核心是在线自适应

  • 追求高精度、强鲁棒性 → 选模型参考自适应(MRAS)+ 扰动观测器

  • 追求工程易实现、低算力 → 选模糊 PID 自整定

  • 无论哪种方案,都必须结合积分分离、抗饱和、工况识别等措施,才能实现不同车速、上下坡的完美控制。

以下是针对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,平衡响应速度和噪声抑制。

  2. 无超调优化

    • 增大微分系数(Kd)可增强阻尼,但过大会导致车速抖动,需配合滤波;

    • 积分分离阈值(ERROR_THRESHOLD)建议设为 ±1~3km/h,根据车型调整;

    • 下坡时通过扰动观测增大Kd,防止车速冲顶。

  3. 硬件适配

    • 轮速传感器:需做齿缺补偿,避免丢脉冲导致车速跳变;

    • 节气门执行器:增加 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文档】

更多推荐