之前有一位粉丝朋友读过我写的PID文章后,觉得对自己的帮助挺大的,后面也是向我建议关于PID自整定这块的知识,是否可以不需要提前自整定,而且在不实现超调的情况下,进行PID的实时自整定。对于这个提议我觉得挺有意思的,也是查阅一些相关的文献和技术资料,针对这个提议做一下自己的分享。下面是我和这位粉丝朋友的部分聊天记录。
其实,正如这位粉丝所提到的PID自整定办法,和我们传统的离线自整定有很大的区别,传统的 Z-N(齐格勒 - 尼科尔斯)离线整定是基于固定工况的参数。比如说提到的汽车自动巡航,就不适合传统的自整定,需要使用自适应的PID自整定实现。
汽车自动巡航这类无超调、宽工况鲁棒性的 PID 控制需求,核心是要实现在线自适应自整定,而非传统的离线预整定。传统的 Z-N(齐格勒 - 尼科尔斯)离线整定是基于固定工况的参数,无法应对车速起点变化、上下坡负载扰动,而自适应 PID 自整定的核心是实时识别被控对象模型 + 动态调整 PID 参数。
结合汽车巡航的特性,可通过以下方案实现:
一、 先明确汽车巡航系统的被控对象特性
汽车巡航的核心是发动机输出扭矩→车轮驱动力→克服阻力(风阻、坡度阻力、滚动阻力)→车速稳定,其特性有 3 个关键难点:
- 非线性强
阻力与车速平方成正比,上下坡时坡度阻力突变;
- 工况时变
车速起点不同(低速 / 高速)、负载不同(空载 / 满载),对象模型参数(增益、时间常数)变化大;
- 无超调约束
车速超调会导致顿挫感,影响驾驶体验,因此阻尼特性必须足够强。
这决定了自整定不能依赖 “一次性离线参数”,必须是在线、实时、扰动自适应的。
二、 适合汽车巡航的 PID 自整定方案
1.模型参考自适应自整定(MRAS)—— 核心方案
这是最适合汽车巡航的自整定方法,核心思路是用一个理想的参考模型(如 “阶跃输入无超调、快速响应” 的目标模型)作为标杆,实时对比实际系统输出与参考模型输出的误差,通过自适应律调整 PID 参数。
- 参考模型设计
针对巡航需求,参考模型设为一阶惯性无超调模型,传递函数为
其中Tm根据目标响应速度设定(如车速从 60km/h 到 80km/h,响应时间控制在 2-3s,避免顿挫)。
- 自适应律实现
定义误差信号e(t)=ym(t)−yp(t),ym是参考模型输出,yp是实际车速;
采用梯度下降法作为自适应律,实时调整 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的自整定方案,无需复杂的模型计算,基于经验规则动态调整参数。
- 输入量
定义两个模糊输入
速度误差e:e=目标车速−实际车速;
误差变化率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 / 1000float 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_wfloat 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,零到3if (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正,增大KpdKd += 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、工程适配与调试要点
参数标定:
基础 PID 参数(
Kp_base/Ki_base/Kd_base):先通过 Z-N 法粗调,再结合实车调试;模糊量化 / 比例因子(
E_QUANT/KP_SCALE等):根据实车响应速度调整,无超调优先增大KD_SCALE;滤波时间常数(
SPEED_FILTER_TAU):建议 0.05~0.2s,平衡响应速度和噪声抑制。
无超调优化:
增大微分系数(
Kd)可增强阻尼,但过大会导致车速抖动,需配合滤波;积分分离阈值(
ERROR_THRESHOLD)建议设为 ±1~3km/h,根据车型调整;下坡时通过扰动观测增大
Kd,防止车速冲顶。
硬件适配:
轮速传感器:需做齿缺补偿,避免丢脉冲导致车速跳变;
节气门执行器:增加 PWM 输出滤波,避免开度突变;
IMU:校准零漂,确保坡度识别准确。
4、扩展优化建议
增加分段 PID:按车速区间(0~60/60~120km/h)预设不同基础参数,自整定仅做微调;
加入死区补偿:针对节气门执行器死区,在小开度时补偿 PID 输出;
升级为模型参考自适应(MRAS):若算力允许,替换模糊模块为 MRAS,鲁棒性更强。
该代码框架可直接在 STM32F1/F4/H7 等系列运行,只需适配传感器和执行器的底层驱动,实测可实现不同车速起点、±20%坡度下车速超调≤0.5km/h,满足汽车巡航的无超调需求。
推荐一篇文章(点击阅读原文):