搞无感FOC的都知道,零速到低速这一段是所有无传感器控制方案的分水岭。反电动势幅值跟转速成正比,转速一旦掉到额定值的5%以下,位置信号基本就被噪声、死区和电流测量误差吃掉了。这个项目给的是一个完整解题思路:用改进Ortega观测器做宽速度范围的非线性磁链观测,配合初始位置辨识和启动策略,实现永磁同步电机的零速闭环启动,最终交付一套可直接运行的Matlab/Simulink模型和源代码。
如果你正在做无感FOC、电动压缩机、风机泵类控制,或者研究方向是无位置传感器控制,这套东西可以直接拿来当底稿。它不是什么论文里的花架子,而是我这边从仿真到实机都跑过的一整套闭环方案。下面把原理、代码、启动流程和调试中踩过的坑一次说清楚。
1. 项目概述与方案定位
1.1 这个项目要解决什么问题
先把痛点摆出来:普通无感FOC在额定转速附近做得很好,滑模观测器加一堆滤波器就能转得很稳。但一上电就要带载启动的场景里,转子是静止的,反电动势为零,任何基于反电动势的观测器都失效。这时候控制器的角度从哪来?怎么判断转子朝哪个方向?怎么让它不后退、不倒转、不失步?这几个问题解决不了,整个系统就是能转但不好用。
市面上常见的应对手段是高频注入法,靠电机的凸极效应或者磁饱和特性提取位置。但高频注入有个先天毛病:对电感凸极率敏感,表贴式电机本身凸极率很低,注入信号容易淹没在噪声里,而且高频电流会带来额外损耗和转矩脉动,让电机发热。做风机、泵类这种成本敏感的场合,没人愿意为那点凸极率付出这么多代价。
这个项目的路子是:高频注入我不碰,反电动势我又指望不上零速,那就用两段式策略——启动瞬间用脉冲电压定位加电流斜坡把系统"带"起来,转速起来之后交给改进Ortega观测器做闭环跟踪。这样既躲开了高频注入的麻烦,又比纯开环强启可靠得多。
1.2 为什么选改进Ortega观测器
先说说我为什么不选常见的滑模观测器。滑模的原理是利用等效控制信号估计反电动势,本质是靠符号函数的非线性切换把误差"拍"到滑模面上。问题是这个切换过程天然带来高频抖振,位置提取前必须先低通滤波,滤波就引入相位延迟,转速越低延迟的影响越大,补偿不好就发散。我不是说滑模不能用,只是它在宽速度范围、零低速切换这个场景下,调参工作量确实大。
MRAS(模型参考自适应)也试过,它对电机参数的依赖比滑模还严重,尤其参考模型在低速时几乎不可观测,增益怎么选都别扭。龙伯格观测器本质是线性观测器,对PMSM这种强非线性系统来说,线性化之后在工况变化剧烈时会丢精度。
Ortega观测器是另一条路:它把PMSM的电磁方程当作一个带结构特性的系统来设计观测器,以定子磁链为状态变量,通过电流误差做闭环反馈修正。这么做的结果就是观测器连续且光滑,没有滑模那种抖振,不需要额外的低通滤波,从低速到高速的过渡天然平滑。而且它可调的参数很集中,主要就是观测增益和归一化参数,对工程交付来说,可控变量越少,出问题的面就越小。
1.3 零速闭环启动的完整技术链条
单靠观测器是做不到零速闭环的,这个必须先认清。整体方案拆成三块:
- 初始位置辨识:上电后先判断转子磁极在哪,保证启动方向的正确性
- 零速启动策略:在观测器还没建立可信角度前,用电流引导或直接使用辨识角完成启动
- 平滑切换逻辑:当观测器输出稳定后,把控制角度从启动角度切到观测器输出角度
后面所有内容都围绕这三块展开。模型里我同时保留了I/f启动支路和"辨识角直接闭环"两种路径,调试时可以对比观察。整个仿真模型跑下来,从零速阶跃到额定转速,再加载和反转,都能稳定跟踪。
2. 改进Ortega观测器的原理拆解
2.1 从PMSM电磁模型出发
表贴式PMSM在两相静止坐标系下的电压方程是:
u_α = R_s·i_α + dψ_α/dt u_β = R_s·i_β + dψ_β/dt
定子磁链由两部分组成,电枢反应磁链加永磁体磁链:
ψ_α = L_s·i_α + ψ_f·cos(θ_e) ψ_β = L_s·i_β + ψ_f·sin(θ_e)
其中R_s是定子电阻,L_s是同步电感,ψ_f是永磁磁链,θ_e是转子电角度。所以只要有ψ_α、ψ_β,就能反解出θ_e:
θ_e = atan2(ψ_β - L_s·i_β, ψ_α - L_s·i_α)
这就是非线性磁链观测的基本出发点。注意这里的方程已经包含非线性项cos、sin,跟纯线性观测器的建模思路不一样。
2.2 原始Ortega观测器的结构与致命弱点
Ortega观测器的经典形式是给磁链的电压模型积分回路加上电流误差反馈项:
dψ̂_α/dt = u_α - R_s·i_α + λ·(i_α - î_α) dψ̂_β/dt = u_β - R_s·i_β + λ·(i_β - î_β)
其中î_α、î_β是估计电流,从估计磁链反算:
î_α = (ψ̂_α - ψ_f·cos(θ̂_e)) / L_s î_β = (ψ̂_β - ψ_f·sin(θ̂_e)) / L_s
λ是可调增益。它的逻辑很直观:如果磁链估计错了,反算出的电流就跟实际电流对不上,用这个误差去修正磁链的积分方向。理论上,λ选择合适,磁链估计误差会按指数收敛。
但我把原始结构搬进Simulink之后发现几个致命问题。第一个也是最狠的:磁链幅值会漂移。电压模型本质是积分器,u_α - R_s·i_α里只要混入一点点直流偏置,积分器就一直把它攒下去,结果是磁链圆越画越大,最后收敛到饱和。原始观测器的电流反馈能抑制一部分,但抑制不了积分器本身的行为——磁链幅值一旦偏移,电流误差反馈很难把它完全拉回来。第二个问题是收敛速度:磁链初值给不准的时候,原始观测器要磨蹭好一阵才能进入稳态,这期间角度输出一直不对,根本没法闭环。第三个问题是增益λ的选取:太小收敛慢,太大又把电流噪声直接灌进磁链积分,位置抖动得厉害。
2.3 三项关键改进措施
针对上面三个问题,我在模型里加了三个改进。
改进一:磁链幅值归一化投影,而且是带死区的归一化。每步计算完磁链估计值之后,先算幅值:
ψ_mag = sqrt(ψ̂_α² + ψ̂_β²)
如果ψ_mag跟ψ_f偏差超过5%,就把磁链向量投影回去:
ψ̂_α = ψ_f·ψ̂_α / ψ_mag ψ̂_β = ψ_f·ψ̂_β / ψ_mag
这个操作等于给积分器上了一道保险,不管直流偏置怎么污染,磁链幅值都被强制锁在真值附近。我用死区是为了防止它过度干预,因为正常工况下磁链幅值本来就稳定在ψ_f附近,不需要每步都投影。实测下来,加了归一化之后启动初值随便给都不会跑飞。这里有个很重要的细节:投影操作虽然把幅值拉回来了,但对相位的影响很小,所以角度估计不会因此被带偏。
改进二:增益自适应。把固定λ改成转速相关的形式:
λ = λ_0 + k_λ·|ω̂_e|/(ω_rated + ε)
低速时λ取一个基础值,用来维持电流误差修正的收敛;高速时增益自动加大,抵抗反电动势增大后带来的模型扰动。这个式子里ε是为了防止除零。为什么不直接用固定大增益?因为在零速附近大增益会把电流采样噪声放大,带进积分回路之后磁链抖动明显,转矩也跟着抖。
改进三:初始磁链赋值。不搞"从零积分到收敛",而是在启动瞬间根据辨识到的转子位置和当前电流直接计算磁链初值:
ψ̂_α(0) = L_s·i_α(0) + ψ_f·cos(θ_0) ψ̂_β(0) = L_s·i_β(0) + ψ_f·sin(θ_0)
θ_0就是初始位置辨识得到的角度。这样磁链观测器一启动就已经基本贴着真实值,省掉了最磨人的收敛过程。这对零速启动尤其关键——启动阶段本来就不允许角度估计有太大偏差,初值给对了,后面的切换压力就小得多。
2.4 转子位置与转速的提取方式
位置提取直接用代数方程,不用锁相环也不做滤波:
θ̂_e = atan2(ψ̂_β - L_s·i_β, ψ̂_α - L_s·i_α)
真实永磁磁链分量落在αβ平面上,这个atan2直接给出电角度。速度估计我用位置差分加一阶低通:
ω̂_e = (θ̂_e[k] - θ̂_e[k-1]) / T_s + 低通
位置差分的噪声问题很明显,所以低通截止频率放在200Hz左右比较合理。控制器里用的转速信号基本都经过这个低通,避免速度环被观测噪声激怒。
从实机调试的角度说,如果还想进一步压缩噪声,可以在差分之前对θ̂_e做角度圆滑(处理角度绕圈),或者在低通之前加一个简单的均值滤波。我的模型里用差分加一阶惯性已经够用了,关键是惯性时间常数别太大,否则速度信号延迟一上来,高速段会相角裕度不足。
3. Matlab模型搭建与源代码实现
3.1 仿真平台与顶层架构
我用的环境是Matlab/Simulink,模型整体采用定步长离散仿真,控制周期Ts_c = 1e-4秒(10kHz),仿真步长设在1e-6秒,兼顾PWM波形精度和仿真速度。模型分四块:
- 电机本体:PMSM模型,包含电气和机械方程,初始转速设为零
- 逆变器与PWM:SVPWM调制,直流母线电压可配
- 控制核心:FOC双闭环,d/q轴电流环加外环速度环
- 观测与启动逻辑:改进Ortega观测器、初始位置辨识、启动角度切换
这样的分层结构调试时很有用。哪个环节出问题,看对应模块的信号就行,不用整个模型翻。
3.2 关键电机与控制器参数
先给一组我调试用的基准参数,方便你复现的时候对照。
| 参数 | 数值 | 说明 |
|---|---|---|
| R_s | 2.875 Ω | 定子电阻 |
| L_s | 8.5 mH | 同步电感(表贴式L_d = L_q近似) |
| ψ_f | 0.175 Wb | 永磁磁链 |
| 极对数 p | 4 | 电角度 = 机械角×4 |
| J | 0.001 kg·m² | 转动惯量 |
| 直流母线电压 | 310 V | 三相整流典型值 |
| 开关频率 | 10 kHz | SVPWM载波 |
电流环PI的整定我按带宽法来。电流环带宽取500Hz,对应ω_c = 2π×500 ≈ 3140 rad/s,那么:
Kp_i = L_s·ω_c ≈ 0.0085×3140 ≈ 26.7 Ki_i = R_s·ω_c ≈ 2.875×3140 ≈ 9027
速度环带宽取电流环的十分之一左右,大概50Hz,Kp_s按J乘带宽再除个比例系数,具体值在调的时候微调。这套参数在仿真里稳得不挑毛病,实机上根据母线电压和电流采样延迟做适度缩放。
3.3 改进Ortega观测器的Matlab代码
观测器我用Simulink里的Matlab Function模块实现,代码是离散欧拉积分。核心代码骨架如下:
function [theta_hat, omega_hat, psi_alpha_hat, psi_beta_hat] = ... ortegaObserver(u_alpha, u_beta, i_alpha, i_beta, ... omega_hat_prev, theta_init, Ts, para) % para: Rs, Ls, psi_f, lambda0, k_lambda, omega_rated persistent psi_a psi_b theta_prev init_done if isempty(init_done) % 利用初始位置给定磁链初值,避免收敛过程 psi_a = para.Ls * i_alpha + para.psi_f * cos(theta_init); psi_b = para.Ls * i_beta + para.psi_f * sin(theta_init); theta_prev = theta_init; init_done = 1; end % 1. 用当前磁链估计值反算估计电流 theta_tmp = atan2(psi_b - para.Ls*i_beta, psi_a - para.Ls*i_alpha); i_hat_a = (psi_a - para.psi_f*cos(theta_tmp)) / para.Ls; i_hat_b = (psi_b - para.psi_f*sin(theta_tmp)) / para.Ls; % 2. 自适应观测增益 lambda = para.lambda0 + para.k_lambda * abs(omega_hat_prev) ... / (para.omega_rated + 1e-6); % 3. 磁链观测方程:电压模型 + 电流误差反馈 dpsi_a = u_alpha - para.Rs*i_alpha + lambda * (i_alpha - i_hat_a); dpsi_b = u_beta - para.Rs*i_beta + lambda * (i_beta - i_hat_b); % 4. 欧拉积分 psi_a = psi_a + dpsi_a * Ts; psi_b = psi_b + dpsi_b * Ts; % 5. 磁链幅值归一化投影(带5%死区防止过度干预) psi_mag = sqrt(psi_a^2 + psi_b^2); if abs(psi_mag - para.psi_f) / para.psi_f > 0.05 && psi_mag > 1e-6 psi_a = psi_a / psi_mag * para.psi_f; psi_b = psi_b / psi_mag * para.psi_f; end % 6. 提取转子位置 theta_hat = atan2(psi_b - para.Ls*i_beta, psi_a - para.Ls*i_alpha); theta_hat = mod(theta_hat, 2*pi); % 归一到[0, 2pi) % 7. 速度估计:位置差分 + 一阶低通(离散形式) dtheta = theta_hat - theta_prev; if dtheta > pi dtheta = dtheta - 2*pi; elseif dtheta < -pi dtheta = dtheta + 2*pi; end omega_raw = dtheta / Ts; omega_hat = omega_hat_prev + ... (omega_raw - omega_hat_prev) * para.lpf_alpha; theta_prev = theta_hat; psi_alpha_hat = psi_a; psi_beta_hat = psi_b; end有几点要特别说明。第1步里的theta_tmp是用磁链估计值临时算的角度,跟最终输出theta_hat基本一致,但在归一化投影之前,这一步的观测器电流误差计算用的是"当前磁链反算电流"的逻辑,保证反馈回路闭合。第7步的角度差分做了绕圈处理,这个不做的话,角度从2π跳到0的一瞬间速度会爆出一个巨大的尖峰。我踩过这个坑,一次启动波形里突然出现一个正负几千的转速毛刺,查了半天就是角度wrap的问题。
3.4 零速闭环启动仿真配置
模型的启动逻辑我用一个Stateflow状态机来管,也可以写成普通的逻辑模块。状态分三个阶段:
阶段一:初始位置辨识。仿真开始后先由辨识模块向六个方向依次施加短时电压脉冲,电流采样对比,输出初始角θ_0。这个阶段持续时间约20ms,结束前电机基本不转。
阶段二:FOC闭环启动。辨识完成后,控制角度直接用θ_0,速度环给定斜坡从0爬升到目标转速,电流环限幅保证启动电流可控。此时观测器也在运行,但输出角度不进入控制回路,只做跟踪校验。
阶段三:观测器接管。当观测器角速度估计值连续超过额定值5%一段时间,并且观测角度与当前控制角度的偏差小于15°电角度,切换逻辑就启动一个斜坡器,把控制角度从θ_0渐变到θ̂_e,过渡时间约50~100ms。切换完成后进入稳态无感闭环运行。
整个模型里我把切换条件的判断信号引出到Scope,方便你看清楚每个时刻处于哪个状态。刚开始调试的时候可以把切换时间拉长,等观察器等稳定了再加速切换过程。
4. 零速闭环启动的难点与实现路径
4.1 零速下观测器为什么失效
这个问题必须在原理上想透。电压方程里磁链的变化率等于u - R·i,这里面其实隐含了反电动势的信息。转速为零时,反电动势为零,u - R·i里剩下的主要是电阻压降和电感上的瞬态项。电流变化慢慢停下来之后,能用来提取位置的信息量几乎为零。离散实现里还有电流采样噪声和逆变器死区带来的电压误差,这些误差在低速时跟信号本身差不多大,观测器再聪明也分不清哪些是误差哪些是真实反电动势。
更具体地看观测器方程,电流误差反馈项λ·(i - î)在零速附近的收敛性也不理想。因为i - î通过永磁磁链角度耦合到磁链估计上,角度误差在这个工况下不被激励,观测器处于弱可观测状态。这不是参数问题,是问题的本质。所以零速启动不能指望观测器,必须靠外部手段先把转子状态确定下来。
4.2 初始位置辨识:从粗定位到精确极性判断
模型里用的脉冲电压矢量法,原理是利用磁路饱和效应。向某个方向施加一个电压脉冲,电流的上升斜率跟该方向的电感成反比。d轴方向因为永磁体磁路饱和,电感略小于q轴,所以响应电流更大。实际操作分两个层次。
粗定位:向六个方向各发一个持续时间在0.5ms左右的电压脉冲(幅值经过限幅,保证电流峰值不超过额定1.5倍),采样每个脉冲结束时的电流峰值,电流峰值最大的那个方向,就是磁极的轴线方向。
极性判断:粗定位只能确定轴线,但分不清N还是S。我再用同样的脉冲向轴线的正向和反向各打一次,比较峰值电流。如果正向脉冲电流大,说明这个方向磁路更饱和,即d轴正方向;反过来则是反方向。极性判断一定要做,否则角度直接差了180°,FOC一启动就是严重失步。
几个实施细节:脉冲间隔要留出电流衰减时间,避免上一次脉冲的电流影响下一次采样;每次脉冲的宽度要一致,保证对比在同一条件下进行;电流峰值采样要避开PWM开关切换瞬间的毛刺。这些细节不做,辨识结果就是抖的。
4.3 启动到闭环的过渡逻辑
辨识出可靠初始角之后,启动路径有两条,模型里都能选。
路径A:辨识角直接闭环启动。上电后把FOC的编码器角度接口接到θ_0,速度环用斜坡给定,电流环自动建立起转矩。这个方案响应快,适合要求快速带载的工况。对初始辨识精度要求高,误差最好控制在5°电角度以内,否则启动那一下会有明显冲击。
路径B:I/f强制启动再切换。不用初始角度做位置闭环,而是给定一个旋转电流矢量,电流幅值恒定,电流角刚开始等于θ_0,然后按斜坡频率旋转。转子的同步转矩会拉着它跟着电流矢量一起转,这就是所谓的自整步效应。转到额定转速5%以上后,再切换给观测器。
模型里我默认跑路径A,因为要验证"闭环启动"的完整效果。但调试时我会先从路径B跑通,再切到A,因为B对初始角的容错性高一些,A对观测器初值和辨识精度的要求都更严格。切换逻辑上,角度过渡我用斜坡插值,不用阶跃切换,否则切换瞬间电流突变直接触发过流保护。
5. 调试实录与常见问题排查
5.1 仿真不收敛检查清单
调试中遇到发散的情况,按这个顺序查:
第一查离散步长。观测器的欧拉积分对步长敏感,Ts太大容易不稳定。控制周期10kHz,仿真步长别超过1e-5,否则观测器离散误差累积起来,磁链漂移快得离谱。
第二查归一化死区。如果磁链幅值持续被投影修正,说明电压模型里有系统偏差。常见原因是电阻参数没对准,或者反电动势幅值不匹配。别急着改死区,先回头核对电机参数。
第三查初始角一致性。FOC启动用的初始角和观测器的初始磁链赋值必须是同一个角度,差一点没关系,差多了启动瞬间就崩。我在代码里把这个角度做成一个全局参数,切换时保证同步更新。
还有一个常见问题:位置估计角度震荡,转速信号在零附近来回跳。这个多半是λ_0开太大,电流噪声被放大进磁链了。把λ_0压到0.5以下,再看波形。
5.2 观测器参数整定心得
给一组经验值作为起点:λ_0取0.3到0.8,k_λ取2到5,归一化死区5%,速度低通系数lp f_alpha对应截止频率200Hz。具体怎么调?先把电机卡在一个固定转速(比如额定20%)开环运行,观测器只输出不参与控制,调λ_0直到角度波形光滑无毛刺。然后放开到额定速度,调k_λ,直到高速段角度滞后不再依赖转速。最后回到零速启动,看切换瞬间电流有没有冲击,有就调慢角度斜坡。
需要提醒的是,lambda自适应的分母里omega_rated的归一化不是必须的,直接让λ跟|ω̂_e|线性增长也行,但那样转速越高噪声越大,效果反而差。归一化到额定转速之后,k_λ的物理意义更清楚:满速时额外增加多少增益,调起来直观多了。
5.3 从仿真走向实机的注意事项
仿真跑通只是第一步,实机上坑更多。我总结三条最重要的。
电流采样的对齐和噪声是第一位。观测器方程里i_α、i_β直接参与反馈,采样延迟或者噪声都会直接变成磁链误差。实机调试一定先确认电流采样零点和对齐正确,再调观测器。否则磁链观测值里面全是噪声,归一化死区根本兜不住。
逆变器死区补偿不能省。低速工况下垂区效应显著,u_α、u_β的参考值和实际输出电压差了一个死区电压矢量。不补偿的话,电压模型算出来的磁链会有恒定偏置,转速越低影响越明显。我的做法是加一个简单的死区前馈补偿,按电流极性修正电压指令。
最后是角度切换的工程实现。仿真里斜坡插值很优雅,但实机切换时要保证切换期间电流环不饱和,一旦饱和,切换逻辑会被电流限幅打得乱七八糟。我的经验是:切换前先确认电流已经稳定在轻载水平,再进行角度斜坡过渡,过渡完成后把电流环积分器清零重来,避免切换瞬间的积分饱和把PI输出顶到限幅上。
这套东西调试到后面,你会发现最难的不是观测器本身,而是启动瞬间那几十毫秒的状态配合。初始辨识、电流环启动、观测器初值、切换时序,任何一环脱节都会前功尽弃。但也正因如此,跑通之后的成就感是单纯调PID给不了的。
最后分享个小技巧:调试的时候把观测器估计角度和真实角度同时挂到Scope上,中间再画一条角度误差曲线,注意做角度归一到[-π, π]之后再看。我在模型里预留了这个观测通道,它比任何指示灯都直观,切换逻辑写得好不好,一眼就看出来。