4. 滑模观测器原理:基于反电动势的滑模观测器设计、低通滤波器与相位补偿
好,咱们进入正题。滑模观测器这东西,说白了就是给电机装个“虚拟传感器”。你想想看,我们做无感控制,最缺的就是转速和位置信息。直接装编码器?成本高、可靠性还打折扣。那怎么办?用数学模型去“观测”它。
我个人习惯把滑模观测器看作一个“纠偏器”。它不直接告诉你位置,而是通过观测反电动势,再反推出位置。为什么选滑模?因为它对参数变化不敏感,鲁棒性好。我在项目里遇到过电机参数随温度漂移的情况,用其他观测器早跑偏了,滑模愣是扛住了。
4.1 反电动势观测:滑模的核心思想
先回忆一下永磁同步电机的数学模型。在α-β坐标系下,电压方程长这样:
uα = Rs·iα + Ls·(diα/dt) - ωe·ψf·sin(θe)
uβ = Rs·iβ + Ls·(diβ/dt) + ωe·ψf·cos(θe)
注意看后面两项,那就是反电动势:
eα = -ωe·ψf·sin(θe)
eβ = ωe·ψf·cos(θe)
反电动势里藏着转速和位置信息。只要能把它观测出来,剩下的就是数学活了。
滑模观测器的思路是这样的:我们构造一个电流观测器,让它的输出与实际电流做差。这个差值经过滑模控制律(通常是符号函数),再反馈回去修正观测值。当系统进入滑模面后,这个修正量就等价于反电动势。
嗯,这里要注意:滑模观测器观测的是电流,反电动势是“副产品”。
核心公式:
滑模观测器方程:
dîα/dt = (1/Ls)·(uα - Rs·îα - k·sign(îα - iα))
dîβ/dt = (1/Ls)·(uβ - Rs·îβ - k·sign(îβ - iβ))
其中 k 是滑模增益,sign() 是符号函数。
当观测收敛后,滑模控制量 ≈ 反电动势:
zα ≈ eα
zβ ≈ eβ
我在调试时发现,k值选大了会有高频抖振,选小了又观测不准。这个平衡点,说白了就是经验活。
4.2 低通滤波器:抖振的克星
滑模控制有个天生的毛病——抖振。符号函数的开关动作会产生高频分量,直接拿这个信号去算位置,结果会抖得像筛糠一样。
怎么办?加低通滤波器。
我建议用一阶低通滤波器,简单可靠:
êα_filtered = êα / (τ·s + 1)
êβ_filtered = êβ / (τ·s + 1)
其中 τ 是滤波时间常数,s 是拉普拉斯算子。
离散化后(比如用一阶后向差分):
êα_filtered(k) = (T/(τ+T))·êα(k) + (τ/(τ+T))·êα_filtered(k-1)
这里 T 是采样周期。
| 参数 | 影响 | 我的建议 |
|---|---|---|
| τ 太小 | 滤波效果差,抖振残留 | 至少取采样周期的 5-10 倍 |
| τ 太大 | 相位滞后严重,位置估算不准 | 不要超过采样周期的 50 倍 |
我曾经在一个项目里把τ设得太大,结果电机低速运行时位置估算滞后了将近30度,电机直接抖起来了。后来把τ降下来,配合相位补偿才搞定。
注意:低通滤波器会引入相位滞后。滞后量大约为 arctan(ω·τ),其中 ω 是电角频率。转速越高,滞后越严重。如果不补偿,高速时位置估算误差会大到无法接受。
4.3 相位补偿:把丢掉的角度找回来
既然低通滤波器带来了相位滞后,那我们就得想办法补回来。说白了,就是估算出滞后角度,然后在最终的位置输出里加上去。
相位滞后角度可以这样估算:
Δθ = arctan(ωe·τ)
其中 ωe 是电角速度,τ 是滤波时间常数。
补偿后的位置:
θ_compensated = θ_estimated + Δθ
这里有个问题:ωe 本身也是估算出来的,存在误差。用有误差的转速去补偿相位,会不会越补越乱?
我的经验是:只要转速估算不是太离谱,这种补偿方式就有效。因为相位滞后是单调函数,补多补少都比不补强。
实用技巧:
我习惯在代码里做一个查表,把不同转速对应的补偿角度预先算好。运行时直接查表加补偿,省去实时计算 arctan 的开销。
比如:
// 预计算补偿表,转速范围 0-6000 rpm
for (int i = 0; i < TABLE_SIZE; i++) {
float w = i * 6000.0f / TABLE_SIZE * 2 * PI / 60;
compensation_table[i] = atan2(w * TAU, 1.0f);
}
4.4 完整的观测器流程
把上面这些串起来,一个完整的滑模观测器流程是这样的:
- 电流采样:采集三相电流,变换到 α-β 坐标系
- 滑模观测:用电流误差驱动滑模控制律,输出 zα、zβ
- 低通滤波:对 zα、zβ 进行滤波,得到平滑的反电动势估算
- 位置估算:用反正切函数从反电动势中提取角度
- 相位补偿:根据当前转速估算滞后角度,补偿到位置输出
- 转速估算:对位置求微分,或者用锁相环提取转速
代码实现大致长这样:
// 滑模观测器主循环
void smo_update(float u_alpha, float u_beta, float i_alpha, float i_beta) {
// 1. 电流观测
float di_alpha_hat = (u_alpha - Rs * i_alpha_hat - k * sign(i_alpha_hat - i_alpha)) / Ls;
float di_beta_hat = (u_beta - Rs * i_beta_hat - k * sign(i_beta_hat - i_beta)) / Ls;
i_alpha_hat += di_alpha_hat * Ts;
i_beta_hat += di_beta_hat * Ts;
// 2. 滑模控制量 = 反电动势
float z_alpha = k * sign(i_alpha_hat - i_alpha);
float z_beta = k * sign(i_beta_hat - i_beta);
// 3. 低通滤波
e_alpha_filtered = (Ts / (TAU + Ts)) * z_alpha + (TAU / (TAU + Ts)) * e_alpha_filtered;
e_beta_filtered = (Ts / (TAU + Ts)) * z_beta + (TAU / (TAU + Ts)) * e_beta_filtered;
// 4. 位置估算
float theta_estimated = atan2(-e_alpha_filtered, e_beta_filtered);
// 5. 相位补偿
float omega_estimated = (theta_estimated - theta_prev) / Ts;
float delta_theta = atan2(omega_estimated * TAU, 1.0f);
float theta_compensated = theta_estimated + delta_theta;
theta_prev = theta_estimated;
}
这段代码我实际用过,在 300-3000 rpm 范围内效果都不错。低速时反电动势信号弱,需要适当提高滑模增益 k。高速时注意相位补偿不要过冲。
避坑指南:
我曾经在调试时发现,电机空载和带载时反电动势幅值差很多。空载时反电动势小,滑模增益 k 需要调低,否则抖振严重。带载时反电动势大,k 要调高才能保证观测精度。
后来我做了个自适应 k 值:根据电流幅值动态调整滑模增益。效果好了不少。
好了,滑模观测器的原理就讲到这里。下一节我们会聊怎么用锁相环从反电动势里提取更平滑的转速和位置信号。那个方法比直接反正切要好用得多。