资讯动态

STM32F103模糊自整定增量式PID电机调速实战解析

发布时间:2026/10/21 23:26:25 来源:尧图企业网站定制
简介面向STM32电机控制学习者的模糊自整定增量式PID速度控制工程基于STM32F103ZET6与编码器直流电机搭建采用正点原子代码风格分模块组织并附有详细注释适合作为课设、毕设或入门进阶的参考。相比普通增量式PID该方案利用模糊控制在线整定比例、积分、微分参数以改善电机调速的动态响应和抗干扰能力为理解增量式PID与模糊控制的结合提供了较完整的代码实现。压缩包共170个文件、约4.74MB包含39个h头文件、38个c源码文件以及uvprojx工程、hex/axf烧录文件、map映射文件、bat清理脚本等编译与调试产物工程结构清晰可在Keil中直接编译运行。已有4282人浏览学习代码经作者实测稳定可靠对掌握定时器编码器测速、增量式PID计算流程和模糊整定方法具有直接的参考价值。1. STM32F103 模糊自整定增量式 PID先把转速调稳再谈省事做坏过三块板子后我的结论是固定参数 PID 能跑但它只能服务一套工况负载一变就要重新手摸参数。STM32F103 上做模糊自整定增量式 PID 控制电机速度思路是让控制器根据当前转速误差和误差变化率实时修正 Kp、Ki、Kd不是替你省掉 PID而是把调参这件事从反复试凑变成查表加推理。它解决的是起步大误差时快速逼近、稳态小误差时消除静差、突加负载时不明显超调这三个典型问题。适合刚接触速度环的小车和桌面机器人的开发者也适合想了解模糊控制如何落到单片机上的人。下面按我自己拆这套工程的过程从原理到代码到翻车点全过一遍。2. 增量式 PID 与编码器测速控制节奏和反馈精度谁先谁后先明确一件事模糊自整定只是把三个系数改活底层速度环仍然是增量式 PID反馈仍然来自编码器。这章先把这层地基立住后面查表才有意义。2.1 为什么电机速度环用增量式而不是位置式位置式 PID 输出的是占空比绝对量u(k) Kp * e(k) Ki * Σe(i) Kd * (e(k) - e(k-1))它把历史误差全部累加在积分项里启动时偏差大会让积分项堆得很高一旦误差反向积分项要从很高的绝对值往回退现象就是大超调。增量式 PID 输出的是占空比的变化量Δu(k) Kp * (e(k) - e(k-1)) Ki * e(k) Kd * (e(k) - 2*e(k-1) e(k-2)) u(k) u(k-1) Δu(k)注意输出量的历史通过 u(k-1) 累积在控制器内部增量式公式里没有显式积分累加项所以不会出现位置式那种积分深度饱和的情况。电机速度环被控对象自带惯性每周期只做小幅调整比每次重置绝对占空比更平顺。增量式不是没有代价。如果输出限幅不合理或者编码器方向反了u(k) 会朝一个方向一直累加表现出来就是电机越跑越快直到满转。代码里必须有输出限幅这不是可选项。常见做法是在速度环里做对称限幅#define PWM_PERIOD 7199 // ARR 值对应 10kHz #define PWM_MAX_DUTY 7199 // 上限对应 100% #define PWM_MIN_DUTY 0 // 下限对应 0% float u_out 0.0f; // 增量式输出累加 u_out du; // 输出限幅 if (u_out PWM_MAX_DUTY) { u_out PWM_MAX_DUTY; } else if (u_out PWM_MIN_DUTY) { u_out PWM_MIN_DUTY; } TIM1-CCR1 (uint16_t)u_out;逻辑说明du 是增量式 PID 算出的占空比变化量u_out 是积分后的绝对占空比限幅在赋值给 CCR1 前完成。这里最容易被忽略的是 PWM_MIN_DUTY 设成了 0导致电机启动需要克服静摩擦力时总从零爬升低速响应会慢半拍。我一般会在启动阶段叠加一个最小占空比偏置跑起来后再交给 PID 接管。参数说明PWM_PERIOD 由定时器重装载值决定7200 个计数单位对应 10kHz PWM。PWM_MAX_DUTY 和 ARR 相等时占空比 100%实际使用建议留 5% 裕量防止占空比饱和后增量式输出继续累加退出饱和时延迟增大。2.2 编码器测速的 M 法与 T 法低速直接决定模糊表能不能用STM32F103 的定时器编码器模式把方向判别和计数都做进硬件里读 CNT 寄存器就能拿到位置增量这个模块本身不复杂复杂的是测速方法选错后速度反馈全是毛刺模糊自整定会把毛刺当成真实误差变化率去调 Kd结果越调越抖。M 法固定时间窗口内数脉冲个数。适用于每个控制周期内脉冲数较多的场合一般要求不低于 20 个否则分辨率不够。T 法测量相邻脉冲的时间间隔低速下脉冲少反而有效。适用于低速场合但每个周期都要捕捉捕获事件逻辑复杂一些。M 法换算公式如下speed_rpm (pulse_count / pulses_per_rev) * (60 / control_period_s)假设电机是 11 线霍尔编码器减速比 1:30则每转总脉冲数 11 * 30 330。目标是 60rpm 时每秒转一圈也就是每秒 330 个脉冲如果控制周期 10ms每周期只有 3.3 个脉冲。10ms 窗口 M 法测出来不是 60rpm而是 3 个或 4 个脉冲对应的 54rpm 或 72rpm这就是低速抖动和模糊表乱跳的根源。所以工程上常见做法是先算一下自己系统的每周期脉冲数再决定测速方式// 每转脉冲数编码器线数 * 减速比 #define ENCODER_LINES 11 #define GEAR_RATIO 30 #define PULSES_PER_REV (ENCODER_LINES * GEAR_RATIO) // 330 // 目标最低转速下的每周期脉冲数预算 #define MIN_SPEED_RPM 60 #define CONTROL_PERIOD_MS 10 #define MIN_PULSES_PER_LOOP \ (MIN_SPEED_RPM * PULSES_PER_REV / 60 / (1000 / CONTROL_PERIOD_MS))逻辑说明先按项目里最低工作转速算出一个周期能拿到多少脉冲如果算出来小于 10 个就要么提高编码器线数要么换 T 法要么把控制周期拉长。脉冲数太少时速度反馈量化噪声会传导到 ec 计算模糊控制规则对噪声又敏感后面 Kd 修正项会周期性跳变。参数说明PULSES_PER_REV 必须和实际减速比一一对应。编码器是轴端编码器还是输出轴编码器会差很多不少拿到手的电机标称减速比和实测值有偏差校准方法在最后一章给。2.3 定时器编码器模式初始化不是所有定时器都能数正交脉冲STM32F103 的 TIM1 到 TIM4 才带编码器接口不是所有定时器都能当编码器用。常用分配是把 TIM3 或者 TIM4 让给编码器TIM1 或者 TIM2 做 PWM 输出。我这里用 TIM3 做编码器TIM1 做 PWM标准外设库初始化如下void Encoder_Init_TIM3(void) { GPIO_InitTypeDef gpio; TIM_TimeBaseInitTypeDef tim; TIM_ICInitTypeDef ic; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // PA6 TIM3_CH1PA7 TIM3_CH2编码器 A/B 相接这里 gpio.GPIO_Mode GPIO_Mode_IN_FLOATING; gpio.GPIO_Pin GPIO_Pin_6 | GPIO_Pin_7; gpio.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, gpio); // 16 位计数器向上计数最大计数范围 0xFFFF tim.TIM_Period 0xFFFF; tim.TIM_Prescaler 0; tim.TIM_ClockDivision TIM_CKD_DIV1; tim.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, tim); // 两个通道都做输入捕获TI1 与 TI2 配合成 4 倍频 ic.TIM_Channel TIM_Channel_1; ic.TIM_ICPolarity TIM_ICPolarity_Rising; ic.TIM_ICSelection TIM_ICSelection_DirectTI; ic.TIM_ICPrescaler TIM_ICPSC_DIV1; ic.TIM_ICFilter 0x0F; TIM_ICInit(TIM3, ic); ic.TIM_Channel TIM_Channel_2; ic.TIM_ICPolarity TIM_ICPolarity_Rising; ic.TIM_ICSelection TIM_ICSelection_IndirectTI; ic.TIM_ICPrescaler TIM_ICPSC_DIV1; ic.TIM_ICFilter 0x0F; TIM_ICInit(TIM3, ic); // TI1 和 TI2 都计数4 倍频模式 TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_SetCounter(TIM3, 0); TIM_Cmd(TIM3, ENABLE); }逻辑说明TIM_EncoderMode_TI12 模式下 A/B 两路正交信号都被纳入计数计数器在四个边沿都翻转结果相当于硬件的 4 倍频。ICFilter 设到 0x0F 可以滤掉编码器在换向瞬间产生的毛刺。每次读取后用 CNT 清零得到的就是控制周期内的脉冲增量。参数说明TIM_Period 设成 0xFFFF 意味着计数器在 65535 处回绕。对 16 位增量不做符号扩展的话超过半个周期的正方向增量会被读成负数。低速下建议减小 TIM_Period比如设成 2000再用 int16_t 强转读回来这样回绕窗口和实际增量范围匹配不容易出符号错乱。读取速度的核心代码int16_t enc_count (int16_t)(TIM3-CNT); TIM3-CNT 0; float speed_rpm (float)enc_count * 60.0f / PULSES_PER_REV / (CONTROL_PERIOD_MS / 1000.0f);逻辑说明CNT 先强转成 int16_t是为了把 65535 回绕转成有符号增量前提是单个控制周期内的增量不会超过 32767。速度公式就是把脉冲数先换成圈数再除以周期换算成转每分钟。CONTROL_PERIOD_MS 必须和控制循环实际执行周期一致否则转速整体按比例偏大或偏小。3. 模糊自整定怎么落地量化因子、49 条规则表和 Sugeno 推理模糊自整定这层要解决的工程问题是给定一组 PID 基准值根据实时误差 e 和误差变化率 ec输出三个修正量 ΔKp、ΔKi、ΔKd。不要把它想成多高深的东西落在 F103 就是三个二维表加上一点加权运算。这章直接给出一套能抄的表和推理代码。3.1 输入量化与论域选择先定边界再谈隶属度物理量不能直接进规则表。误差 e 的单位是 rpm误差变化率 ec 的单位是 rpm/s必须各自缩放到标准论域 [-3, 3]typedef struct { float Ke; // 误差量化因子 float Kec; // 误差变化率量化因子 float limit; // 论域边界默认 3.0 } FuzzyInput; // 将物理量量化到 [-limit, limit] float FuzzyQuantize(float x, float scale, float limit) { float q x * scale; if (q limit) q limit; if (q -limit) q -limit; return q; }逻辑说明量化因子的物理含义是论域半宽除以实际物理量最大幅值。比如速度误差经常在 ±300rpm 以内Ke 取 3.0 / 300 0.01误差变化率正常不超过 ±1000rpm/sKec 取 3.0 / 1000 0.003。把 e 和 ec 先限幅再缩放可以避免偶发毛刺把输入推到论域之外。参数说明limit 不一定要 3取 2 也行但是量化档位变密后规则表灵敏度会增加建议先用 3跑完阶跃再调。Ke 偏大会让系统等效 Kp 放大偏小会让小误差根本到不了中心档位稳态精度下降。3.2 规则表设计逻辑大误差快追小误差细调规则表是模糊自整定里的黑匣子很多人照着抄但不知道为什么这样写。核心原则是三条误差大的时候Kp 要给大让系统快速靠近目标Kd 要放小防止起步就被微分项压住Ki 也要适当放小避免积分累积过头。误差中等的时候Kp 收一点Kd 回到适中让系统平滑过渡。误差小的时候Kp 继续减小Kd 略微加大用来抑制稳态抖动Ki 加大用来消除静差。下面是常用的 Kp 修正规则表行是 ec列是 e取值是输出论域上的离散档位NB 对应 -3NM -2NS -1ZO 0PS 1PM 2PB 3ec \ eNBNMNSZOPSPMPBNBPBPBPMPMPSPSZONMPBPBPMPSPSZONSNSPMPMPMPSZONSNSZOPMPMPSZONSNMNMPSPSPSZONSNSNMNMPMPSZONSNSNMNMNBPBZONSNSNMNMNBNB注意这张表沿主对角线呈反对称结构这个结构保证了误差为正和误差为负时修正方向相反不会出现某个象限里参数越调越紧导致系统自发振荡。Ki 和 Kd 表类似。Ki 表在中间 ZO 列处给正向增益因为稳态附近需要 Ki 拉大来消静差Kd 表在设计上要注意ec 大的时候输出档位不要给太高不然速度反馈的量化噪声会被放大成高频抖动。3.3 模糊推理与重心法去模糊的 C 实现规则表存的是输出档位需要转成实际修正量。完整 Mamdani 推理在 F103 上也就是三重循环加浮点乘除控制周期 5ms 到 10ms 完全跑得动。F103 没有 M4 的 FPUfloat 运算是软件算的一个推理周期实测在几十到一百多微秒量级对速度环不是瓶颈。核心推理函数// 三角形隶属度函数center 为中心位置half_width 为半宽 float Trimf(float x, float center, float half_width) { float d fabsf(x - center); if (d half_width) return 0.0f; return 1.0f - d / half_width; } // 计算输入 x 在 [-3,3] 上七个模糊子集的隶属度 void FuzzyMembership(float x, float m[7]) { for (int i 0; i 7; i) { m[i] Trimf(x, (float)(i - 3), 1.0f); } } // Sugeno 式重心推理rule 是 7x7 规则表 float FuzzyInfer(float e, float ec, const int8_t rule[7][7]) { float me[7], mec[7]; float num 0.0f, den 0.0f; FuzzyMembership(e, me); FuzzyMembership(ec, mec); for (int i 0; i 7; i) { for (int j 0; j 7; j) { // 取小运算作为规则强度 float w me[i] mec[j] ? me[i] : mec[j]; if (w 0.0001f) continue; // 输出模糊子集在这里用单值重心近似即规则表档位 float zc (float)rule[i][j]; num w * zc; den w; } } if (den 0.0001f) return 0.0f; return num / den; }逻辑说明每个输入在七个模糊子集上都有隶属度一条规则同时对 e 的某个档位和 ec 的某个档位生效规则强度取两者较小的那个这就是取小运算。输出不是只取激活度最高的一条规则而是把 49 条规则的加权平均值算出来这样输出是连续的不会出现档位跳变。参数说明Trimf 的 half_width 取 1.0意味着相邻模糊子集在中心点交界处恰好相交任何输入最多激活相邻两个子集其他隶属度为 0。这个设置保证了推理输出平滑。如果你想要系统更灵敏把 half_width 调小到 0.75更迟钝则调大到 1.25。4. STM32F103 工程落地引脚分配、控制循环和 PWM 输出映射原理讲完进入实际工程。这套东西不复杂但引脚分配和定时器资源规划一旦出错硬件上很难查先说清楚布局再贴代码。4.1 定时器资源规划与引脚映射STM32F103C8T6 只有 TIM1-TIM4 支持编码器接口。把编码器放在 TIM3PWM 放在 TIM1这个分配最省心功能定时器/外设引脚说明编码器 A 相TIM3_CH1PA6外部输入编码器 B 相TIM3_CH2PA7外部输入PWM 输出TIM1_CH1PA810kHz接驱动模块 INPWM 方向普通 GPIOPB0控制电机正反转串口调试USART1PA9/PA10转速打印、参数观察TIM1 是高级定时器输出 PWM 前需要配置刹车和死区相关寄存器否则 CCR1 写入不生效这是新手最容易卡住的地方。如果不想碰高级定时器的输出控制位把 PWM 挪到 TIM2_CH1 的 PA0 也行普通定时器没有刹车机制省事很多。4.2 10ms 速度环主循环读编码器、算模糊、跑增量式控制周期我一般按 5ms 到 10ms 选。速度环比电流环慢一个数量级10ms 足够。核心循环写成周期调度形式不要在 while 里直接延时否则串口打印和编码器读取会互相拖延volatile uint16_t g_tick_1ms 0; void SysTick_Handler(void) { g_tick_1ms; } // 主循环10ms 执行一次速度环 int main(void) { // ... 外设初始化略 uint16_t last 0; float target_rpm 120.0f; float e_prev 0.0f, e_prev2 0.0f; float speed 0.0f; float u_out 0.0f; // 基准 PID 值和输出步进 const float kp_base 0.08f; const float ki_base 0.02f; const float kd_base 0.01f; const float kp_step 0.02f; const float ki_step 0.005f; const float kd_step 0.003f; while (1) { if ((uint16_t)(g_tick_1ms - last) 10) { last g_tick_1ms; // 读取编码器增量并换算为转速 int16_t cnt (int16_t)TIM3-CNT; TIM3-CNT 0; speed (float)cnt * 60.0f / PULSES_PER_REV / 0.01f; // 计算误差与误差变化率 float e target_rpm - speed; float ec (e - e_prev) / 0.01f; // 量化后查模糊表得到修正档位 float eq FuzzyQuantize(e, 0.01f, 3.0f); float ecq FuzzyQuantize(ec, 0.003f, 3.0f); float dKp FuzzyInfer(eq, ecq, KpRuleTable); float dKi FuzzyInfer(eq, ecq, KiRuleTable); float dKd FuzzyInfer(eq, ecq, KdRuleTable); // 基准值加修正值 float kp kp_base dKp * kp_step; float ki ki_base dKi * ki_step; float kd kd_base dKd * kd_step; // 增量式 PID float du kp * (e - e_prev) ki * e kd * (e - 2.0f * e_prev e_prev2); u_out du; if (u_out PWM_MAX_DUTY) u_out PWM_MAX_DUTY; else if (u_out PWM_MIN_DUTY) u_out PWM_MIN_DUTY; e_prev2 e_prev; e_prev e; // 占空比映射到比较寄存器 TIM1-CCR1 (uint16_t)u_out; } } }逻辑说明控制周期 10ms每次读取编码器增量后立即清零保证下次窗口从零开始计数。ec 的计算是把两次误差差除以周期得到每秒误差变化量。模糊推理直接操作量化后的 [-3,3] 数值输出档位通过 step 系数还原成 PID 参数修正量。参数说明kp_base 是固定参数 PID 调试出的基准值模糊表在它附近摆动。kp_step 决定自整定的修正幅度0.02 表示最大修正 ±0.06也就是基准值在实际运行中最多偏移 75%。如果发现负载突变时响应不够加大 kp_step如果出现抖动减小它。注意每个控制周期都是从基准值重新计算不是累加修正这样模糊表输出偶发跳变时不会把 PID 参数一直带偏。4.3 PWM 频率与占空比映射CCR1 写错就是半速运行F103 主频 72MHzARR 取 7200 得到 10kHz 的 PWM 频率。这个频率下电机电磁噪声小驱动芯片开关损耗也可以接受。PWM 初始化void PWM_Init_TIM1(uint16_t arr, uint16_t psc) { GPIO_InitTypeDef gpio; TIM_TimeBaseInitTypeDef tim; TIM_OCInitTypeDef oc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE); gpio.GPIO_Mode GPIO_Mode_AF_PP; gpio.GPIO_Pin GPIO_Pin_8; gpio.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, gpio); tim.TIM_Period arr; // 7200 tim.TIM_Prescaler psc; // 0 tim.TIM_ClockDivision TIM_CKD_DIV1; tim.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1, tim); oc.TIM_OCMode TIM_OCMode_PWM1; oc.TIM_OutputState TIM_OutputState_Enable; oc.TIM_Pulse 0; oc.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM1, oc); // 高级定时器必须开启主输出否则 PA8 没有波形 TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE); }逻辑说明TIM_CtrlPWMOutputs 在高级定时器上是必须的它打开 MOE 主输出少了这一行 PA8 永远是低电平电机一动不动还查不出为什么。PWM 模式 1 表示计数器小于 CCR1 时输出高电平占空比 CCR1 / ARR。参数说明占空比输出是 u_out单位是计数单位而不是百分比。有些人习惯把 PID 输出限幅在 0~100 再赋值给 CCR1导致电机永远在很低的占空比下运行表现为转速整体偏小且加载后掉速明显。正确的做法是速度环输出直接以 CCR 计数单位为基准限幅到 0 和 ARR 之间。5. 避坑记录五个让电机失控或抖动的实际问题这章是我自己调试时踩过的坑每一条都跟着现象走。如果你照着上面代码改完还是不稳定先过一遍这里。5.1 现象电机上电直接朝一个方向加速到满转速度环完全没起作用原因典型有两个方向。一是编码器 A/B 相接反了电机实际正转时计数器在减数速度反馈是负值误差 e 始终大于零模糊表不断输出正向 Kp 修正PWM 越给越大。二是 PWM 和电机驱动方向控制不匹配占空比使能方向和编码器计数方向相反。解决先把编码器 A/B 对调或者软件里把增量取反cnt -cnt。然后在没接负载的情况下手动开环给一个固定占空比串口看编码器读数确认占空比增加时计数方向符合预期。5.2 现象电机转起来了但实际转速只有目标的一半PID 输出却已经接近 100%这个坑隐蔽在映射关系上。跑回环之前占空比低于 50% 时电机其实能全速转如果 PWM 占空比不是从 0% 到 100% 线性对应到电机电压而是驱动模块 IN 引脚还叠加了使能信号会吃掉一部分有效占空比。解决量一下电机端电压和占空比的关系确认驱动模块的输入是独立的 PWM 还是需要使能引脚一直拉高。常见的驱动模块使能脚如果悬空或接错引脚PWM 输入只会让输出端出现半开状态。5.3 现象目标 60rpm 时电机哒哒响波形上转速在 50rpm 和 70rpm 之间跳M 法测速在低速下的波长问题。每转 330 个脉冲60rpm 时 10ms 窗口内只有 3.3 个脉冲计数要么 3 要么 4换算出来相差 18rpm反馈本身就带大台阶。解决这个场景建议把编码器 4 倍频利用起来。TIM_EncoderMode_TI12 已经把每转脉冲放大到 132010ms 窗口内 13 个脉冲分辨率提升了四倍。如果还是不够把控制周期拉到 50ms但这会让速度环响应变慢模糊表对负载突变的抵抗能力会变差。另一个方案是换 T 法测速不过 T 法在 F103 上要占用输入捕获中断资源代码复杂度上一个台阶。5.4 现象空载波形挺好一带负载就出现周期性振荡Kd 修正值剧烈摆动负载变化导致速度瞬时跌落ec 突变到论域边界模糊表给出很大的 Kd 修正微分项又被编码器量化噪声进一步放大。越调越抖之后模糊表使用率非常高但实际系统性能比固定 PID 还差。解决先对 ec 做一阶低通滤波再送模糊表。滤波系数取 0.2 附近ec_filt ec_filt 0.2f * (ec - ec_filt);同时把 Kd 修正步进 kd_step 减小一半或者在规则表上把 Kd 表四角的值压低一档。记住模糊自整定调的是趋势不是让 Kd 完全跟随瞬时值。5.5 现象串口打印转速波形时控制循环间歇性卡顿波形整体被拉慢printf 往串口发数据时阻塞等待发送完成发送一帧几十个字节在较低波特率下耗时好几毫秒直接把 10ms 控制周期拖成长短不一的周期。控制周期不稳速度环相位裕量下降模糊表也跟着遭殃。解决串口输出用 DMA 或者只在特定标志位时才打印一帧。常见做法是维护一个环形缓冲主循环把格式化好的字符串丢进缓冲DMA 自己慢慢发速度环不等待发送完成。或者把打印周期拉长到 100ms 一次波形虽然略稀但控制周期保持稳定。6. 三档阶跃验证法十分钟内确认模糊表有没有调对调完频率和占空比最后做一次系统验证。我不建议直接看波形就下结论每次调完都按三档阶跃走一遍记录下来的数据比感觉可靠得多。先把目标转速设成 100rpm稳态运行 30 秒记录稳态误差波动范围。再把目标突然切到 200rpm观察超调量和调节时间。最后切到接近额定转速的 300rpm检查是否还能达到目标。三档数据填进下表的对应项校验项判定标准失败时的排查方向100rpm 稳态误差波动不超过 ±5rpmKp 基础值偏小Ki 修正幅度不足100→200rpm 超调量不超过 20rpmKd 过快介入模糊表在中等误差区修正过大200→300rpm 调节时间小于 1.5 秒Kp 基准值偏小量化因子 Ke 偏小300rpm 满载保持掉速不超过 30rpm编码器每转脉冲数标称值不准顺带把编码器每转脉冲数校准一下电机轴空转手动拨一圈轮子从串口读出计数增量和标称值对比。很多标称 1:30 的减速器实际减速比在 29 到 31 之间波动按标称值换算出来的转速会有几个百分点的系统偏差。之前一个项目一直抱怨速度控制精度不够查到最后是减速比偏差 4%速度环和模糊表本身没问题。进阶一点的技巧是给模糊输出加一个衰减系数。模糊表给出的修正量先乘一个 0.6 到 0.9 的系数再用系统会更稳定。这相当于给自整定加阻尼代价是负载突变时参数响应稍微慢半拍。我习惯在调试初期系数给 0.5等波形稳定后逐步加大到 0.9。最后说一个习惯从那以后我每次拿到新板子都会先跑一遍三档阶跃转速稳不下来就强制把 PWM 频率、编码器分频和量化因子全查一遍不搞玄学调参。固定 PID 参数对照组的波形也要留一版模糊自整定有没有真的改善性能对比数据说话。这套流程你照着走一遍模糊表能不能干活基本十分钟内就能判断出来。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