ARTICLE DETAIL

资讯详情

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

高频注入无感FOC低速启动:IIR滤波与磁极极性判断代码实现

高频注入无感FOC低速启动:IIR滤波与磁极极性判断代码实现 1. 高频注入无感 FOC 到底在解决什么问题1.1 从零速启动的尴尬说起搞过无感 FOC 的人都知道一个绕不开的坎电机静止或者转速极低的时候反电动势几乎为零滑模观测器、龙伯格观测器这些依赖反电动势的方案全部失灵。你拿一个没有霍尔、没有编码器的 PMSM通电那一刻根本不知道转子在哪强行闭环就是赌命——运气好转起来运气不好直接堵转、过流、炸管。高频注入HFIHigh Frequency Injection就是专门治这个病的。它的核心思路很朴素既然反电动势没有那我就主动往定子绕组里注入一个高频电压信号利用凸极效应d/q 轴电感不等产生的响应电流来“问”转子到底在哪。转子位置信息藏在高频响应电流的幅值或相位里把它解调出来就能在零速和低速段实现有传感器级别的控制精度。这套东西适合谁看如果你已经能跑通有霍尔或者有编码器的 FOC想进一步啃无感低速启动这块硬骨头或者你正在用 STM32、TMS320 这类平台做电机控制被初始位置检测和磁极极性判断卡住了那这篇内容就是给你写的。我会从代码层面把 HFI 的注入、解调、IIR 滤波、位置估计、磁极极性判断整条链路拆开讲不玩虚的。1.2 为什么偏偏选高频注入而不是别的方案无感 FOC 低速段可选的方案其实不多。滑模观测器在零速附近信噪比极差脉振电压法虽然简单但只能判断到 180 度电角度剩下的磁极极性还得单独处理。高频注入的优势在于它不依赖转速零速就能工作而且对参数变化的鲁棒性相对好。代价也很明显注入高频信号会带来额外的电流纹波、噪声和损耗解调过程需要滤波器滤波器又引入相位延迟延迟直接影响位置估计精度。所以 HFI 的工程难点从来不是“能不能注入”而是“怎么把位置信息从一堆噪声和延迟里干净地抠出来”。这也是为什么 IIR 滤波器和磁极极性判断会成为整个链路的关键节点。2. 高频注入的代码实现与信号链路拆解2.1 注入信号的选型旋转电压还是脉振电压高频注入主流有两种玩法旋转电压注入和脉振电压注入。旋转注入是在 α-β 坐标系下注入一个旋转的高频电压矢量响应电流的包络里包含转子位置信息脉振注入是在估计的 d 轴方向注入高频信号通过 q 轴响应电流的符号和幅值来判断位置误差。从代码实现角度脉振注入更常用因为它对逆变器非线性不那么敏感而且位置误差信号直接体现在 q 轴电流上解调链路更短。我实测下来脉振注入在 STM32G4 这类带硬件三角函数单元的芯片上跑起来非常顺计算量可控。注入频率的选择有个经验公式一般取 PWM 频率的 1/10 到 1/5。比如 20kHz 的 PWM注入频率取 2kHz 到 4kHz 比较合适。太低会和基波耦合太高又会被电流采样带宽限制。注入电压幅值通常取额定电压的 5% 到 15%具体要看电机的凸极率凸极率小的电机需要更大的注入幅值才能看到明显的响应。// 脉振高频电压注入核心代码片段 // 在估计的 d 轴方向注入高频余弦信号 #define HFI_FREQ 2000.0f // 注入频率 2kHz #define HFI_AMP 0.1f // 注入幅值 10% 额定电压 #define HFI_TS 0.00005f // 控制周期 20kHz float hfi_phase 0.0f; void hfi_injection(float theta_est, float *vd_out, float *vq_out) { // 更新注入相位 hfi_phase 2.0f * PI * HFI_FREQ * HFI_TS; if (hfi_phase 2.0f * PI) hfi_phase - 2.0f * PI; // 注入电压在估计 d 轴方向 float u_inj HFI_AMP * cosf(hfi_phase); // 叠加到估计 dq 轴的电压指令上 *vd_out u_inj; // q 轴不注入保持原控制量 }这段代码看着简单但有个坑注入信号必须叠加在估计的 dq 轴电压指令上而不是实际的 dq 轴。因为整个 HFI 的前提就是“我不知道真实转子位置只能用估计位置来注入”。如果你不小心用真实位置去注入那位置估计器就失去了意义。2.2 响应电流的解调从高频载波里提取位置误差注入电压之后电流环的反馈电流里会混入高频响应分量。这个高频分量的幅值和相位与转子位置误差直接相关。解调的核心操作是把采样到的电流乘以与注入信号同频的参考信号然后低通滤波得到包含位置误差的直流分量。数学上q 轴高频响应电流可以近似表示为iq_hf ≈ (U_inj / (ω_hf * L_d)) * sin(2 * Δθ) * cos(ω_hf * t)其中 Δθ 是估计位置与真实位置的误差ω_hf 是注入角频率。乘以 cos(ω_hf * t) 之后经过低通滤波剩下的就是与 sin(2Δθ) 成正比的量。当 Δθ 很小时sin(2Δθ) ≈ 2Δθ所以这个量直接反映了位置误差。// 解调过程同步解调 低通滤波 float hfi_demod(float iq_feedback, float hfi_phase) { // 同步解调乘以同频参考信号 float demod iq_feedback * cosf(hfi_phase); // 低通滤波提取直流分量这里用 IIR 滤波器 float error iir_lpf_update(hfi_lpf, demod); return error; // 该值正比于位置误差 }这里的关键在于低通滤波器的截止频率选择。截止频率必须远低于注入频率一般取注入频率的 1/10 到 1/5。比如 2kHz 注入截止频率取 200Hz 到 400Hz。截止频率太高高频载波滤不干净位置误差信号里会有纹波截止频率太低相位延迟大动态响应慢电机加速时位置估计会滞后。2.3 位置误差到转速和角度的闭环拿到位置误差信号之后接下来就是把它送进一个锁相环PLL或者龙伯格观测器估计出转速和角度。PLL 的结构简单调参直观在 HFI 里用得最多。// 简化 PLL 位置估计器 typedef struct { float kp; float ki; float theta_est; float omega_est; float integral; } pll_t; void pll_update(pll_t *pll, float error, float ts) { // PI 调节器 float proportional pll-kp * error; pll-integral pll-ki * error * ts; pll-omega_est proportional pll-integral; // 积分得到估计角度 pll-theta_est pll-omega_est * ts; // 角度归一化到 [0, 2π) if (pll-theta_est 2.0f * PI) pll-theta_est - 2.0f * PI; if (pll-theta_est 0.0f) pll-theta_est 2.0f * PI; }PLL 的带宽选择是个权衡。带宽高动态响应快但噪声放大也严重带宽低估计平滑但加速时跟不上。我的经验是HFI 的 PLL 带宽取 20Hz 到 50Hz 比较稳妥具体看应用对动态的要求。如果是风机、水泵这类负载带宽可以低一点如果是伺服类应用需要适当提高。3. IIR 滤波器在 HFI 里的角色与代码落地3.1 为什么 HFI 离不开 IIR 滤波HFI 的信号链路里滤波器承担了两个任务一是从 PWM 开关噪声和电流采样噪声里提取有用的高频响应信号二是把解调后的信号平滑成可用的位置误差。这两个任务对滤波器的要求不一样前者需要带通特性后者需要低通特性。IIR 滤波器相比 FIR 的优势在于同样的滤波性能下阶数更低计算量更小相位延迟在通带内也更可控。对于电机控制这种对实时性要求极高的场景IIR 是更务实的选择。当然 IIR 的缺点是相位非线性但在 HFI 里我们主要关心的是特定频率点的相位延迟可以通过相位补偿来修正。3.2 二阶 IIR 低通滤波器的直接I型实现在嵌入式平台上二阶 IIR 是最常用的结构。下面是一个标准的二阶巴特沃斯低通滤波器实现采用直接I型结构数值稳定性好适合定点或浮点运算。// 二阶 IIR 低通滤波器结构体 typedef struct { float b0, b1, b2; // 分子系数 float a1, a2; // 分母系数a0 归一化为 1 float x1, x2; // 输入历史 float y1, y2; // 输出历史 } iir_lpf2_t; // 滤波器初始化根据截止频率和采样频率计算系数 void iir_lpf2_init(iir_lpf2_t *f, float fc, float fs) { float omega 2.0f * PI * fc / fs; float sn sinf(omega); float cs cosf(omega); float alpha sn / (2.0f * 0.7071f); // Q 0.7071 巴特沃斯 float a0 1.0f alpha; f-b0 (1.0f - cs) / 2.0f / a0; f-b1 (1.0f - cs) / a0; f-b2 f-b0; f-a1 -2.0f * cs / a0; f-a2 (1.0f - alpha) / a0; f-x1 f-x2 f-y1 f-y2 0.0f; } // 滤波器更新 float iir_lpf2_update(iir_lpf2_t *f, float x) { float y f-b0 * x f-b1 * f-x1 f-b2 * f-x2 - f-a1 * f-y1 - f-a2 * f-y2; f-x2 f-x1; f-x1 x; f-y2 f-y1; f-y1 y; return y; }这段代码有几个细节值得说。第一Q 值取 0.7071 是巴特沃斯响应通带最平坦适合 HFI 这种需要干净直流分量的场景。第二系数计算里的 alpha 用 sin 而不是 tan这是双线性变换的标准做法能保证频率预畸变正确。第三历史状态必须初始化为零否则上电瞬间会有冲击。3.3 滤波器参数选择的实操计算假设 PWM 频率 20kHz注入频率 2kHz解调后需要提取的直流分量带宽大约 200Hz。那么低通滤波器的截止频率取 200Hz 到 400Hz 之间。用上面的初始化函数fc 300Hzfs 20kHzomega 2 * π * 300 / 20000 0.0942 radsn sin(0.0942) 0.0941cs cos(0.0942) 0.9956alpha 0.0941 / (2 * 0.7071) 0.0665a0 1.0665b0 (1 - 0.9956) / 2 / 1.0665 0.00206b1 (1 - 0.9956) / 1.0665 0.00413b2 0.00206a1 -2 * 0.9956 / 1.0665 -1.867a2 (1 - 0.0665) / 1.0665 0.875这组系数在 2kHz 处的衰减大约是 -20dB 左右能把注入载波压得比较干净。如果你发现位置误差信号里还有明显的 2kHz 纹波可以把截止频率再降低或者改用四阶滤波器。注意IIR 滤波器在定点 DSP 上实现时系数需要做 Q 格式缩放否则小系数会被截断成零。比如 TMS320C6416 这类定点平台b0 0.00206 直接存成整数就是 0必须左移 12 位以上再运算最后右移回来。4. 磁极极性判断HFI 的最后一块拼图4.1 为什么位置估计完了还要判断极性高频注入基于凸极效应而凸极效应的周期是 180 度电角度不是 360 度。也就是说HFI 能告诉你转子在哪个轴上但没法区分 N 极还是 S 极。位置估计出来的角度可能是真实角度也可能是真实角度加 180 度。如果不做极性判断电机有 50% 的概率反转或者启动失败。磁极极性判断的核心原理是磁饱和效应。定子铁芯在永磁体磁场的作用下N 极方向的饱和程度和 S 极方向不一样。如果在估计的 d 轴正方向注入一个正电压脉冲再注入一个负电压脉冲比较两次电流响应的幅值就能判断出磁极方向。电流响应大的那个方向就是磁饱和更严重的方向对应永磁体的 N 极。4.2 脉冲注入法的代码实现极性判断通常在 HFI 收敛之后、电机启动之前做一次。具体操作是在估计的 d 轴方向分别注入正负电压脉冲记录 d 轴电流的峰值比较大小。// 磁极极性判断 #define POLARITY_PULSE_VOLTAGE 0.3f // 脉冲电压幅值 30% 额定 #define POLARITY_PULSE_TIME 0.005f // 脉冲持续时间 5ms #define POLARITY_SETTLE_TIME 0.01f // 脉冲间隔 10ms int polarity_detect(float theta_est) { float id_pos, id_neg; // 正脉冲在估计 d 轴正方向注入 set_dq_voltage(POLARITY_PULSE_VOLTAGE, 0.0f, theta_est); delay(POLARITY_PULSE_TIME); id_pos get_id_feedback(); set_dq_voltage(0.0f, 0.0f, theta_est); delay(POLARITY_SETTLE_TIME); // 负脉冲在估计 d 轴负方向注入 set_dq_voltage(-POLARITY_PULSE_VOLTAGE, 0.0f, theta_est); delay(POLARITY_PULSE_TIME); id_neg get_id_feedback(); set_dq_voltage(0.0f, 0.0f, theta_est); delay(POLARITY_SETTLE_TIME); // 电流响应大的方向对应 N 极 if (fabsf(id_pos) fabsf(id_neg)) { return 0; // 估计角度就是真实角度 } else { return 1; // 估计角度需要加 180 度 } }这段代码看起来直白但实操里有几个坑。第一脉冲幅值不能太小否则饱和效应不明显也不能太大否则电机可能会动或者过流。我一般从 20% 额定电压开始试根据电流响应调整。第二脉冲时间要足够长让电流建立到稳态但也不能太长否则电机发热。5ms 到 10ms 是个比较安全的范围。第三两次脉冲之间要留足够的间隔让电流完全衰减到零否则第二次脉冲的初始条件受第一次影响判断会出错。4.3 极性判断的可靠性提升技巧单次脉冲判断有时候会翻车尤其是小功率电机或者凸极率很低的电机。我常用的提升手段有三个多次平均正负脉冲各做 3 到 5 次取电流峰值的平均值再比较能有效抑制随机噪声。电流差分不直接比较绝对幅值而是比较正负脉冲的电流差值差值符号比绝对幅值更稳定。结合高频注入的二次谐波有些方案会在 HFI 解调信号里提取二次谐波分量利用饱和引起的二次谐波来判断极性不需要额外注入脉冲。这个方法更优雅但实现复杂度高适合对启动平滑性要求极高的场合。实操心得极性判断做完之后建议把判断结果存到非易失存储器里。下次上电如果转子没有移动过可以直接用上次的结果省掉脉冲注入的过程启动更快也更安静。当然如果应用场景里转子可能被外力转动那每次上电还是老老实实重新判断。5. 整条链路的联调与常见问题排查5.1 从注入到闭环的完整启动流程把前面几块拼起来一个完整的 HFI 无感启动流程是这样的初始化配置 PWM、ADC、定时器初始化 IIR 滤波器系数和 PLL 参数。HFI 注入与解调在估计 d 轴注入高频电压采样电流同步解调IIR 低通滤波得到位置误差。PLL 收敛位置误差送入 PLL估计转速和角度。观察位置误差是否收敛到零附近转速估计是否稳定。磁极极性判断HFI 收敛后注入正负脉冲判断极性修正角度。切换到闭环极性修正后角度已经准确可以切换到电流环、速度环闭环逐渐加速。过渡到中高速随着转速升高反电动势增大可以平滑过渡到滑模观测器或其他中高速无感方案。这个流程里第 3 步到第 5 步的切换时机很关键。HFI 收敛的判据一般是位置误差的绝对值持续小于某个阈值比如 0.05 rad超过一定时间比如 100ms。极性判断要在 HFI 收敛之后做否则角度都不准脉冲注入的方向也是错的。5.2 常见问题速查表现象可能原因排查方向解决方法位置误差不收敛一直在振荡PLL 带宽过高或过低观察误差波形频率调整 PLL 的 Kp、Ki先降带宽试电机启动时反转磁极极性判断错误检查脉冲注入方向和电流采样增加脉冲次数改用电流差分判断位置估计有 2 倍频纹波IIR 截止频率太高观察误差信号频谱降低截止频率或改用四阶滤波低速时电流噪声大注入幅值过大听电机声音看电流波形降低注入幅值提高注入频率加速时位置估计滞后PLL 动态响应不够突加转速给定观察适当提高 PLL 带宽或加前馈补偿极性判断结果不稳定脉冲间隔不够看电流是否归零增加脉冲间隔时间多次平均切换到中高速时失步过渡策略太激进观察切换瞬间的电流和转速降低切换转速加过渡区平滑混合5.3 几个容易踩的坑和我的处理方式第一个坑是电流采样时机。HFI 的响应电流是高频的如果 ADC 采样时刻和 PWM 载波不同步采到的值会包含大量开关噪声。我的做法是让 ADC 在 PWM 中心对齐模式下的计数零点触发这时候开关噪声最小。STM32 的定时器可以配置 ADC 触发源为 TIM_TRGO正好在计数器归零时触发。第二个坑是死区补偿。逆变器的死区会导致输出电压和指令电压有偏差这个偏差在 HFI 里会被解调成位置误差的直流偏置导致估计角度整体偏移。解决办法是在注入电压上叠加死区补偿量或者选择对死区不敏感的注入方式。脉振注入比旋转注入对死区更鲁棒这也是我倾向脉振注入的原因之一。第三个坑是参数敏感性。HFI 的位置误差信号幅值和 L_d、L_q 的差值有关如果电机凸极率很低比如表贴式 PMSM信号会非常微弱。这时候要么加大注入幅值要么改用 INFORM 法或者高频电流注入法。表贴式电机做 HFI 确实吃力选方案之前先确认电机的凸极率L_q/L_d 小于 1.1 的基本可以放弃 HFI 了。第四个坑是滤波器相位延迟补偿。IIR 低通滤波器在位置误差信号上引入了相位延迟这个延迟会导致估计角度滞后于真实角度。补偿方法有两种一是根据滤波器在注入频率处的相位特性在 PLL 输出上叠加一个与转速成正比的补偿角二是把滤波器设计成线性相位但 IIR 做不到严格线性相位只能用全通网络做相位均衡。我一般用第一种简单有效补偿系数通过实验标定。6. 代码之外的工程经验6.1 参数标定的实操流程HFI 的参数不多但每一个都影响最终效果。我通常按这个顺序标定先定注入频率。从 PWM 频率的 1/10 开始逐步提高观察电流采样信噪比。找到信噪比明显恶化的频率点然后退回到它的一半。比如 20kHz PWM从 2kHz 开始试如果 4kHz 时噪声明显变大那就用 2kHz。再定注入幅值。从额定电压的 5% 开始逐步加大观察位置误差信号的幅值。目标是让误差信号在位置偏差 0.1 rad 时能有足够的信噪比同时电流纹波不超过额定电流的 10%。这两个条件往往矛盾需要折中。然后调 IIR 截止频率。先用 300Hz 试如果位置误差纹波大就降低如果动态响应慢就提高。每次调整后做一次阶跃转速响应看超调量和调节时间。最后调 PLL 带宽。从 20Hz 开始逐步提高直到位置估计能跟上最快的加速工况同时不引入明显噪声。PLL 的 Kp 和 Ki 按典型二阶系统整定阻尼比取 0.707。6.2 不同平台的实现差异STM32 系列有硬件浮点单元和三角函数加速器IIR 滤波和 PLL 都可以用浮点跑代码可读性好开发效率高。TMS320C6416 这类定点 DSP 需要把系数转成 Q 格式中间运算注意防溢出但运行速度更快适合高 PWM 频率的应用。不管什么平台HFI 的计算量都不小。一个完整的 HFI 链路包括注入信号生成、电流采样、同步解调、IIR 滤波、PLL 更新、极性判断。在 20kHz 的控制频率下这些计算必须在 50 微秒内完成。如果算力吃紧可以把 IIR 滤波和 PLL 放在比电流环更低的频率上跑比如 10kHz牺牲一点带宽换计算余量。6.3 从 HFI 过渡到中高速的策略HFI 在低速段好用但高速段反电动势大了注入信号会被淹没而且高频损耗也大。所以转速升到一定程度通常是额定转速的 10% 到 20%就要切到中高速观测器。切换策略有两种硬切换和软切换。硬切换简单但切换瞬间容易失步。软切换是在过渡区把两个观测器的输出按转速加权混合HFI 的权重随转速升高逐渐降到零中高速观测器的权重逐渐升到一。我一般用软切换虽然代码复杂一点但切换过程平滑不会出现电流冲击。过渡区的宽度取额定转速的 5% 到 10%。太窄了切换太突然太宽了 HFI 在高速段拖后腿。过渡区的加权曲线用线性或者 S 形都可以S 形更平滑但计算量稍大。最后分享一个小技巧调试 HFI 的时候把估计角度和真实角度如果有编码器做对比同时用 DAC 输出到示波器上看比看串口打印的数据直观一百倍。角度误差的波形、收敛过程、纹波大小一目了然。没有 DAC 的话用 PWM 加 RC 滤波也能凑合但带宽有限只能看个大概趋势。这套 HFI 方案我从零速启动到中高速过渡整条链路跑通前后调了大概两周踩的坑基本都写在上面了。代码框架可以直接拿去用参数需要根据你的电机和硬件平台重新标定。记住一点HFI 的核心不是注入本身而是从噪声里把位置信息干净地提取出来滤波器设计和参数标定决定了最终性能的上限。
返回列表