拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

无感FOC核心:龙伯格观测器原理与STM32实现详解

无感FOC核心:龙伯格观测器原理与STM32实现详解

无感FOC这几年被问得最多的一个问题,就是“没有编码器,转子位置到底怎么估?”电流环要坐标变换,坐标变换要角度,角度本身却是个未知数,这就成了个先有鸡还是先有蛋的死结。做有感的同学只需要读一下编码器,做无感的就得自己想办法把这个角度“算”出来,而算角度的核心,就是状态观测器。今天不扯滑模、不扯卡尔曼,集中把龙伯格观测器讲透——它怎么从电压电流里提取反电动势、怎么通过极点配置设计增益、怎么在STM32上写成能跑的代码,以及我在调试中踩过的那些坑。

这篇文章适合正在搞PMSM无感FOC但被观测器卡住的朋友,不管你是刚入门还是在调参阶段,看完应该能对“龙伯格观测器”这个东西建立起一个完整的画面:它为什么存在、数学上干了什么、代码上怎么落地、实际跑起来又会遇到哪些问题。

1. 为什么无感FOC绕不开观测器

1.1 无感控制的本质困难:位置藏在电气量里

FOC的整个逻辑链条是:采样电流,经过Clark变换得到αβ轴电流,再经过Park变换得到旋转坐标系下的dq轴电流,然后交给PI调节器去控制。可Park变换的角度从哪儿来?有编码器就简单了,编码器读数就是角度;无感系统里没有这个硬件,就只能从电机的电压和电流里推测转子位置。

关键线索在反电动势上。永磁同步电机转动时,转子磁钢会在定子绕组里感应出一个反电动势,这个反电动势的大小和转子的电气速度成正比,它的相位方向和转子位置直接相关。只要能从电压方程里把反电动势估出来,再用反正切或者锁相环把角度提出来,无感FOC的基本问题就解决了。

但这里有个麻烦:反电动势没法直接测量,它藏在电压和电流的关系里,而且和电阻压降、电感压降混在一起。直接微分会引入巨大噪声,低通滤波又会带来相位延迟。所以人们就想,能不能建立一个电机的数学模型,输入电压和电流,让模型自己去推算反电动势?这就是观测器的思路。龙伯格观测器就是这套思路里最直观、最经典的一种。

1.2 三种主流观测方案对比

无感FOC里常见的观测方案有三个:滑模观测器、扩展卡尔曼滤波、龙伯格观测器,另外还有模型参考自适应等变体。很多人一上来就听说滑模鲁棒性好、卡尔曼精度高,但实际用下来各有各的难受。

方案优点缺点适用场景
滑模观测器对参数变化不敏感,实现简单抖振明显,需要低通滤波,带来相位延迟,角度补偿麻烦中高速无感FOC,工业界用得最多
扩展卡尔曼噪声抑制出色,能同时估速度和位置计算量大,矩阵运算复杂,协方差矩阵调参门槛高对精度要求高的场合,但实时性压力大
龙伯格观测器结构简单、物理意义清晰,增益设计直观,计算量很小对电阻电感参数敏感,零速低速失效中高速无感FOC,做学习研究和快速落地都很合适

龙伯格观测器的优势在于“透明”。每个变量是什么物理量、每个增益调大调小会有什么影响,你心里都能有数。不像卡尔曼那样一堆协方差矩阵调起来像玄学,也不像滑模那样要处理抖振。对于想搞懂观测器本质、或者想在STM32这类MCU上快速跑起来的人,龙伯格是绝佳的切入点。

1.3 龙伯格观测器的核心思想:模型预测加实时纠偏

龙伯格观测器这个名字听起来高大上,原理其实非常朴素。想象你开车去一个地方,手机导航的路线是地图模型推算出来的,但如果中途堵车或者你走错路,导航会结合实时路况不断修正路线。观测器干的就是这件事:一方面用电机的数学模型去预测电流和反电动势,另一方面用实际采样的电流去和预测值做比较,把误差反馈回去修正预测,最终让反电动势估计值收敛到真实值附近。

用数学语言说就是:系统状态方程是dx/dt = Ax + Bu,我们只测得到输出y(电流),测不到内部状态(反电动势),于是构造一个观测器:dx_hat/dt = Ax_hat + Bu + L(y - y_hat)。其中L是增益矩阵,它决定了误差纠偏的速度。这个结构简单得惊人,但背后有一个非常重要的性质——如果L设计得当,估计误差会以可控的速度衰减到零,这就是龙伯格观测器能用的根本保证。

