ARTICLE DETAIL

资讯详情

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

高频注入无感FOC零低速位置观测原理与工程实现

高频注入无感FOC零低速位置观测原理与工程实现 做无感FOC的兄弟都有这个体会中高速一切好说滑模观测器、龙贝格观测器随便挑一个都能跑得很欢。但速度一掉到额定转速的5%以下尤其完全静止那一下反电动势直接变成零观测器瞬间抓瞎电机不是在启动时抖两下就是带载直接失步。高频注入无感FOCHFIHigh Frequency Injection就是专门来解决这一段的原理不复杂但工程实现里有一堆容易被代码细节坑住的地方。这篇东西我打算从代码层面把高频注入的完整链路拆开从高频信号怎么生成、IIR滤波怎么解调、位置误差怎么收敛到磁极极性怎么判断把每一步的代码逻辑和背后的工程考量都讲清楚适合手里已经有FOC基础、但还没把零低速无感搞明白的朋友参考。1. 零低速无感FOC的痛点为什么滑模观测器在这里失效1.1 反电动势信号在零速下直接消失滑模观测器、龙贝格观测器这一类方法本质上都是从反电动势BEMF里提取转子位置信息。永磁同步电机的反电动势表达式是E Ke * ωm转速越低反电动势幅值越小到了零速反电动势就是零。观测器全靠输入信号活着输入为零的时候观测器就算数学上再稳定输出也是白搭——就像在完全没光的黑屋子里让人找东西唯一的办法是自己打个手电筒去照。高频注入就是这支手电筒自己主动往电机里打一个高频激励信号再从电流响应里把位置信息捞出来。这也是为什么项目里无感FOC 滑模观测器这一套配置跑起来顺风顺水一旦做启动、堵转、低速爬行就原形毕露。我碰到不止一个项目中高速测试全部通过最后死在零速带载启动这一关。所以只要你的工况涵盖零速、极低速比如电动工具、伺服抱闸后的再启动、压缩机低频运行就必须在观测器方案之外再补一套高频注入。1.2 凸极性高频注入得以成立的前提高频注入能工作的前提是电机的定子电感随转子位置变化。内嵌式永磁同步电机IPMSM天然有这个特性d轴电感Ld和q轴电感Lq不相等典型的内嵌式电机Ld可能只有Lq的一半到七成。转子转到不同角度时从定子看进去的等效电感会呈周期变化这个特征叫凸极性saliency。高频注入就是不停用高频电压去试探电感分布通过测量电流响应来判断转子转到哪了。表贴式永磁电机SPMSM比较尴尬d、q电感接近相等凸极率接近1理论上高频注入的误差信号趋近于零。实际项目里遇到表贴电机还要做HFI就得靠磁饱和制造一个等效凸极出来或者用饱和造成的电感二次谐波来检测但那个信号更弱对采样和滤波的要求更高。所以做高频注入最好先确认电机铭牌或测试报告里的Ld、Lq数据凸极率低于1.3的电机工程上做HFI会非常痛苦。2. 高频注入系统的整体信号链路从PWM中断到位置输出的代码骨架2.1 信号流的宏观视图高频注入无感FOC并不是一个孤立的功能块而是嵌在传统FOC电流环里的一个信号支路。我把整条链路按数据流方向捋一下后面每段代码都能对应到这里PWM定时器触发中断进入电流采样和FOC运算周期电流环PI输出d、q轴电压指令在估算d轴电压上叠加高频余弦电压分量经过IPark变换后输出到PWM三相电流采样后做Clarke变换再做Park变换得到估算dq轴电流i_d_est、i_q_esti_q_est经过带通滤波提取出高频电流响应分量高频电流分量与参考高频信号做同步解调相乘再经过低通滤波得到位置误差信号位置误差信号送入锁相环PLL输出估算转速和估算角度启动阶段再做一次磁极极性判断必要时把估算角翻转180°。这就是一个完整的HFI闭环。注意这里面电流环本身还正常在工作高频注入只是叠加在电流环输出电压之上的一个扰动信号电流环不需要改动太多主要增加的是信号提取和位置观测那一串。2.2 中断处理函数的代码骨架看代码比看框图更直观。下面是一个典型的20kHz PWM中断里和HFI相关的调用顺序我把和HFI无关的电流环细节省略掉只看主干void pwm_isr(void) { // 1. 采样相电流Clarke变换 abc_to_clarke(i_alpha, i_beta); // 2. 使用上次估算角做Park变换 park_transform(theta_est, i_alpha, i_beta, i_d_est, i_q_est); // 3. 电流环PI计算得到基波电压指令 vd_base, vq_base current_loop_pi(i_d_ref, i_q_ref, i_d_est, i_q_est, vd_base, vq_base); // 4. 高频注入更新高频相位叠加到估算d轴 hf_theta HF_PHASE_INC; if (hf_theta TWO_PI) hf_theta - TWO_PI; float hf_cos cosf(hf_theta); float vd_ref vd_base HF_INJ_AMPL * hf_cos; float vq_ref vq_base; // 脉振注入只在估算d轴加 // 5. 转子位置观测HFI信号处理 hfi_position_observer(i_d_est, i_q_est, hf_theta, vd_ref, vq_ref); // 6. IPark变换并更新PWM比较寄存器 ipark_transform(theta_est, vd_ref, vq_ref, v_alpha_ref, v_beta_ref); update_pwm(v_alpha_ref, v_beta_ref); }观测器函数里装的就是滤波、解调、PLL那一串东西后面几节逐个拆开讲。有一点要提醒hf_theta的累加必须放在PWM中断里保证高频信号与PWM载波严格同步。如果把高频相位放在慢速任务或者和PWM不同步的定时器里更新解调的参考信号和实际注入信号之间会出现随机相位漂移位置误差信号会严重畸变而且这种畸变很难排查。3. 高频电压注入的生成细节叠加位置、频率选择与死区问题3.1 脉振高频电压生成代码高频注入有两种主流方式旋转高频注入和脉振高频注入。旋转注入是在静止αβ坐标系里注入一个旋转高频电压矢量脉振注入是在估算d轴方向注入一个余弦高频电压。从工程实现角度脉振注入解调逻辑更直观代码也更省所以我这里用脉振注入来讲。生成高频电压本身不复杂核心就三行#define HF_INJ_FREQ 800.0f // 注入频率 800Hz #define PWM_FREQ 20000.0f // PWM频率 20kHz #define HF_INJ_AMPL 5.0f // 注入电压幅值 5V48V母线约10% hf_theta TWO_PI * HF_INJ_FREQ / PWM_FREQ; if (hf_theta TWO_PI) hf_theta - TWO_PI; vd_ref HF_INJ_AMPL * cosf(hf_theta);高频频率800HzPWM频率20kHz意味着一个高频周期里有25个采样点离散化精度足够。为什么选800Hz而不是更高或更低下面细说。3.2 注入频率和幅值怎么定注入频率不是拍脑袋定的有三个约束条件一是必须远高于基波最大电频率。电机最高转速对应的电频率是基波频率高频注入信号必须明显高于它才能通过滤波分离。比如极对数4、最高转速3000rpm电频率200Hz注入频率取800Hz中间留出4倍的间隔带通滤波器才能把基波和高频分开。如果注入频率只比基波高一倍滤波器设计就很难看了。二是必须低于PWM采样频率的1/2要留足奈奎斯特余量。20kHz采样注入频率800Hz占比只有4%离散误差很小。有一些项目为了省MCU算力把注入频率提高到2kHz、采样频率10kHz高频周期里只有5个点波形离散误差会明显变大解调出来的误差信号噪声也高。三是最好和电流环带宽拉开距离。如果电流环带宽本身有1kHz你在800Hz注入高频分量会被电流环PI当作干扰强行压制注入电流响应很小信噪比会很差。所以通常注入频率要明显高于电流环带宽或者保证电流环输出端不处理这个频率成分只是脉宽调制正常输出。注入幅值的选择同样有讲究。幅值太小电流响应淹没在采样噪声和死区谐波里幅值太大会带来可听见的啸叫、转矩脉动和额外损耗。工程上一般取母线电压的5%到15%。48V母线我常用5V左右实际测试下来解调信号信噪比可以接受电机啸叫声也不算刺耳。母线电压越高比例可以适当降低一点400V大功率系统注入幅值比例过高损耗和噪声都扛不住。3.3 死区时间对高频注入的影响高频注入信号幅值本来就不大死区时间造成的误差电压在这种量级下影响会被放大。死区效应本质是一个方波扰动幅值和母线电压、死区时间、电流极性有关谐波成分非常丰富其中一部分正好落在注入频率附近直接污染高频电流响应。拿48V系统举例死区时间2μs在20kHz斩波周期里占空比损失可能达到4%对应的误差电压接近2V。而我的注入电压只有5V死区带来的干扰占相当大比例。如果不解调信号波形你不会觉得有问题一旦把带通滤波后的电流和参考信号相乘那些和注入频率相近的谐波会直接被解调到低频段变成位置误差信号上的纹波甚至偏置。解决思路有两个层面第一是硬件上尽量选择死区时间短、开通关断对称的驱动器第二是软件里加死区补偿至少做一个基于电流极性的电压修正。我实际做HFI项目的经验是没有死区补偿的HFI位置误差信号里会有明显的2倍电频率扰动噪声静止状态下还好一转起来就露馅。把死区补偿加上后那个2倍频纹波立刻小一个量级。4. IIR滤波器在同步解调中的角色与实现4.1 信号里到底藏着什么先想清楚一个问题电流环采样得到的i_q_est里有几路信号叠加在一起。基波电流是主要的可能有几十安高频注入产生的电流响应只有基波的百分之几到十几还叠加了PWM开关噪声和死区谐波。位置信息恰恰藏在那一点微弱的高频响应幅值里不滤波根本没法用。所以HFI信号处理的第一步是把i_q_est里的高频分量提取出来滤掉基波和大部分开关噪声。工程上常用一个带通滤波器中心频率放在注入频率附近。实现带通至少有三种路径直接设计一个IIR带通用一阶高通和一阶低通串联用陷波器。我倾向用一阶高通和一阶低通串联两级一阶IIR代码量极小参数直观调试时还能把中间量拉出来看波形性价比很高。4.2 一阶IIR滤波器的系数设计与代码一阶低通IIR最常用也最稳的形式是指数加权移动平均y[n] alpha * x[n] (1 - alpha) * y[n-1]系数alpha和截止频率的关系alpha 1 - expf(-2.0f * PI * fc / fs);比如fs20kHz、fc100Hz时2*PI*100/20000 0.0314 alpha 1 - expf(-0.0314) 0.0309这意味着每一步只保留新输入值的3%过去的值以0.969的比例衰减。这个滤波器很平滑但相位延迟不小这是后面设计PLL带宽时必须考虑进去的。一阶高通IIR的标准形式是y[n] alpha * y[n-1] alpha * (x[n] - x[n-1])这里的alpha和截止频率的关系用RC高通离散化推导fs远大于fc时近似为alpha 1.0f / (1.0f 2.0f * PI * fc / fs);比如高通截止50Hz、fs20kHzalpha大约0.969。这个高通可以滤掉基波分量把高频成分放出来。两级串联的带通一个中心频率附近的表现大概是这样高通把低频段削掉低通把高频噪声修圆中间留出的频带里主要就是注入频率附近的电流响应。缺点是过渡带比较宽选择性不如高阶巴特沃斯。如果对噪声指标要求高可以换成二阶biquad结构直接实现Butterworth带通系数用现成工具算好之后填进结构体就行typedef struct { float b0, b1, b2; float a1, a2; float z1, z2; } biquad_t; float biquad_process(biquad_t *f, float x) { float y f-b0 * x f-z1; f-z1 f-b1 * x - f-a1 * y f-z2; f-z2 f-b2 * x - f-a2 * y; return y; }4.3 滤波器级联与延迟预算整个HFI信号链里带通的群延迟和解调后的低通群延迟是串联的。滤波器越多、越窄滤得越干净但位置误差信号到达PLL的时间就越晚。PLL带宽再高也敌不过前级滤波拖的这几毫秒延迟。所以我每次调HFI都会先列一个延迟预算带通滤波器高通低通两级群延迟大约2-3ms同步解调后的低通滤波器截止频率80-120Hz群延迟大约2-4msPLL等效时间常数设计带宽20-30Hz大约5-10ms。整个信号链路从注入电压到输出估算角总延迟10ms上下。这意味着如果PLL带宽调得很高比如50Hz以上系统很容易在收敛过程里震荡甚至发散因为相位裕度被前级滤波吃掉太多了。所以HFI的响应速度有上限这是物理规律代码再花哨也绕不过去。5. 位置误差解调的数学与代码从sin(2θ_err)到锁相环5.1 为什么q̂轴电流里藏着位置误差脉振高频注入下估算d轴注入了高频电压但真正包含位置信息的信号却出现在估算q轴电流的高频分量里。这件事不少初学者会困惑我把推导思路简化一下。假设估算角度和真实角度之间有一个偏差角θ_err。在估算d轴注入的高频电压分解到真实d、q轴上时两个轴都会分到电压。但真实d轴和q轴电感不同产生的高频电流响应在变换回估算d、q轴时q̂轴分量里会出现一个正比于sin(2θ_err)的成分。写成式子大概是i_qh ≈ K_hf * sin(2 * theta_err) * cos(omega_hf * t)其中K_hf由注入幅值、注入频率、Ld、Lq共同决定。注意θ_err是估算角和真实角的偏差它等于0时这个高频响应分量为零。也就是说当估算角度恰好对准真实转子位置时q̂轴高频电流为零一旦偏差出现q̂轴高频电流就和偏差的正弦值成正比。这个关系正好用来做闭环观测。5.2 同步解调的乘法与误差归一化i_qh本身还是高频载波信号要把它变成直流型的位置误差做法是拿一个和注入信号同频同相的参考余弦去乘它。利用积化和差公式乘积里会出现两项一项是包含θ_err的低频项另一项是频率为2倍注入频率的高频项。再用低通滤波器把2倍高频项滤掉剩下的就是位置误差信号float err_raw i_q_bp * (2.0f * hf_cos);这个2倍系数的乘数只是为了把积化和差后的幅值拉回来不乘也能用只是后面增益要重新标定。完整代码// 带通滤波提取q̂轴高频电流 float i_q_hf hp1_process(hfi_hp, i_q_est); i_q_hf lp1_process(hfi_bp_lp, i_q_hf); // 同步解调 float demod_ref 2.0f * hf_cos; float err_raw i_q_hf * demod_ref; // 低通滤波提取位置误差包络 float theta_err_signal lp1_process(hfi_err_lp, err_raw);关键是滤波后的误差信号幅值不是固定的它和母线电压、电机电感、注入频率全都有关系。在不同电机上跑同一套代码这个幅值能差出好几倍。PLL的增益就得跟着变这是很多移植项目最烦的地方。解法是做一个归一化用电机参数算一个理论增益把误差信号除以这个增益变成无量纲的近似角度偏差// 理论增益UHF / (4 * ωHF) * (1/Ld - 1/Lq) float hfi_norm_gain HF_INJ_AMPL / (4.0f * HF_INJ_W) * (1.0f / LD_EST - 1.0f / LQ_EST); if (hfi_norm_gain 0.0f) hfi_norm_gain -hfi_norm_gain; float err_norm theta_err_signal / hfi_norm_gain;归一化之后误差信号在小角度时接近真实的θ_err弧度值PLL的PI参数就可以跨电机复用了。实测下来即使电感参数有20%误差归一化也能把PLL调试成本压下来一大截。5.3 PLL观测器实现代码位置误差信号有了剩下就是用锁相环把它收敛到零。PLL本质上是一个PI调节器加一个积分器比例项提供即时反馈积分项累积消除稳态误差积分输出是估算电角速度再积分一次是估算电角度。typedef struct { float kp, ki; float err_int; float w_est; float theta_est; float w_limit; } hfi_pll_t; void hfi_pll_update(hfi_pll_t *pll, float err_norm, float ts) { pll-err_int err_norm * ts; // 积分限幅防止启动时刻积分饱和 float int_limit pll-w_limit / pll-ki; if (pll-err_int int_limit) pll-err_int int_limit; if (pll-err_int -int_limit) pll-err_int -int_limit; pll-w_est pll-kp * err_norm pll-ki * pll-err_int; if (pll-w_est pll-w_limit) pll-w_est pll-w_limit; if (pll-w_est -pll-w_limit) pll-w_est -pll-w_limit; pll-theta_est pll-w_est * ts; if (pll-theta_est TWO_PI) pll-theta_est - TWO_PI; if (pll-theta_est 0.0f) pll-theta_est TWO_PI; }PLL带宽设计按照典型二阶系统来。取自然频率fn25Hz、阻尼系数ζ1对应kp 2.0f * PI * fn * 2.0f * zeta; // ≈ 314 ki (2.0f * PI * fn) * (2.0f * PI * fn); // ≈ 24674也就是说kp大约300、ki大约25000这组参数配合前面20kHz的采样周期在归一化误差信号正常的情况下从启动到锁定角度大约需要100ms到200ms。如果想更快可以把PLL带宽临时拉高到40-50Hz锁定后再降回来。这个带宽调度在启动阶段很有用后面第七节我会再提。6. 磁极极性判断高频注入环节里最容易被漏掉的一环6.1 sin(2θ_err)的180度死角如果只看位置误差信号sin(2θ_err)会发现它在θ_err等于0和等于π时都为零。也就是说PLL既可以把估算角收敛到真实角度也可能收敛到相反方向也就是转了180°。在实际工程里启动时估算角度初始化在0附近真实转子位置未知PLL收敛到哪个方向完全看初始误差的符号和扰动毫无确定性。如果估算角正好反了180°电流环输出的力矩方向就反了本来想往正方向出力实际上往反方向猛推。轻则启动瞬间倒一下重则直接触发过流和失步。所以在HFI启动流程里极性判断不是可选项是必选项。6.2 磁饱和原理与d̂轴高频电流幅值检测之所以能判断N、S极性靠的是磁饱和效应。永磁体建立的磁场方向固定当外部定子磁场和永磁体磁通方向一致时磁路叠加铁心更饱和等效电感变小方向相反时磁路去饱和等效电感变大。电感一变高频电流响应幅值就跟着变。反映到代码里观测d̂轴的高频电流响应幅值就能看到这个差异。在估算角正好对准真实d轴时如果方向正确d̂轴高频电流幅值偏大如果方向反了180°幅值偏小。拿一个实际测过的电机数据来说凸极率2.0的IPMSM饱和引起的高频幅值差大约在3%到10%之间虽然不算大但比噪声高好几倍有条件判断。具体实现是在PLL已经收敛到角度稳定后对d̂轴高频电流做一次同步解调参考信号和注入同相float i_d_hf hp1_process(hfi_hp_d, i_d_est); i_d_hf lp1_process(hfi_bp_lp_d, i_d_hf); float pole_signal lp1_process(hfi_pole_lp, i_d_hf * hf_cos);pole_signal为正说明d̂轴方向和永磁体N极方向一致当前估算角正确pole_signal为负说明实际反了180°把估算角整体加πif (pole_signal 0.0f) { pll.theta_est PI; if (pll.theta_est TWO_PI) pll.theta_est - TWO_PI; }这个判断必须在轻载、电流比较小的状态下做因为大电流本身会改变铁心饱和状态极有可能把符号搞反。所以工程上一般安排在完全零速待机、没有力矩指令时执行或者在启动的第一个电流建立阶段做完极性判断再执行电流环。6.3 极性判断的工程实现策略实际代码里的时序大概是这样的闭合HFI位置环给一个固定的高频注入电压让PLL先收敛到某个估算角等待PLL角度稳定根据误差信号绝对值连续N个周期小于阈值来判断执行d̂轴高频电流幅值解调得到极性信号符号为负则翻转估算角翻转后强制把PLL的积分项清零因为角度跳变了180°转速积分值不该突变。还有一种更直接的做法是注入正、负两个短促的直流测试脉冲比较两个方向的电流响应大小来判极性。这个方法逻辑更简单但会产生力矩冲击而且需要额外的测试脉冲时序脉振高频注入的基波检测法不需要额外动作代码上更顺。7. 实测记录解调波形、死区干扰和切入中高速的衔接7.1 解调信号正常长什么样调试HFI最有效的办法是把几路关键信号通过DAC或上位机波形通道拉出来看。我正常会同时看四路带通滤波后的i_q_est、解调后的err_raw、低通后的theta_err_signal、PLL输出的theta_est。静止状态下如果转子被外力推到一个方向低通后的误差信号应该是一个比较干净的直流电平幅值和θ_err的正弦值成正比PLL收敛后这个电平会逐渐归零。用手缓慢转动转子theta_err_signal应该跟着转子角度变化形态接近sin函数而且PLL输出的估算角会平滑跟踪真实角。如果看到误差信号里有明显的毛刺或周期性尖峰优先查死区补偿和PWM采样点位置。如果误差信号整体有偏置查一下解调参考信号和注入信号之间有没有相位差这个相位差会在高通低通滤波器的延迟中积累出来必要时要在解调参考上补一个相位补偿角。7.2 调试中遇到过的坑第一个坑是采样时刻和PWM更新点的配合。部分MCU的ADC采样安排在PWM载波的顶点或谷点插入高频信号后如果注入分量在采样点附近恰好处于快速变化段采样到的电流会带有一个固定偏差。解决办法是把ADC采样时刻稍微往前挪一点避开开关动作区和注入信号的瞬变沿或者干脆在多个载波周期上做均值处理。第二个坑是启动瞬间PLL积分饱和。转子初始位置完全未知时初始误差可能接近90°误差信号最大PLL积分项会迅速冲高等角度快要追上时积分项还在顶格结果角度冲过头来回震荡好几拍才能稳住。我的做法是给PLL积分项单独设一个较小的限幅同时启动阶段把PLL带宽先拉高、等误差信号进入一个死区范围后再切换到正常带宽。代码里加上这个限幅逻辑后启动收敛过程明显变得更干净。第三个坑是高频注入和死区补偿之间的交互。死区补偿本身是随电流极性切换的电流在零点附近抖动时补偿输出电压会频繁翻转产生一个很宽频带的扰动。这个扰动落进带通滤波器范围后位置误差上会出现类似白噪声的抬升。解决手段是把死区补偿做成滞回切换电流超过一定阈值才切换极性零电流附近保持上一个状态这样能压掉不少高频噪声。7.3 从HFI切换到中高速观测器的衔接高频注入不是无感FOC的全部它只管零低速这一段。转速升起来以后反电动势足够强滑模观测器可以正常工作了这时候应该把位置来源切到滑模把高频注入关掉否则持续注入只会白白增加电机啸叫和损耗。切换逻辑的经验是当估算转速超过额定转速的5%到10%并且持续一段时间比如100ms以上就把PLL的估算角切换成滑模观测器的输出然后逐步关闭高频注入。切换瞬间要保证两个角度源是连续的否则电流环会看到角度跳变产生电流冲击。我一般是在切换前先运行一小段并联状态也就是HFI的PLL和滑模观测器同时跑比较两者的角度差差值小于一个阈值比如5°再真正切过去。这样做虽然代码里多一个状态但切换过程肉眼可见地顺滑。再补充一个和滤波器相关的细节从HFI切到滑模之后HFI那一串带通、低通滤波器里的状态变量还残留着上一个阶段的高频数据如果不做初始化就直接关掉下次再进入HFI时会有一段几毫秒的瞬态。所以进入HFI之前记得把滤波器状态全部清零包括PLL积分项。最后再分享一个小习惯调试HFI时电机发出的高频啸叫声很容易让人误以为系统出了问题其实那恰恰说明高频电压已经成功注入、电流响应正常出现在预期频率上。真正需要警惕的是啸叫消失而位置误差信号依然很大——那多半是信号链哪里断掉了或者是死区补偿和采样时序的问题。我现在的习惯是把HFI调试分成两步第一步只看信号链让PLL在电机堵转状态下收敛观察角度是否稳定第二步才上闭环带载测试。先把位置观测器喂干净再谈整体控制性能这条经验帮我省掉过太多联合调试的冤枉时间。
返回列表