电机控制这个领域,有个很有意思的现象:很多人PID调得飞起,觉得自己已经"会"控制了,直到某天遇到一个负载变化剧烈的工况,或者一个对跟随精度要求苛刻的位置环,才突然发现手里那把锤子好像不太够用了。我前阵子正好在一套直流无刷电机实验平台上,把传统PID、模糊PID和滑模控制(SMC)三种算法从头到尾各跑了一遍,踩了不少坑,也把每种算法的脾气摸了个大概齐。这篇文章不打算只列公式,我想直接聊聊三种算法在这套平台上的真实表现、调参过程里那些书本上不写的事,以及我最后在什么场景下愿意用谁。
直流无刷电机跟普通有刷电机不一样,它的换相是靠控制器完成的,转子是永磁体,定子绕组按一定顺序通电。这种结构决定了它天生效率高、寿命长,但也意味着控制起来有更多环节要做——六步换相、FOC矢量控制、速度环、电流环,每一个环节都有一堆参数在等你。而控制算法,说白了就是在这些环节里,决定"给定多少电压、在什么时刻换相"这件事。
我在平台上分别实现了速度闭环下的三种算法,然后做了三组对比测试:空载阶跃启动、突加负载、正弦波速度跟随。下面把过程彻底摊开来讲。
1. 为什么拿着调好的PID,我还在折腾另外两种算法
先说个场景。实验平台是一套24V的直流无刷电机,额定转速3000rpm,带一个磁粉制动器做负载模拟。我一开始用的是最经典的增量式PID,结构简单,代码量少,跑起来也确实稳。
PID的控制逻辑不复杂,它靠三个环节的组合来修正误差:比例项按当前误差大小出力,积分项把历史误差累积起来消除稳态偏差,微分项看误差变化的趋势来提前刹车。公式写出来就是:
u(t) = Kp * e(t) + Ki * ∫e(t)dt + Kd * de(t)/dt
这一套在转速恒定的场合非常好用,空载阶跃响应调一调,超调控制在5%以内,稳态精度在±10rpm以内,听起来挺像回事。
但问题很快就来了。当我打开磁粉制动器,让负载从0逐步加到额定转矩的80%时,转速掉了一截,然后靠积分项慢慢才拉回来,恢复时间大概在600ms左右。如果负载是周期性波动的呢?比如每秒钟波动一次,那转速就一直在跟着晃。PID的参数在低负载工况下调得再好,到了高负载区间,Kp和Ki的最优值其实是变了的,而固定参数照顾不了这么多工况。
另外还有一个在高频场合特别头疼的事:微分项对噪声极度敏感。速度环反馈来自编码器,编码器信号到了单片机里做差分求速度时,本身就会引入量化噪声。Kd稍微调大一点,电流指令就开始发抖,电机不仅啸叫,还会额外发热。后面我干脆给微分项做了低通滤波,算是压下去了,但也牺牲了一部分动态响应。
我当时的想法是:如果有一种算法,能让参数随着工况自己变,或者干脆不依赖精确模型也能扛住扰动,事情是不是就简单了?这就是我接下来去碰模糊PID和滑模控制的直接动机。
2. 传统PID在直流无刷电机上的控制逻辑与参数整定要点
要对比,先得把PID本身做扎实。我在平台上跑的是速度环+电流环的串级结构,内环电流环负责力矩响应,外环速度环负责转速稳定。电流环用的PI,速度环用PID,采样频率内环10kHz,外环1kHz。
2.1 位置式、增量式与微分先行选哪个
PID数字化的实现方式有三种常见形态:位置式、增量式、微分先行。位置式直接输出占空比或电压指令,积分项累积的是历史误差的完整和,容易出现积分饱和。增量式输出的是控制量的增量,执行器带记忆,不容易饱和,我速度环用的就是增量式:
Δu(k) = Kp * [e(k) - e(k-1)] + Ki * e(k) + Kd * [e(k) - 2*e(k-1) + e(k-2)]
这里有个细节:增量式天然隐含着"只关心变化量"的意思,所以就算误差突然跳变,输出也不会出现特别剧烈的冲击,这对电机电流保护比较友好。
微分项我单独做了处理。因为纯微分项会把高频噪声放大得离谱,我在工程里用的是"微分先行"结构——只对反馈量求微分,不对给定求微分。这样做的好处是转速给定突变时,微分项不会产生尖峰,起步瞬间的电流冲击要小很多。各位如果用的是位置式PID又碰到给定跳变导致过流报警,可以试试这个改法。
2.2 一套能落地的整定流程
PID参数我从来不靠公式硬算,而是遵循一套"先内后外、先比例后积分再微分"的工程流程:
- 先把积分项和微分项全部置零,只保留比例项。从很小的Kp开始,慢慢往上加,观察转速响应。转速开始出现等幅振荡时,记下这个临界增益和振荡周期。
- 把Kp回退到临界增益的50%左右,加上积分项。Ki先给一个保守值,观察稳态误差是否被消除,如果消除过程中转速出现缓慢的波动,说明Ki偏大,往回调。
- 最后加微分项。Kd从零往上试探,每次加一点点,观察转速毛刺。什么时候转速波形开始出现高频抖动,那就是Kd的上限,回退30%做余量。
- 整定过程中电流环的PI参数先固定,不要内外环一起调,否则出了问题你根本分不清是谁引起的。
这套流程跑下来,我在空载阶跃工况下得到了Kp=0.35、Ki=0.12、Kd=0.02这一组参数,超调量4.2%,调节时间180ms,静态误差基本测不到。看着不错,但心里清楚:这是"工况锁死"的结果。
2.3 PID三个参数在实测中暴露的软肋
超调量和恢复时间是一对天然矛盾。Kp给大了超调大,Kp给小了抗负载能力差。我在磁粉制动器负载从25%跳到70%的工况下测过,转速掉落大约120rpm,恢复时间约570ms。说实话这个数字不算难看,但放在要求高的场合,比如机器人关节或者医疗离心机里,这种扰动下的转速波动不可接受。
积分项更麻烦。为了把稳态误差压平,Ki不能太小,但Ki大了又会让系统在负载突变时"冲过头",转速会先越过目标值再荡回来。这个过程在低速重载工况下表现得尤其明显,电机能听到明显的"嗡——嗡"周期性声响,那就是积分项在临界振荡边缘反复拉扯。
微分项在无刷直流电机上还有个大坑:换相转矩脉动会直接混进速度反馈里。每60度电角度换一次相,转矩会瞬间掉一下再恢复,反映在速度环上就是一个周期性小毛刺。微分项看到这个毛刺就以为速度在剧烈变化,会给出反向补偿电流,结果电流波形里多了一大堆锯齿。这个必须靠低通滤波把换相脉动频率以上的分量滤掉,截止频率我取的是50Hz,效果还算能接受。
3. 模糊PID:把调参老师的经验塞进规则表里
模糊PID不是我凭空想出来的招,它的核心思路很朴素:既然PID参数在不同工况下的最优值不一样,那我就建立一个"工况→参数修正量"的映射表。这个映射表不用精确数学模型,而是把"误差大、误差变化快"这类模糊概念翻译成规则,让Kp、Ki、Kd随着工况自动调整。
3.1 模糊控制器到底在做什么
我用的结构是二维模糊控制器,输入是误差e和误差变化率ec,输出是三个参数的修正量ΔKp、ΔKi、ΔKd。最终参数等于基础值加修正量:
Kp = Kp0 + ΔKp Ki = Ki0 + ΔKi Kd = Kd0 + ΔKd
输入量先要做模糊化,就是把实际的误差数值映射到若干个模糊集合上。我把误差e的论域分成七个档:负大、负中、负小、零、正小、正中、正大,用字母表示就是NB、NM、NS、ZO、PS、PM、PB。误差变化率ec也做同样的划分。
关键在于隶属度函数。我用的是三角形隶属度函数,因为它计算量小、实现简单,在单片机里几乎不占资源。每个输入量在每个档位上都有一个隶属度值,范围0到1,表示"这个误差属于'负大'这个概念的程度上限"。这个环节说起来抽象,跑起来就是一个查表加插值的事。
推理解法用的是Mamdani算法,规则表是核心。比如规则可以写成:如果e是NB且ec是NB,那么Kp取大增量、Ki取小增量、Kd取小增量。这类规则我总共列了7×7=49条,每条对应一种工况组合,完全是从"有经验的人怎么调参"的逻辑里归纳出来的。
去模糊化我选的是重心法,就是把所有规则的输出按照隶属度加权平均,得到一个具体的修正量数值。重心法计算稍微麻烦点,但输出比较平滑,不会像最大隶属度法那样有跳变。
3.2 规则表的核心逻辑:看的是边际变化,不是绝对值
很多人第一次写规则表容易犯一个错:只盯着误差大小,不看误差变化的趋势。我举个例子,同样是转速误差是50rpm:
- 如果误差还在继续变大,那是系统正在恶化,必须加大Kp往回拉。
- 如果误差已经在快速变小,说明系统正在恢复,这时候再加Kp反而会过头,应该适可而止。
所以规则表里,我表头是误差e,表列是误差变化率ec,两者交叉处才是ΔKp的值。下面是我实际用的Kp修正规则表(局部):
| e \ ec | NB | NS | ZO | PS | PB |
|---|---|---|---|---|---|
| NB | 大 | 中 | 中 | 小 | 零 |
| NS | 中 | 中 | 小 | 零 | 小 |
| ZO | 中 | 小 | 零 | 小 | 中 |
| PS | 小 | 零 | 小 | 中 | 中 |
| PB | 零 | 小 | 中 | 中 | 大 |
这张表的逻辑是:误差大且误差还在继续增大时,Kp修正量给到最大档;误差小且误差变化率也小,那就别乱动参数,让它稳定待着。Ki和Kd的规则表逻辑类似,Ki在误差中等偏大时才加强,避免积分饱和;Kd在误差变化率明显增大时给到最大,用来提前抑制超调。
3.3 模糊PID实测表现与调试中的坑
我在这套平台上跑模糊PID,第一个直观感受是:阶跃启动的转速曲线明显比以前利索了。因为启动瞬间误差大,模糊规则自动把Kp拉高,加速过程变快;接近目标转速时误差变小,Kp被往下调,Kd被往上加,超调被压住。最终测出来的超调量约1.8%,调节时间120ms,两项指标都比固定PID要好看。
抗扰动的改善更明显。突加负载70%的工况下,转速掉落从PID的120rpm降到了70rpm,恢复时间从570ms缩到了320ms。原因在于负载突变那一瞬间,误差变化率ec冲到了负大,规则表立刻把Kp和Ki往大了调,相当于系统自动"反应更猛了"。
不过坑也相当多。第一,模糊规则表不是越多越好,49条规则我前后调了四版才稳定下来。规则之间可能存在冲突,两条规则给出的结论相反时,输出会变得很怪,表现为转速曲线在某些工况下出现莫名其妙的抖动。第二,隶属度函数的形状和论域范围很敏感。论域设小了,误差很快触达边界,输出修正量一直饱和在最大值附近,模糊控制器退化成一个大增益PID;论域设大了,误差总是在中间的模糊地带,修正不够敏锐,提升有限。第三,重心法在单片机上是浮点运算,每一步推理和去模糊化大概要多花40微秒,我用的是主频168MHz的MCU,速度环1kHz的采样周期完全扛得住,但如果你用的是低端MCU,得把量化表和插值算好,不然肯定顶不住。
4. 滑模控制:从建模开始,到和抖振硬碰硬
滑模控制跟前面两种算法的思路完全不同。PID和模糊PID说到底都是"看误差调输出",滑模控制的核心思想是"设计一个滑模面,然后不管系统在哪,都强行把它拉到滑模面上来"。
4.1 先把电机的数学模型摆出来
直流无刷电机在dq坐标系下的运动方程,速度环这一层用起来最顺手的形式是:
J * dω/dt = Kt * iq - TL - B * ω
其中J是转动惯量,Kt是转矩系数,iq是q轴电流,TL是负载转矩,B是粘滞摩擦系数。这个模型忽略了一些次要项,比如电枢电感对速度环的延迟,工程上够用了。
关键在于:J、Kt、B这些参数,实际工作中你是测不准的,温度变了、负载变了,有效转动惯量都会变。所以如果设计的控制器严重依赖精确模型,那到了现场一定会拉胯。滑模的一个好处恰好在这里——它不那么依赖精确模型,只要参数误差在一个有界范围内,它照样能把系统拉到滑模面上。
4.2 滑模面设计与控制律的完整推导
我设计的是最简单的线性滑模面:
s = c * e + de/dt
其中e是转速误差,c是一个正值常数。s=0时,系统就满足de/dt = -c * e,误差按指数衰减,衰减速度完全由c决定。这个c就是"系统要多快趋向目标"的旋钮。
控制律分两部分:等效控制项加切换控制项。等效控制项是把系统模型代入滑模面的保持条件ds/dt=0解出来的,它负责"让系统保持在滑模面上";切换控制项负责"把偏离滑模面的系统拉回来",一般取一个符号函数:
iq_ref = iq_eq + k * sign(s)
i q_eq = (J * (dω_ref/dt + c * de/dt) + B * ω + TL_est) / Kt
切换增益k必须大于系统总扰动的上界,才能保证滑动模态能建立起来。这个上界我一开始估计得保守,取了个比较大的值,结果就是:滑模面是进去了,但系统在滑模面附近来回穿越,控制量高频切换,电机电流波形跟锯条似的,这就是著名的抖振问题。
4.3 三种抖振抑制手段的实测对比
抖振是滑模控制在工程落地时绕不开的坎,我前后试了三种方法:
第一种是边界层法,把符号函数替换成饱和函数,在滑模面附近设定一个边界层厚度Δ,s在边界层内部时,控制量按比例线性变化而不是直接切换:
sat(s/Δ) = s/Δ,|s| < Δ 时;sign(s),|s| ≥ Δ 时
边界层越厚,抖振越小,但跟踪精度越差,因为系统实际上是停留在边界层里面而不是严格在滑模面上。Δ我试了0.02到0.1,转速纹波从±15rpm降到±5rpm时,跟踪误差却从2rpm涨到了10rpm,这个取舍得看具体应用。
第二种是趋近律法。控制的不是直接给一个常值k,而是设计一个趋近律,让s按某种规律趋近于零。我用的是指数趋近律:
ds/dt = -ε * sign(s) - q * s
ε是等速趋近项系数,q是指数趋近项系数。实测下来,这种方法的抖振比纯常值切换轻不少,因为q * s这一项可以让s在靠近零点时速度变缓,自然减轻了穿越的冲击。
第三种是扰动观测器辅助。既然抖振的根源是扰动观测不准、只能用大切换增益去硬抗,那我干脆加一个扩张状态观测器把总扰动估出来,前馈补偿掉一部分,切换增益的负担就小了。我用了一阶扩张状态观测器,把负载转矩和模型误差当成扩张状态去估,效果是最明显的,转速纹波降到了±3rpm,电流锯齿也基本看不到了。代价是观测器本身有三个增益要调,其中一个调大了会在系统里注入高频噪声,调小了对扰动估计滞后,这个要反复磨合。
5. 三种算法同台实测:指标对比与现场数据
前面每个算法单独说了一堆,但真正让人下决心的,是同一个平台上、同一套工况下跑出来的对比数据。我设计了三组测试,每组都记录超调量、调节时间、抗扰动恢复时间、稳态误差、控制量抖动这几项硬指标。
5.1 空载阶跃响应对比
给定转速从0阶跃到1500rpm,记录转速响应曲线。
| 算法 | 超调量 | 调节时间(±2%) | 稳态误差 | 控制量平滑度 |
|---|---|---|---|---|
| 传统PID | 4.2% | 180ms | ±2rpm | 平滑 |
| 模糊PID | 1.8% | 120ms | ±1rpm | 平滑,启动初段略猛 |
| SMC(边界层) | 0% | 110ms | ±8rpm | 有明显高频分量 |
| SMC(观测器辅助) | 0% | 105ms | ±3rpm | 基本平滑 |
滑模控制确实能做到零超调,这是它的结构决定的——滑模面一旦建立,系统沿着滑模面走,而线性滑模面本身不产生超调。但注意看稳态误差,边界层法的稳态误差明显比另外两种算法大,这就是前面说的"边界层厚度换抖动"的代价。
5.2 突加负载扰动对比
稳态运行在1500rpm,突加70%额定负载,记录转速掉落和恢复时间。
| 算法 | 最大转速掉落 | 恢复时间 |
|---|---|---|
| 传统PID | 120rpm | 570ms |
| 模糊PID | 70rpm | 320ms |
| SMC(边界层) | 45rpm | 150ms |
| SMC(观测器辅助) | 30rpm | 100ms |
这一项滑模的优势非常明显。因为滑模控制本身对外部扰动有不变性,只要扰动在切换增益的能力范围内,它根本不在乎扰动有多大,直接给你压回去。模糊PID虽然能自动调参数,但响应还是需要一两个控制周期才能把增益调上去,反应速度上比不过滑模的"硬扛"。
5.3 正弦速度跟随对比
给定速度按1Hz正弦波变化,幅值200rpm,记录最大跟踪误差。
| 算法 | 最大跟踪误差 |
|---|---|
| 传统PID | 38rpm |
| 模糊PID | 22rpm |
| SMC(边界层) | 25rpm |
| SMC(观测器辅助) | 12rpm |
正弦跟随这个场景,模糊PID表现很亮眼,因为它规则表里的"误差变化率"维度和正弦波的"速度一直在变"特别契合,参数的实时调整充分发挥了作用。滑模这边,观测器辅助方案的12rpm误差是最好的,但边界层方案因为为了抑制抖动牺牲了精度,反而比模糊PID差。
我总结一下三张表的规律:纯抗扰动场景,滑模无敌;变工况场景,模糊PID的适应性和精度平衡最好;固定工况低成本场合,传统PID够用且省心。
6. 选型决策与调试中的关键经验
聊完实测数据,最后说点更务实的:什么时候选谁,以及调试过程中那些让人抓狂的细节。
6.1 按应用场景选算法的实用决策表
我给三种算法画了个大致的适用范围:
| 应用场景 | 推荐算法 | 原因 |
|---|---|---|
| 风扇、水泵等恒速运行 | 传统PID | 结构简单、稳定可靠、成本最低 |
| 负载变化明显的自动化设备 | 模糊PID | 自动适应工况变化,性价比高 |
| 伺服位置跟随、机器人关节 | SMC+观测器 | 抗扰动能力强,跟踪精度高 |
| 模型不确定且要求强鲁棒的场景 | SMC | 核心优势就是鲁棒性 |
| 硬件资源受限的小型控制器 | 传统PID或查表式模糊PID | 计算量小,实时性有保障 |
需要提醒一点,滑模控制是"强鲁棒性"但不是"万能药"。它的鲁棒性是有条件的,切换增益必须大于扰动的上界。如果你面对的是一个扰动上界根本无法估计的系统,为了硬抗抖动把增益调到极大,系统会变得比PID还要差,表现为持续的极限环振荡。
6.2 我踩过的几个典型坑
第一个坑是SMC切换增益调太大导致的电流饱和。有一次我把切换增益k设成正常值的2.5倍,结果转速是稳了,但突加负载时电流指令直接顶到限幅值,电流环饱和,瞬间转速反而掉得更厉害。这是因为切换控制项在扰动来的时候会要求"无穷大"的控制力,但实际系统有物理极限,输出顶到天花板以后,后面的积分式等效控制项也跟着失控。解决方法是把滑模控制输出的参考电流也加一个限幅,但限幅值要和切换增益联动设计,不能各自为政。
第二个坑是模糊PID的论域匹配问题。我一开始把误差论域设成±500rpm,但实际上大部分时间系统工作在±50rpm以内,这导致模糊控制器长期在"零"附近的小档位上工作,修正量几乎为零,模糊PID退化成了普通PID。后来我把论域改成了±80rpm,把分辨率集中在小误差区间,效果立刻变了。这个细节特别容易忽视,因为仿真里你给阶跃信号,误差动辄几百转,但实际稳态运行时误差其实很小,论域必须按实际运行区间来设计。
第三个坑是采样周期差异问题。滑模控制对控制周期很敏感,理想情况下切换控制项希望无限快的切换,但实际数字控制有固定采样周期。我用1kHz速度环跑滑模时,抖振明显比用2kHz时要严重。把内环电流环的周期从5kHz提到10kHz后,滑模的表现上了一个台阶。这并不是说所有系统都必须跑到10kHz,但如果你发现抖振怎么压都压不下去,先看看采样率是不是瓶颈。
第四个坑和编码器分辨率有关。我用的编码器是每转2500线,四倍频以后就是10000个脉冲/转。这是配合1500rpm转速,分辨率相当于0.06rpm的量化步长,看起来够用,但做差分求速度时量化噪声其实不小。滑模控制的微分项对噪声极其敏感,我最后对速度反馈做了一阶低通滤波,截止频率80Hz,稳定性和控制品质都改善了很多。滤波不能太狠,否则相位滞后会让滑模面不对,系统照样拉胯。
6.3 一个值得尝试的混合思路
如果你拿不准选谁,我的建议是别把它们当成互斥选项。我在平台上最后跑通的一种方案是:模糊PID做主控制器,负责正常工况下的转速调节;SMC只在线性滑模面失稳或扰动特别剧烈的时段切入。这种混合策略不是我自己拍脑袋想的,是一个做运动控制的同行分享的思路,实测效果确实好——正常工况下保持模糊PID的低超调和低抖振,扰动工况下依靠SMC的强鲁棒性迅速恢复。
实现起来关键要解决两个问题:一是"什么时候切入"的判据,我用的判据是转速误差绝对值超过阈值,或者误差变化率连续N个周期持续增大;二是切入时间的平滑处理,不能直接切换,否则输出会跳变,我用了一阶惯性滤波做过渡。
还有一个思路更简单,就是用模糊规则去"调度"SMC的切换增益,本质还是那套"工况自适应"的思想,只不过调的对象从PID参数换成了滑模的控制强度。这两种混合思路做下来,实验效果都算满意,比单独使用任何一种算法来得从容。
我自己的体会是,控制算法这行,没有银弹。你手里拿着的不是一把最锋利的刀,而是一把可以换刀片的瑞士军刀。把每种算法的边界摸清楚,比背下一堆公式有用得多。至少现在我再碰到一个新工况,第一反应不是急着上滑模,而是先把系统需求捋一捋,然后从最简单的PID开始往上叠。这个习惯,比任何一种控制算法都值钱。