2. 龙伯格观测器的数学基础与设计要点

2.1 PMSM在αβ坐标系下的状态空间模型

设计观测器之前,得先把电机的数学模型写出来。在静止的αβ坐标系下,PMSM的电压方程可以写成:

uα = R*iα + L*diα/dt + eα uβ = R*iβ + L*diβ/dt + eβ

这里的eα和eβ就是反电动势在αβ轴上的分量,它们的表达式是:

eα = -ψf * ωe * sin(θe) eβ = ψf * ωe * cos(θe)

其中ψf是永磁体磁链,ωe是电气角速度,θe是转子电角度。看到了吧,反电动势的相位直接携带转子位置信息,把eα和eβ算出来,位置信息就到手了。

把电流和反电动势都作为状态变量,可以得到一个增广状态方程。假设在一个控制周期内转速基本不变,也就是dωe/dt≈0,那反电动势的导数约等于零。于是状态方程可以整理成:

d/dt [iα, iβ, eα, eβ]^T = A * [iα, iβ, eα, eβ]^T + B * [uα, uβ]^T

这其实是一个四阶线性系统。之所以能把反电动势当作慢变量放进状态里,根本原因是电气时间常数远小于机械时间常数,转子速度和位置在一个PWM周期内的变化微乎其微。这个假设在电机控制里几乎总是成立的,也是龙伯格观测器能做下去的前提。

2.2 观测器方程的重构与增益设计

观测器方程就直接在模型后面加反馈校正项:

d/dt iα_hat = (-R*iα_hat + uα - eα_hat) / L + L1 * (iα - iα_hat) d/dt iβ_hat = (-R*iβ_hat + uβ - eβ_hat) / L + L1 * (iβ - iβ_hat) d/dt eα_hat = L2 * (iα - iα_hat) d/dt eβ_hat = L2 * (iβ - iβ_hat)

其中L1是对电流误差的反馈增益,L2是对反电动势误差的反馈增益。定义电流估计误差和反电动势估计误差,代入方程后可以得到误差动态方程,它是一个二阶系统。为了让误差收敛速度可控,通常把两个极点都配置在左半平面,并且让它们和电气速度相关。

最常见的做法是把极点配置在s = -kωe ± jωe附近,这样算出来的增益是:

L1 = 2*k*ωe L2 = k^2 * ωe^2 * L

这个形式有个好处:观测器的带宽会跟着转速走,低速时带宽低、噪声抑制好,高速时带宽高、响应快,正好匹配反电动势幅值随转速增大的特点。k通常取1到2之间,太大则噪声放大明显,太小则收敛慢,高速时跟不上位置变化。

这里特别强调一个工程细节:如果前期不想搞太复杂,L1和L2也可以先用固定值,选取时按额定转速下期望的收敛带宽作为基准来算。固定增益的好处是调试简单,代价是高速性能略差。我自己调试时习惯先用固定增益跑通整个链路,再慢慢换成随转速变化的增益。

2.3 离散化与采样周期选择

代码里没法直接算微分方程,得离散化。最常用也最简单的是一阶前向欧拉法:

x[k+1] = x[k] + Ts * f(x[k], u[k])

套到观测器方程里,每个控制周期依次更新电流估计和反电动势估计。离散化的精度取决于采样周期Ts,采样周期又由PWM开关频率决定。比如10kHz的开关频率下Ts=100μs,一个基波周期20ms内有200个采样点,精度就完全够用。如果开关频率是8kHz,对应125μs,也还在合理范围内。

要提醒的是,代码里电流采样、坐标变换、观测器更新、PI调节器、PWM更新这些步骤必须严格按顺序执行,而且整个过程要在一次PWM中断里完成,保证所有数据对应同一个时间点。我自己见过一个案例,因为代码里先算观测器后更新PWM,导致观测器用的电压是上一个周期的,低速时问题不大,高速时角度就飘了。

2.4 角度提取与速度估算

反电动势估出来了,角度提取就是一锤子买卖。用反正切函数:

θe_hat = atan2(-eα_hat, eβ_hat)

注意符号,不同公式推导出来的反电动势方向定义可能不同,最终角度差90度或者反号,这是新手最容易懵的地方,后面会细说。反正切算出来的角度范围是[-π, π],需要做角度归一化处理,保证角度连续变化,不然运算时就会出现跳变导致的抖动。

