ARTICLE DETAIL

资讯详情

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

无感PMSM零速启动难?I/F强拖启动原理与工程实践详解

无感PMSM零速启动难?I/F强拖启动原理与工程实践详解 做无位置传感器PMSM驱动的人十有八九都卡在“零速起步”这道坎上电机停在那里转子位置完全不知道反电动势为零速度观测器根本没有有效输入强行闭环只会让电流冲得乱七八糟。我最早把I/F强拖启动用起来是在一款24V低压无感风机驱动板上简单说就是先不看转子在哪直接给电流矢量一个固定幅值然后让它的电角度按设定速率稳步往前走用定子磁场把转子“拖”到能建立反电动势的转速再切回正常FOC闭环。这个方法稳定、代码量小、不需要额外硬件非常适合风机、水泵这类负载特性相对平稳的PMSM启动场景。这篇文章把I/F强拖启动的原理、启动参数设计、仿真验证以及我在实际调试中踩过的坑一次性讲清楚代码都是可以直接跑、可以搬进嵌入式工程的。1. I/F强拖启动的底层逻辑1.1 转矩公式和“功角”是关键先摆出表贴式PMSM在转子dq坐标系下的电磁转矩公式Te 1.5 × p × Ψf × iq其中p是极对数Ψf是永磁体磁链iq是转子q轴电流。表贴式电机Ld≈Lq磁阻转矩可以忽略所以转矩完全由iq决定。那I/F强拖又是怎么和iq挂钩的关键在于我们人为定义了一个“虚拟电角度”θc并且让电流矢量始终落在θc的方向上。假设转子真实电角度是θe那么两者之间的差值就叫功角δδ θc - θe如果I/F阶段电流环给定的是idc_ref Is、iqc_ref 0也就是电流幅值恒定、方向由θc决定那么在旋转坐标变换之后转子上的d轴和q轴电流可以写成id Is × cosδ iq Is × sinδ所以电磁转矩就变成了Te 1.5 × p × Ψf × Is × sinδ这个公式是理解I/F的全部核心。δ0时电流矢量完全落在转子上产生不了转矩δ在0到90°之间时定子电流矢量领先转子转子会受到一个向前的加速转矩δ90°时转矩最大达到1.5×p×Ψf×Is。I/F强拖启动做的事情本质上就是通过控制θc的旋转速度间接控制δ进而控制转矩。再看机械方程J × dωm/dt Te - TL - B × ωm如果电流矢量旋转的电角速度ωc大于转子当前的电角速度那么δ会逐渐拉大转矩上升转子被加速。等δ增加到“负载转矩 加速转矩”都刚好能被电磁转矩平衡时转子就跟着电流矢量同步转了。所以I/F看起来像是“盲转”实际上是一个由电流源强拖的同步过程正常情况下不会丢步。1.2 为什么不少项目选I/F而不是高频注入或V/F很多人第一反应是“既然要无感启动为什么不用高频注入或者简单的V/F”这里需要分清场景。高频注入在IPMSM上效果比较明显因为IPMSM的Ld和Lq差得多转子凸极性容易被检测到。但如果是表贴式PMSM电感差值很小高频注入信号很难解调软件复杂度和硬件噪声都上去了在低成本风机、水泵控制器上性价比很低。V/F则是电压开环驱动没有电流环负载突变或者母线电压波动时PMSM很容易失步而且启动电流不可控容易过流烧管子。I/F的优势在于它只在已有的FOC电流环上做改动电流始终是被控制的启动电流被钳在设定值鲁棒性天然就好。我整理了个简单的对比启动方案硬件/软件条件启动鲁棒性软件复杂度典型应用高频信号注入凸极性明显、采样精度高中等高重载压缩机、油泵V/F开环启动无特殊要求低低异步机或对启动要求极低的场合I/F强拖启动已有FOC电流环即可高低风机、水泵、低压PMSMI/F也不是没有缺点因为电流矢量并不完全对准转子q轴启动过程中会有无功分量功率因数差、效率低启动段会有明显电流发热。但启动时间通常只有几百毫秒对整体温升影响很小为了可靠性这点代价完全值得。2. 启动参数设计预定位、电流幅值、斜坡时间和切换点2.1 预定位先让转子“听话”I/F启动的第一步不是直接旋转电流矢量而是要先做一个预定位。做法是让θc固定在一个已知角度比如0°同时给定idc_ref Is、iqc_ref 0持续100到300毫秒。这相当于给定子施加一个固定方向的直流电流磁场转子会被这个磁场“拉”到对应位置。如果负载转矩不大转子最终会停在电流矢量方向上。如果负载有阻力转子会停在一个稳定的平衡功角上δ0 arcsin(TL / Tmax)。对这个平衡点我们来做一个快速估算小型电机Tmax如果是0.14Nm负载0.05Nm那么δ0大概是arcsin(0.05/0.14)也就是约20°。所以预定位之后转子和虚拟坐标之间通常还会留有一个小角度这并不影响后续斜坡启动。预定位的真正意义有两点一是让电流环提前进入工作状态避免一上电就出现电流尖峰二是给虚拟电角度一个确定的起点让后面斜坡阶段的行为可预期。高摩擦负载或者大惯量负载预定位时间可以适当加长到300ms甚至500ms直到确认转子已经稳定下来再进入斜坡。2.2 启动电流到底给多大启动电流Is直接决定最大启动转矩Tmax 1.5 × p × Ψf × Is它必须大于“启动过程中可能出现的最大负载转矩 惯性加速转矩 阻尼转矩”。实际选型时Is一般取额定电流的0.3到0.7倍不建议超过0.8倍否则启动发热和母线压力都大。我用一个实际例子来过一遍计算。某小型PMSM参数额定电流3AΨf0.012Wbp4转动惯量J2e-5kg·m²负载转矩TL0.05Nm要求1.2秒内机械转速从0加速到300rpm。加速过程需要的角加速度大约是α Δω / Δt (300/60 × 2π) / 1.2 ≈ 26.2 rad/s²惯性转矩J × α ≈ 0.00052Nm相比负载转矩0.05Nm来说非常小基本可以忽略。那主要克服的就是负载。如果Is取2ATmax 1.5×4×0.012×2 0.144Nm负载只占约35%留的裕量非常足。如果Is只给1ATmax0.072Nm负载占比接近70%一旦负载有波动就很容易拉不动。在真正调硬件时我建议按“Tmax ≥ 1.5倍总阻力矩”来定Is。有余量启动过程才不会被负载波动打断。2.3 斜坡时间别让功角顶到90°斜坡时间是指虚拟电角速度从0上升到切换点电频率所用的时间。如果斜坡太快ωc持续大幅领先转子δ会很快逼近甚至超过90°。一旦过了90°sinδ反而下降转矩变小转子追不上就失步了。所以斜坡时间的本质约束是在整个加速过程中需要的转矩对应的工作点δ必须明显小于90°留出足够的“角度裕量”。常见的经验是把切换速度定在额定转速的5%到10%斜坡时间先按1到2秒起步。比如3000rpm的电机切换点取300rpm斜坡时间就设定为1.2秒。如果是大惯量风机可能要放到3秒甚至5秒。调的时候如果看到启动过程中电机有“顿挫”或速度回退第一时间先把斜坡时间加长而不是去加大电流。有些项目还会把线性斜坡换成S型斜坡也就是角加速度先升后降进一步降低机械冲击和功角振荡。对大多数低压小风机线性斜坡已经足够S型属于锦上添花。2.4 切换FOC的时机与过渡手段I/F不能一直用否则电机始终工作在“力跟随”状态效率和动态响应都差。通常当转子转速到达额定转速的5%到10%时反电动势幅值已经足够让位置观测器工作就可以切换回正常FOC。以刚才的例子算一下300rpm机械转速、极对数4对应电频率20Hz电角速度约125.7rad/s反电动势幅值约125.7×0.012≈1.5V线电压幅值约2.6V。对12V或24V系统来说这个信号已经足够PLL锁定。切换不能直接把角度从θc换成观测器角度否则角度跳变会带来转矩突变。我的做法是在I/F模式下先让观测器运行一段时间用θc - δ_est作为初始值给PLL锁相等角度误差稳定在±5°以内再做一个20到50ms的线性过渡把电流指令从“常值Is”切到“速度环输出”。这样整个过程不会出现速度断崖或电流尖峰。3. 用Python仿真验证I/F启动3.1 为什么先仿真再上硬件I/F启动看起来只是“给电流环加一个旋转角度”但真正调起来功角δ看不见摸不着示波器上只能看到相电流和母线电压判断失步原因全靠猜。所以我在设计启动曲线时一定会先在Python里把PMSM模型和控制器跑一遍把δ、转矩、转速的变化曲线画出来确认参数合理再动硬件。仿真模型采用转子dq坐标系下的PMSM方程状态量是id、iq、ωm、θe。控制器模拟的是嵌入式里的“虚拟旋转坐标系”电流环PI工作在θc决定的dq轴上输出的电压再根据δ变换回转子坐标系。这个结构和你最后写进单片机里的FOC代码非常接近仿真结论基本能直接搬运到工程上。仿真步长取1/20000秒也就是20kHz和大多数嵌入式电流环中断频率一致。这样做不仅模型更接近实际也能顺便观察在20kHz离散控制下电流环是否稳定。3.2 完整可运行仿真代码代码放在下面复制到Python环境里就能跑。需要安装numpy和matplotlib。重点看三个关键点预定位阶段θc固定、斜坡阶段θc累加、以及旋转坐标变换的方向这三处最容易写错。import numpy as np import matplotlib.pyplot as plt # ---------- PMSM 参数 ---------- Rs 0.6 # 定子电阻欧姆 Ld 1.0e-3 # d轴电感H Lq 1.0e-3 # q轴电感H表贴式LdLq Psi_f 0.012 # 永磁体磁链Wb p 4 # 极对数 J 2.0e-5 # 转动惯量kg.m^2 B 3.0e-6 # 阻尼系数N.m.s/rad TL 0.05 # 恒转矩负载N.m # ---------- I/F启动控制参数 ---------- I_strt 2.0 # 强拖电流幅值A t_align 0.2 # 预定位时间s t_ramp 1.2 # 频率斜坡时间s f_hand 20.0 # 切换点电频率Hz对应机械转速300rpm dt 1.0 / 20000.0 # 电流环PI参数 Kp 8.0 Ki 80.0 vlim 10.0 # dq电压输出限幅V # ---------- 状态初始化 ---------- theta_e 0.0 # 转子真实电角度rad omega_m 0.0 # 转子机械角速度rad/s id, iq 0.0, 0.0 # 转子dq电流 theta_c 0.0 # 控制器虚拟电角度rad omega_c 0.0 # 虚拟电角速度rad/s int_id, int_iq 0.0, 0.0 # PI积分项 # ---------- 仿真主循环 ---------- N int((t_align t_ramp 0.5) / dt) t_log np.zeros(N) speed_log np.zeros(N) delta_log np.zeros(N) Te_log np.zeros(N) for k in range(N): t k * dt # 1. 虚拟电角度指令 if t t_align: # 预定位θc固定为0 omega_c 0.0 theta_c 0.0 else: # 频率斜坡电频率从0线性上升到切换点 omega_c (2.0 * np.pi * f_hand) * min(1.0, (t - t_align) / t_ramp) theta_c omega_c * dt idc_ref I_strt iqc_ref 0.0 # 2. 功角 delta theta_c - theta_e # 3. 转子dq电流 - 虚拟旋转坐标系电流 idc id * np.cos(delta) iq * np.sin(delta) iqc -id * np.sin(delta) iq * np.cos(delta) # 4. 电流环PI虚拟旋转坐标系 err_id idc_ref - idc err_iq iqc_ref - iqc int_id err_id * dt int_iq err_iq * dt int_id np.clip(int_id, -1.0, 1.0) int_iq np.clip(int_iq, -1.0, 1.0) vdc Kp * err_id Ki * int_id vqc Kp * err_iq Ki * int_iq vdc np.clip(vdc, -vlim, vlim) vqc np.clip(vqc, -vlim, vlim) # 5. 虚拟旋转坐标系电压 - 转子dq电压 vd vdc * np.cos(delta) - vqc * np.sin(delta) vq vdc * np.sin(delta) vqc * np.cos(delta) # 6. PMSM电机方程转子dq did_dt (vd - Rs * id p * omega_m * Lq * iq) / Ld diq_dt (vq - Rs * iq - p * omega_m * (Ld * id Psi_f)) / Lq id did_dt * dt iq diq_dt * dt Te 1.5 * p * Psi_f * iq domega (Te - TL - B * omega_m) / J omega_m domega * dt theta_e p * omega_m * dt # 7. 记录数据 t_log[k] t speed_log[k] omega_m * 60.0 / (2.0 * np.pi) delta_log[k] delta Te_log[k] Te # ---------- 画图 ---------- fig, ax plt.subplots(3, 1, figsize(10, 9), sharexTrue) ax[0].plot(t_log, speed_log, label机械转速(rpm)) ax[0].set_ylabel(转速/rpm) ax[0].grid(True) ax[0].legend() ax[1].plot(t_log, delta_log, label功角δ(rad)) ax[1].set_ylabel(功角/rad) ax[1].grid(True) ax[1].legend() ax[2].plot(t_log, Te_log, label电磁转矩(N.m)) ax[2].set_ylabel(转矩/N.m) ax[2].set_xlabel(时间/s) ax[2].grid(True) ax[2].legend() plt.tight_layout() plt.show()这段代码里我特意把电流环的PI积分做了限幅避免积分饱和。真正常用的工程代码里还要加上完整的抗积分饱和逻辑不过对于看启动曲线来说这个简化版本已经足够。3.3 仿真结果应该怎么看跑完代码后重点看三条曲线。第一条是机械转速预定位阶段基本为0斜坡开始后转速稳步上升最后稳定在300rpm附近。第二条是功角δ预定位结束后它会先有一个小的稳态值对应负载转矩斜坡阶段δ会增大原因是转子需要额外的加速转矩斜坡结束时δ会回落最终停在一个满足“只克服负载转矩”的角度上。第三条是电磁转矩它应该在某一个平均值附近波动加速段比稳定段略高整体落在Tmax之内。如果你把Is从2A改到1A再跑一遍会发现δ明显变大如果继续减小到0.8Aδ会超过1.2rad甚至逼近π/2这时候电机就停在原地不转了。把t_ramp从1.2s改成0.5s也会看到类似效果。这就是“调参靠仿真”的价值参数合理不合理跑一次图就清清楚楚。有一点需要说明仿真里用的是恒转矩负载真实风机负载是和转速平方成正比的低速时负载很小启动更容易。所以仿真参数如果没问题真实风机上往往更稳。3.4 从仿真迁移到嵌入式代码的注意点仿真跑通了之后把它搬进单片机的时候有几个坑要注意。第一θc的累加必须放在PWM中断里顺序是ADC采电流 → 坐标变换进电流环 → 更新θc → SVPWM输出。顺序反了会出现一拍延迟在小惯量电机上可能直接导致电流振荡。第二电流环的离散化要和你MCU的中断频率匹配。20kHz仿真步长实际代码也建议跑20kHz电流环PI参数可以从仿真里的Kp8、Ki80初调再根据母线电压和电流反馈系数做归一化修正。很多工程代码会把电流环写成“标幺制”这样PI参数不随电机批次变化太夸张。第三坐标变换方向最容易写错。仿真里的变换方向已经验证过写固件时建议先开环给一个固定电压矢量手动缓慢旋转θc看电机是否跟着转再确认电流极性最后才合上电流环。我见过太多人第一步就栽在“转起来后电流正反馈爆炸”上。4. 调试验收那些让我折腾到半夜的坑4.1 启动时电流和转速低频振荡现象是上电启动后电机在某个低频段来回晃相电流包络像波浪一样起伏转速反馈也是波动的。这个现象的本质是功角δ在稳定点附近来回围绕振荡。I/F启动在这个阶段相当于一个弹簧-质量系统定子磁场产生的同步转矩是“弹簧力”转子惯量是“质量”如果系统阻尼不足就会来回晃。我在实际调试中解决这个问题的顺序是先把斜坡时间拉长50%看振荡是否变小然后把Is稍微调大一点减小负载转矩占Tmax的比例让稳态功角不要那么靠近不稳定边界最后检查预定位时间是否太短如果转子在预定位阶段还没停稳就进入斜坡启动段同样容易来回晃。对一般风机负载这三步调完基本都能压下去。少数高惯量场合可以在电流环里叠加一个与虚拟频率变化率成比例的q轴电流前馈相当于给系统人为增加阻尼但这类做法一般用不到。4.2 电流指令正常电机却纹丝不动有次调试电流环反馈正常、idc_ref2A也跟踪上了但电机就是一动不动。查到最后是三个原因里的一个。第一个原因θc根本没有递增。预定位结束时斜坡状态机的判断条件没满足θc一直锁在0度电流矢量方向不变转子早就对齐了当然没有转矩。看代码时先确认θc在斜坡阶段有没有一直累加。第二个原因启动电流不够。算一下Tmax对比总阻力矩如果负载摩擦、机械卡滞带来的阻力矩已经超过Tmax电机就是拉不动。这时候加大Is或者排查机械问题。第三个原因电压饱和。电流环输出的vdc/vqc已经撞到限幅值但电流仍然追不上给定值说明母线电压或调制比不够。I/F启动频率不高时一般不会饱和但如果母线电压偏低、电机电感偏大就会出现“电压有、电流没有”的尴尬局面。用示波器看逆变器调制波是否顶到100%就能判断。4.3 切换FOC瞬间转速跳动或过流I/F切FOC时最怕的就是角度突变。如果观测器输出的角度和当前θc相差30°直接切换等于把电流矢量瞬间掰到一个新方向轻则转速跳一下重则过流保护。解决方案我归纳成三步。第一步切换前让观测器在I/F模式下先运行几百毫秒给足收敛时间。第二步观测器初始角度不要给0而是给θc - δ_estδ_est可以从当前转矩和Is估算也可以用一个小PLL把误差吸进去。第三步切换过程做一个20到50ms的过渡比如电流指令按比例从“常值Is”过渡到速度环输出不要一步切过去。按这个流程走我遇到过的最严重情况也就是转速波动几十转不会触发过流。4.4 一张初始参数表如果项目刚起步没有太多调参经验可以直接用下面这组初始参数再根据实际电机微调。参数推荐范围说明Is0.3~0.7 × Irated确保Tmax大于1.2倍总阻力矩预定位时间0.1~0.3s高摩擦或高惯量取上限电流斜坡时间0.1~0.2s防止启动瞬间电流尖峰频率斜坡时间1~2s高惯量可放到3~5s切换转速5%~10%额定转速保证反电动势足够可观测电流环带宽500~1500Hz必须远高于启动斜坡频率我实际调过一台12V/60W的小水泵额定电流4AIs最终定在1.5A预定位200ms斜坡1s到400rpm额定转速3600rpm切换点约11%切入无感FOC后一直稳定运行。这个案例里的启动电流只有额定的0.375倍说明负载比较轻没有必要给大电流徒增发热。5. 工程化落地状态机与保护逻辑5.1 启动状态机怎么编排I/F启动在正式工程里不是一段散装代码而是一个清晰的状态机。我的习惯是分成五个状态IDLE、ALIGN、IF_RAMP、IF_HOLD、FOC_RUN。IDLE是待机ALIGN是预定位IF_RAMP是频率斜坡IF_HOLD是到达切换速度后短暂保持FOC_RUN是正常闭环。每个状态都有明确的进入条件和退出条件。用C语言写出来大概这样typedef enum { MOTOR_IDLE, MOTOR_ALIGN, MOTOR_IF_RAMP, MOTOR_IF_HOLD, MOTOR_FOC_RUN, MOTOR_FAULT } MotorState; MotorState state MOTOR_IDLE; void motor_control_isr(void) { switch (state) { case MOTOR_ALIGN: set_current_ref(I_STRT, 0.0f); theta_c 0.0f; if (align_timer T_ALIGN) { ramp_timer 0.0f; state MOTOR_IF_RAMP; } break; case MOTOR_IF_RAMP: set_current_ref(I_STRT, 0.0f); omega_c OMEGA_HAND * (ramp_timer / T_RAMP); if (omega_c OMEGA_HAND) omega_c OMEGA_HAND; theta_c omega_c * TS; ramp_timer TS; if (omega_c OMEGA_HAND) state MOTOR_IF_HOLD; break; case MOTOR_IF_HOLD: set_current_ref(I_STRT, 0.0f); theta_c omega_c * TS; if (speed_est SPEED_SWITCH pll_locked) { state MOTOR_FOC_RUN; } break; case MOTOR_FOC_RUN: // 正常FOC速度环 break; default: break; } }IF_HOLD这个状态很容易被忽略但它很重要。斜坡结束后如果没有这个短暂的保持阶段一旦转速还没完全跟稳就直接切FOC角度和速度误差都会偏大。我在IF_HOLD里会同时让PLL锁定等速度估计和角度误差都满足条件再切走。5.2 电流限幅、母线电压饱和与保护I/F强拖虽然是电流源思路但最终执行电压的是电压源逆变器。随着转速上升反电动势也在变大如果母线电压不够电流环必然饱和i_f就跟踪不上参考值。工程上一定要加一个调制比监控比如vd²vq²超过一定阈值就认为接近饱和此时可以暂停频率斜坡或者小幅降低Is给电流环留出电压裕量。另外I/F模式下功角没有直接反馈负载突变时电机可能失步。失步后的特征是相电流出现低频振铃、转子速度回退、θc和速度估算差越拉越大。固件里要加状态保护检测到速度回退超过阈值或者θc连续快速增加但速度反馈不涨立刻切到FAULT状态重新执行预定位不要让它硬转下去。这个保护在实机上非常重要能避免电机在失步状态下长时间堵转发热。我现在做低压风机驱动基本就是这套代码框架跑一年也不动。宁可多留一点启动裕量把Is给足、斜坡给慢后面运行稳定比启动快半秒重要得多。仿真代码和状态机结构都给你了照着调应该能少走不少弯路。
返回列表