简介:面向永磁同步电机无位置传感器控制场景,一套完整的滑模观测器(SMO)文档与算法源码,适合电机驱动开发者、相关专业学生以及研习德州仪器嵌入式平台的工程师,用于解决转子位置和速度估计难题。压缩包共6个文件,包含2个C源文件、2个头文件、1个Simulink仿真模型和1份PDF技术文档,整体仅238KB,体积小巧、结构清晰。PDF文档从观测器基本原理讲起,覆盖滑动变量与边界层设计、PMSM直交轴电磁力矩方程、SMO参数选择与稳定性分析,并给出离散化流程和抖振抑制方法,结合实验结果对比帮助从理论过渡到工程实现。平台源码与所附仿真模型可直接配合,用于仿真验证和代码移植,工程人员可在此基础上快速验证算法效果,为提升控制精度与鲁棒性提供可落地的参考。目前已有432人学习下载,无论入门还是进阶,都是系统掌握SMO并快速上手的实用资料。 前阵子接手一个电动工具项目,客户要求把霍尔传感器去掉。原因很现实:高温高振动工况下,霍尔要么退磁要么断引脚,售后换回来的板子一大半都是传感器损坏。于是我把尘封的“永磁电机滑模观测SMO文档及算法源码”翻了出来,一边读文档一边对着C源码逐行核,花了三个晚上把整套无感FOC方案跑通。这个资料包的价值在于,它不是那种只有公式没有代码的PPT式文档,也不是只有晦涩注释没有推导的裸代码,而是把“为什么这么做”和“代码怎么落地”对齐了。这篇文章就把我对这份文档和源码的核心拆解记录下来,围绕的正是无感控制里最经典的滑模观测器SMO,以及网上很多人问的电压极限圆和电流极限圆对观测器的影响。
1. 为什么这份SMO文档值得从头读一遍
1.1 无感FOC的工程背景
永磁同步电机要做磁场定向控制,绕不开转子位置。过去最省事的办法是装霍尔或者编码器,但工程上总有装不了、装不起、装上去容易坏的情况。高温、油污、振动、成本敏感,每个理由都足以让人放弃传感器。滑模观测器属于反电动势观测法的一种,它通过电机的电压方程和电流采样,把反电动势估计出来,再反向解出转子磁极位置和转速。
这里必须说清楚一个适用边界:反电动势的幅值与转速成正比,转速越低信号越弱,所以SMO天生适合中高速段。零速和极低速下,反电动势淹没在噪声和死区非线性里,SMO基本无能为力。文档里明确写了目标工况是额定转速的10%以上,低于这个范围,要配合I/F强拉启动或者其他注入方法。很多做项目的人看到SMO就说“无感”,默认它能从零速跑到高速,其实这是最大的误解。
1.2 文档和源码的配合方式
这份资料包里,文档一共有五章,源码是按模块拆分的C文件。文档第一章讲电机模型和坐标系变换,第二章推导滑模观测器方程,第三章讲离散化实现,第四章讲参数整定,第五章是实验波形。真正有价值的不是公式本身,而是每一处近似都标注了“为什么可以这样近似”。
比如文档里反复强调:SMO设计用的是αβ静止坐标系下的电流方程,而不是旋转坐标系下的方程。原因是静止坐标系下反电动势包含位置信息,而旋转坐标系下位置信息被变换矩阵吃掉了。这种“文档讲物理意义,源码讲实现细节”的配合方式,适合边看边敲,不能只看其中一半。
2. 滑模观测器原理中容易被代码掩盖的两个反直觉点
2.1 滑模面不是用来“收敛”的,而是用来“保持”的
很多初学者容易把滑模观测器理解成一种PID形式的电流估计器,觉得目标是让估计电流逐渐逼近实际电流。这个理解不能说全错,但它错过了最核心的机制。SMO的控制目标不是让电流误差最小化,而是让系统状态被“强制”到滑模面上,并在滑模面上保持高频切换运动。
PMSM在αβ坐标系下的电压方程可以写成:
L * d/dt(i) = u - R*i - e其中,L为相电感,R为相电阻,u为外加电压,e为反电动势。常规做法是把e当作扰动,用滑模控制项去补偿它。构造一个估计电流方程:
L * d/dt(i_hat) = u - R*i_hat - K*sat(i_hat - i)这里K是滑模增益,sat是饱和函数。用估计电流减去实际电流得到滑模面 s = i_hat - i。当系统进入滑模状态后,等效控制量里就包含了反电动势信息。
反直觉的地方在于:滑模控制器的输出是高频切换量,它本质上不是“把误差算小”,而是“用足够大的增益把误差压到零附近来回振荡”。这个振荡频率在理想情况下是无穷大,实际数字实现里受采样频率限制,表现为抖振。抖振是SMO的固有数学特征,不是算法bug。源码里用饱和函数替代理想符号函数,就是为了把抖振控制在一个可接受的边界层内。
2.2 低通滤波器是为了消除抖振,但代价是相位滞后
滑模控制项里包含反电动势信息,但它混在高频切换分量里。提取它的标准做法是加低通滤波器。源码里是一阶低通:
e_alpha_lpf += lpf_coeff * (e_alpha_raw - e_alpha_lpf);这个滤波器把高频抖振滤掉,留下近似等效反电动势。但代价非常直接:低通滤波器会给反电动势引入相位滞后,滞后角度与电频率成正比。如果不做补偿,位置估计就会偏一个固定角度,直接导致负载能力下降,甚至带载失步。
文档里给出的工程经验是:滤波器转折频率取电机额定电频率的3到5倍。取低了,反电动势被衰减得厉害,相位滞后巨大;取高了,抖振滤不干净,PLL输入噪声很大。这个参数没有万能值,必须结合载频和转速范围来试。
3. 源码实现逐行拆解:从电流观测到角度输出
3.1 离散化的电流观测器
文档第二章推导的是连续域方程,但控制代码跑在MCU里,必须离散化。源码用的是最简单的前向欧拉法,因为电流环采样周期足够短,在10kHz甚至20kHz的载频下,前向欧拉的误差可以忽略。
核心代码可以简化为:
#define TS 0.0001f // 采样周期 10kHz #define RS 0.55f // 定子电阻 #define LS 0.0016f // 定子电感 float i_alpha_hat, i_beta_hat; float e_alpha_raw, e_beta_raw; void smo_current_observer(float u_alpha, float u_beta, float i_alpha, float i_beta) { float s_alpha = i_alpha_hat - i_alpha; float s_beta = i_beta_hat - i_beta; float v_alpha = smc_gain * sat(s_alpha, smc_epsilon); float v_beta = smc_gain * sat(s_beta, smc_epsilon); e_alpha_raw = v_alpha; e_beta_raw = v_beta; i_alpha_hat += (u_alpha - RS * i_alpha_hat - v_alpha) * (TS / LS); i_beta_hat += (u_beta - RS * i_beta_hat - v_beta) * (TS / LS); }这里面有一个容易忽略的细节:代码里用的是i_alpha_hat而不是i_alpha来算电阻压降。这其实是用估计电流做状态递推,而不是用实际电流做校正。这样做的原因是防止微分噪声被放大。实际电流只出现在滑模面的误差项里,这个误差项会被饱和函数限幅,因此噪声不会直接冲击微分环节。
如果这里不小心用了i_alpha,会发现电流观测波形上有明显的锯齿噪声,尤其是在电流斩波比较深的时候。我当时排查了整整一个下午,最后逐行对照文档才发现是这个隐藏的反馈源选错了。
3.2 饱和函数与边界层厚度
理想滑模用符号函数sign,但工程实现必须用饱和函数sat(s/ε)。ε就是边界层厚度。代码实现:
float sat(float x, float eps) { if (x > eps) return 1.0f; if (x < -eps) return -1.0f; return x / eps; }ε的取值直接影响两个矛盾:ε太小,滑模增益在误差零点附近变化过于剧烈,等效控制量高次谐波多,反电动势波形毛刺明显;ε太大,滑模控制退化为线性比例控制,SMO抗扰动优势消失,反电动势估计出现幅度衰减和相位延迟。
从文档的实验数据看,ε取额定电流标幺值的0.05到0.2是一个合理区间。但这里的“标幺值”很关键,源码内部默认电流基值是逆变器峰值输出电流,如果移植到别的项目,基值变了,ε也要跟着换算,否则光调一个ε就能折腾好几天。
3.3 PLL锁相环解算角度
提取到反电动势之后,角度解算有两种常见方式:直接atan2,或者PLL锁相。源码选的是PLL,原因在于atan2对噪声极其敏感,而PLL本身就是一个低通性质的闭环,解算出的角度平滑得多。
反电动势与转子磁链方向的关系是垂直的,两个分量可以写成:
e_alpha = -psi_f * omega_e * sin(theta_e) e_beta = psi_f * omega_e * cos(theta_e)其中psi_f为永磁磁链,omega_e为电角速度,theta_e为电角度。PLL的基本思想是构造一个误差项:
float err = -e_alpha * cos(theta_hat) - e_beta * sin(theta_hat);这个误差在角度估计值逼近真实值时趋近于零。误差进PI控制器,输出电角速度,再对电角速度积分得到角度:
speed_hat = pi_pll.update(err); theta_hat += speed_hat * TS;需要注意PI控制器极性。文档特意标注了:反电动势定义方向不同,误差公式的正负号必须相应调整。我在DSP上第一个版本直接把文档里的C代码复制过来,结果PLL变成正反馈,角度发散到飞起。排查到最后发现是电流采样方向定义和文档不一致,导致反电动势符号整体反转。
3.4 低速启动切换逻辑
源码里有一块状态机,处理零低速到中高速的过渡:
typedef enum { STATE_IF_START, STATE_CLOSE_LOOP, STATE_FAULT } smo_state_t;启动阶段用I/F强拉方式,即定子电流矢量以设定频率旋转,不管实际转子位置,先把转子带起来。当反电动势幅值超过阈值,并且PLL角度误差连续一段时间保持在小范围内,才切换到SMO闭环。
这里面的工程细节是切换瞬间的角度衔接。I/F模式下的给定角度和SMO估计角度之间可能存在偏差,直接切换会造成电流跳变。源码里的处理办法是:切换前把电流环积分器清零,同时把PLL输出角度强制拉平到I/F的给定角度,用两个电周期做软过渡,电流波形才不炸。
4. 实机调试中的波形与参数坑
4.1 滑模增益过大的表现
滑模增益K的作用是保证滑模面的可达性,理论上必须大于反电动势的最大幅值。但工程上有一个常见倾向:为了确保各种工况下都能进入滑模,把K调得很大,结果电流误差波形出现高密度毛刺,反电动势波形抖成“刺猬”。
我实测下来,K过大时最典型的现象是:空载电流波形还行,带上负载后相电流出现明显的脉冲状噪声,噪声频点集中在开关频率附近。这是因为过大的K让饱和函数经常工作在饱和区,等效控制量的占空比调制噪声被放大。
判断K是否合适的土办法:在额定速度下,把示波器探头夹在DAC输出的反电动势观测通道上,调节K值从小到大。刚开始反电动势幅值随K增大而增大,等K超过反电动势峰值后,再增大K只会让波形上的毛刺越来越多,幅值基本不变。那么这个拐点就是K的最小合理值,再留1.3到1.5倍裕量就够用了。
4.2 滤波器和PLL带宽的配合
这个坑非常隐蔽,而且最让人头疼。单独调低通滤波器或者单独调PLL带宽,都没有问题,两个参数一叠加,高速段角度波动明显。
原因是:低通滤波器在转折频率附近有相位突变,而PLL如果带宽太宽,会把这些相位畸变转化为角度振荡。文档给出的整定顺序是:先定低通滤波器转折频率,再按转折频率的1/5到1/3来定PLL带宽。实测下来,PLL带宽取20到50Hz,LPF转折频率取80到150Hz(电频率)是比较稳的组合。
如果发现高速段角度噪声偏大,先做角度动态补偿,而不是盲目降PLL带宽。补偿公式是:
theta_comp = theta_hat + atan(omega_e / omega_cut)这个公式补偿的是低通滤波器的相位滞后。注意omega_e是电角速度,omega_cut是滤波器转折角频率。转速变化时这个补偿角要实时更新,不能用一个固定角度硬补,否则中低速过补偿,高速欠补偿,反而更差。
4.3 电压极限圆与电流极限圆对观测器的影响
这部分是最近不少人在讨论的热点,其实它和SMO的关系非常直接。电流极限圆和电压极限圆是电机驱动系统在dq平面上的两个运行约束边界,它们不只是弱磁控制的话题,更直接决定了SMO在哪些工作点会失效。
电流极限圆由逆变器和电机的电流承受能力决定,表达式是:
id^2 + iq^2 <= Imax^2电压极限圆由直流母线电压和转速决定,表达式是:
(Ld*id + psi_f)^2 + (Lq*iq)^2 <= (Umax / omega_e)^2这个式子看起来是弱磁控制的公式,实际上和SMO的边界条件深度绑定。SMO滑模增益K必须大于反电动势幅值,而反电动势幅值本质上受限于电压极限圆。当转速升高到电压极限圆收紧之后,外加电压u已经接近饱和,此时电压方程里用于抵消反电动势的余量就不足了,滑模控制量进入深度饱和区,等效反电动势提取精度急剧下降。
我在样机上调高速段时遇到过这种情况:电机在3000rpm以下一切正常,一旦拉到4000rpm以上,轻载没问题,稍微带一点负载,SMO估计角度就开始抖动,紧接着相电流畸变,最终触发过流。
回看数据,问题恰恰出在电压极限圆上。4000rpm时反电动势已经接近母线电压能提供的最大值,PWM处于过调制边缘,SMO的输入电压谐波巨大,把反电动势观测波形给污染了。解决方式不是去调K或者滤波器,而是主动限制弱磁区的最大输出电流和最高转速,保证电压余量不低于额定值的15%。
这里分享一个调试经验:调试高速稳定性和SMO参数之前,先计算一下电流极限圆和电压极限圆在当前工况下的交叠范围。如果运行点已经贴到电压极限圆外侧,再去纠结SMO的参数整定,基本是白费功夫,问题根源不在观测器,而在电压约束。先把运行点拉回两个极限圆的交叠区域内,再回头调SMO,才谈得上有意义。
5. 把这份代码用到自己项目中的几点建议
5.1 移植时的关键改动清单
从文档源码移植到自己的硬件平台,有几个地方最容易出问题。第一是标幺值基值,源码内部大量采用标幺值运算,如果基值定义不一致,所有PI参数、滑模增益、边界层阈值都要重新换算。第二是电流采样对齐,源码假设PWM中心对齐采样,实际硬件如果用了单电阻采样或者边沿对齐,电流噪声特性完全不同,必须重新调滤波器。第三是电感参数,源码里L用的是同步电感还是相电感,直接影响离散化系数的数值,电机不同,这个差异可能达到20%。
另外,强烈建议在代码里直接加入“反电动势幅值异常”和“角度误差过大”两个故障判据。前者可以捕获电机退磁或匝间短路,后者可以捕获SMO失步。这两个保护用不到太多代码量,但能避免绝大多数样机损坏事故。
5.2 后续可以往哪个方向扩展
如果项目要求零速跑满转矩,纯SMO是不现实的,但可以把SMO和高频注入做融合:零低速用高频注入观测凸极性,中高速切回SMO。这两者的平滑切换,是另一个大工程。更简单的扩展是给SMO加自适应增益,根据反电动势幅值实时调节滑模增益K,这样低速段不必为了高速段的抗扰动性而承受过大的抖振。
在我实际做过的项目里,先把SMO的中高速段调稳,永远是第一优先级。不要一上来就想做成全速域无感,先把1000rpm到3000rpm这个区间调到波形干净、带载不掉步,再考虑往两端扩展。这套思路在多个电机平台上验证下来,调试周期最短。
本文还有配套的精品资源,点击获取