速度估算有两种常见办法。一种是对角度做差分,然后滤一下波,简单但噪声大;另一种是把观测器输出交给一个锁相环,用PI调节器去跟踪角度变化,输出就是速度,而且天然带滤波效果。实际工程里我更推荐第二种,锁相环带宽调好之后,角度平滑、速度干净,后续做速度环会舒服很多。

还有一个容易被忽略的问题:延迟补偿。从PWM更新到电流采样,中间存在硬件延迟和滤波延迟,这会让观测器输出的角度滞后于真实位置。高速时这个滞后尤其明显,必须补偿。补偿量很简单:

θ_comp = θe_hat + ωe_hat * τ_delay

τ_delay通常是半个PWM周期加上电流滤波器的群延迟,具体数值要结合实际链条测量,不是拍脑袋定的。

3. STM32工程实践:龙伯格观测器的代码落地

3.1 数据结构与初始化

代码层面,第一步是把观测器要用到的变量封装成一个结构体。这样做的好处是,多个电机或者要切换不同电机参数时,只需初始化不同的结构体实例。一个典型的观测器结构体长这样:

typedef struct { float Rs; // 定子电阻 float Ls; // 定子电感 float Ts; // 采样周期 float L1; // 电流误差增益 float L2; // 反电动势误差增益 float ialpha_hat; // α轴电流估计 float ibeta_hat; // β轴电流估计 float ealpha_hat; // α轴反电动势估计 float ebeta_hat; // β轴反电动势估计 float theta_hat; // 估算电角度 float omega_hat; // 估算电气角速度 } LuenbergerObserver;

初始化的时候,电流估计和反电动势估计都置零,角度从0开始。注意一点:如果电机带着初始位置启动,一上电观测器感知到的是零反电动势,而实际是有角度的,观测器会从零开始修正,这个收敛过程需要时间。这也是无感FOC普遍需要特殊启动策略的根本原因。

3.2 核心状态更新代码结构

观测器的核心更新函数长这样,我在注释里写清了每一步的物理含义:

void Luenberger_Update(LuenbergerObserver *obs, float ualpha, float ubeta, float ialpha, float ibeta) { float ialpha_err, ibeta_err; float ealpha_dot, ebeta_dot; float ialpha_dot, ibeta_dot; // 1. 计算电流估计误差 ialpha_err = ialpha - obs->ialpha_hat; ibeta_err = ibeta - obs->ibeta_hat; // 2. 更新反电动势估计值 // 反电动势的导数为反馈误差乘以L2 ealpha_dot = obs->L2 * ialpha_err; ebeta_dot = obs->L2 * ibeta_err; obs->ealpha_hat += obs->Ts * ealpha_dot; obs->ebeta_hat += obs->Ts * ebeta_dot; // 3. 更新电流估计值 // 电流的导数来自电压方程,再加上反馈校正项 ialpha_dot = (-obs->Rs * obs->ialpha_hat - obs->ealpha_hat + ualpha) / obs->Ls + obs->L1 * ialpha_err; ibeta_dot = (-obs->Rs * obs->ibeta_hat - obs->ebeta_hat + ubeta) / obs->Ls + obs->L1 * ibeta_err; obs->ialpha_hat += obs->Ts * ialpha_dot; obs->ibeta_hat += obs->Ts * ibeta_dot; // 4. 提取角度和速度 obs->theta_hat = atan2f(-obs->ealpha_hat, obs->ebeta_hat); // 速度估算可以通过角度差分 + 低通滤波,或者交给锁相环 }

这段代码看起来简单,但它是一个完整的、可运行的龙伯格观测器核心。实际项目里可以在此基础上加角度归一化、速度锁相环、延迟补偿等模块。调试的时候,我建议先把这段代码跑通,单独打印出ealpha_hat和ebeta_hat的波形,确认它们是相位相差90度的正弦波,再去做后续的位置和速度处理。

一个非常重要的顺序问题:观测器更新必须放在电流采样之后、PI调节器之前。因为PI调节器需要坐标变换,而坐标变换需要角度,观测器提供的角度必须新鲜。如果你把观测器放在PI之后运行,那就等于PI用的是上一拍的角度,这会直接导致dq轴电流解耦不干净,系统跑起来会莫名其妙地振荡。

3.3 参数整定的实操顺序

观测器参数无非两大类:电机参数Rs、Ls,以及观测器增益L1、L2。整定顺序应该先搞定电机参数,再调增益。

电机参数怎么来?最土的办法是电桥测电阻和电感,但实际运行中电阻会随温度变化,电感会随电流饱和变化。所以我建议在程序里预留参数在线辨识的接口,或者至少做离线辨识。离线辨识其实不复杂:给电机施加一个电压矢量,记录电流变化率,用电压方程反推Rs和Ls;再用一个旋转的电压矢量让电机匀速转起来,记录反电动势的幅值就能推出磁链。具体公式网上很多,这里不展开,但要强调一点:参数测不准,观测器再高级也白搭。

接下来调L1和L2。初始值怎么给?先预估一个额定电气频率,比如电机额定转速3000rpm,4对极,那电气频率是200Hz。再把k取1,那么L1=212π200≈2513,L2=1(2π200)²Ls。跑起来之后,用示波器看估算角度波形,调大k看角度是否跟得更紧、噪声是否变大,反复试直到找到合适的点。

调试观测器,强烈建议有一个编码器或者测速发电机做对照实验。给电机通一个小幅度的正弦电流让轴来回摆动,同时对比编码器角度和观测器角度。如果两者相差恒定角度,大概率是反电动势符号或延时问题;如果差值忽大忽小,大概率是增益不对或者电流采样有噪声。

3.4 与启动策略的配合:I/F开环启动与切换

龙伯格观测器有个硬伤:零速和极低速时反电动势几乎为零,位置信息不存在,观测器没法工作。所以无感FOC启动时普遍采用I/F开环强拉或者预定位加开环切换。

I/F开环启动的逻辑是:不管转子在哪,先给一个电流矢量把转子拉到一个已知位置,然后让电流矢量的相位以一定加速度旋转,带着转子转起来。在这个过程中观察估算反电动势的幅值,等转速高到反电动势足够大、观测器角度和实际角度基本同步之后,再切到闭环FOC。切换条件一般看三个量:转速是否达到阈值、反电动势幅值是否足够、当前角度误差是否在允许范围内。

这里有个小技巧:在开环阶段就让观测器保持运行,输入用开环给定的电压和实际采样的电流,让观测器的角度一直跟着转子跑。这样在切换的瞬间,观测器的输出角度已经接近真实值,不会有太大的冲击。我见过很多人把观测器在开环阶段停掉,切换时突然使能,结果角度跳变导致电流瞬间冲顶,直接触发过流保护。

4. 调试中常见问题与排查实录

4.1 转子初始位置检测与零速难题

正如前面讲的,零速下反电动势为零,观测器完全没有位置信息。要处理初始位置,有两条路:预定位和高频注入。

预定位最简单,直接给一个固定的电压矢量,让转子转到已知位置,然后把这个位置写入观测器作为初值。这个方法在负载不大、允许转子有少许转动的场合完全够用。但负载较大或者要求零速带载的场合,预定位就不行了,只能上高频注入。高频注入的原理是:向定子注入高频电压信号,利用凸极效应或者磁饱和效应,从高频电流响应中解调出转子位置。这条路线和龙伯格观测器是互补关系,低速用高频注入,中高速切回反电动势观测器。

对于做FOC入门的朋友,我建议先接受“零速要预定位”这个工程事实,先让整个系统跑起来,再去优化初始位置检测。

4.2 估算角度抖动与滤波取舍

角度抖动是调试中最常见的现象。抖动来源主要是电流采样噪声和PWM开关噪声,它们经过观测器后会反映在反电动势里,再经过atan2变成角度抖动。抖动的直观表现是电流波形毛刺多、电机噪音大、高速时还可能引发过流。

手段上,第一层是让电流采样尽量干净,采样时刻避开PWM开关边沿,用硬件滤波或过采样平均。第二层是对观测器输出做处理,可以加低通滤波器,但低通滤波会带来相位延迟,所以滤波带宽要权衡。第三层是让观测器带宽本身随转速自适应,低速时低带宽抑制噪声,高速时高带宽保持响应。这个我在2.2节讲过,工程上效果很显著。

还有一个容易被忽略的问题:角度提取用atan2而不是atan。atan2考虑了象限,能输出完整的[-π, π]范围,atan只有[-π/2, π/2],角度会翻折。用了atan之后观测器输出角度看起来像三角波,电流可能追不上真实角度,系统性能惨不忍睹。这种低级错误一定要避免。

4.3 高速下发散:参数失配与采样延迟

高速无感FOC跑飞,是另一个高频问题。现象往往是启动正常、中速正常,一到高速电流波形就开始发散,甚至过流报错。

第一类原因是参数失配。电机温度上来后电阻升高,电感可能因为磁饱和下降,观测器模型和实际系统的偏差变大,反电动势估计值出现偏移,角度跟着偏,系统就失控了。排查方法是:先让系统在固定转速下长时间运行,观察观测器角度和真实角度(如果有编码器)的误差随温度的变化趋势。如果误差随温度单调增加,基本可以锁定是电阻漂移。

第二类原因是采样延迟和高惯量下的相位滞后。高速时反电动势频率高,即便只有十几微秒的控制延迟,折算到电角度也可能是好几度,如果不做补偿,角度滞后会不断累积。解决方法是补偿延迟,或者反正在坐标变换里做角度补偿,这比调PI参数管用得多。补偿值理论上用半拍PWM周期加滤波器群延迟,工程上可以稍微调一下让角度误差最小。

第三类原因比较隐蔽:PWM占空比接近极限导致电压输出非线性。高速时反电动势接近母线电压,电压余量变小,PWM非线性畸变,观测器输入电压不准,估计偏差就出来了。这个阶段一般伴随弱磁控制,需要专门处理,普通无感FOC高速调试时可以先把转速上限设小一点,把系统跑稳再做扩展。

4.4 快速排查表

调试久了你会发现,很多问题有共性,整理成一个速查表能帮自己节省大量时间:

现象可能原因检查方法解决措施
角度估计值为恒定值不变反电动势符号反向对比编码器角度看相位关系修改反电动势公式中的符号定义
角度抖动剧烈电流采样噪声大看电流波形毛刺调整采样时刻、加滤波、降低观测器带宽
低速正常高速发散采样延迟未补偿对比编码器角度误差随转速变化增加角度延迟补偿,补偿量同步速增加
电机温度升高后性能下降电阻参数漂移热态和冷态对比角度误差加入电阻在线辨识或温度补偿
角度估算正确但电流控制不稳Park变换角度符号或偏移错误检查dq轴电流PI输出波形核对坐标变换公式符号约定
启动时切换冲击开环切闭环时角度跳变查看切换瞬间电流波形开环阶段保持观测器运行,提前同步角度

这张表不能解决所有问题,但能覆盖绝大多数初学者会遇到的坑。每次调试遇到新问题,建议追加到自己的记录里,慢慢就会形成一套自己的排查手册。

5. 一些来自实际调试的体会

最后聊点实操中得来的经验,这些东西文档里很少写。

第一个体会是:观测器调通的关键不在观测器本身,而在前级的电流采样质量和电压重构。我花在电流采样调理上的时间,比调观测器增益的时间多得多。采样电阻布局不合理、运放带宽不够、采样时刻选在开关边沿,这些都会让观测器输入信号含噪声,后面怎么调增益都是白搭。把硬件底子打好,观测器自然就好调了。

第二个体会是:先用编码器当“老师”,再让观测器独立工作。具体做法是,代码里同时启用编码器角度和观测器角度,但控制用的是编码器角度,观测器角度只用来对比。看着两个角度的误差曲线调参数,很快就能把增益和延迟补偿调到合理范围。等误差在可接受范围内,再把控制切换到观测器角度,这一步成功之后,整个系统的信心就建立起来了。我之前带人做项目,这个“老师和学生”的方法屡试不爽,效率比纯盲调高出一大截。

第三个体会是关于速度估算的。如果你要做的系统对速度动态响应要求高,那速度估算尽量不要用简单差分加滤波,建议上一个锁相环结构。锁相环输出角度平滑、速度噪声小,速度环跑起来会更稳。角度差分在低速时噪声尤其大,高速时又存在相位问题,体验真的不行。

龙伯格观测器的代码其实不难写,算法本身在教材里也就几页纸,难的是理解它背后的物理过程和工程约束。把电机模型、增益配置、离散化、延迟补偿这些环节逐个搞清楚,很多所谓“调参玄学”自然就变成了有理有据的调试步骤。希望这篇文章能帮你把这个东西打通。

返回列表