1. 无感FOC的角度困局为什么滑膜观测器的抖动让人头疼搞过无感FOC的人都有一个共同的痛电机在中低速运行时转子角度估计值像心电图一样上下跳动电流波形毛刺明显听觉上能听到明显的啸叫严重的时候电机直接失步堵转。这个问题的根源十有八九出在滑膜观测器SMO身上。滑膜观测器的本质是一个bang-bang控制结构它通过一个高频切换函数通常是sign函数强制估计电流跟踪实际电流然后从切换信号中提取反电动势再反正切算出角度。问题就出在这个“bang-bang”上——切换函数天然带来高频抖振chattering这个抖振会直接传导到角度估计上表现为角度抖动。虽然可以通过低通滤波器LPF平滑但LPF又引入了相位延迟角度滞后了转矩响应就变差高速时甚至直接发散。我在一台STM32F407上跑无感FOC的时候就遇到过这个经典问题电机在1000rpm以下角度抖动超过±15°电流THD飙到12%以上低速段根本没法用。试过调滑膜增益、换用饱和函数代替sign函数、加二阶LPF效果都有限——要么抖动压下去了但动态响应变慢要么响应快了抖动又回来了。这是一个结构性的矛盾不是调参能根本解决的。后来我把目光转向了PLL锁相环。PLL在电力电子和通信领域用得很成熟它的核心思路是不直接从反电动势反正切求角度而是构造一个角度跟踪环路用PI调节器让估计角度“锁”住实际角度。这样出来的角度是连续平滑的抖振被环路滤波器天然抑制而且PI调节器可以做到零相位延迟的跟踪效果。实测下来同样一台电机换成PLL之后角度抖动从±15°降到±3°以内电流THD降到5%以下低速段也能稳定运行到300rpm。这篇文章就是把我从滑膜观测器切换到PLL的完整过程拆开来讲——为什么PLL能解决抖动、STM32F4上怎么配置定时器和ADC、PLL的参数怎么算、代码怎么写、调试时踩了哪些坑。如果你也在被无感FOC的角度抖动折磨这篇内容应该能帮你少走不少弯路。2. 方案选型PLL凭什么替代滑膜观测器2.1 滑膜观测器的结构性缺陷要理解PLL为什么好得先搞清楚滑膜观测器为什么抖。滑膜观测器的基本方程是这样的di_est/dt (1/L) * (V - R*i_est - E_est) E_est K_slide * sign(i_est - i_actual)其中sign函数在电流误差过零时瞬间切换输出正负这个切换频率理论上无限高实际受限于离散采样频率。每次切换都会在估计反电动势上叠加一个高频分量这个分量就是抖振的来源。传统做法是加LPF滤掉高频抖振但LPF的截止频率和相位延迟是一对矛盾截止频率越低抖振滤得越干净但相位延迟越大。对于FOC来说角度延迟直接导致dq轴解耦不准确转矩脉动增大。我实测过用一阶LPF截止频率设在200Hz时角度延迟在1000rpm下大约滞后8°这个滞后量在高速弱磁区是致命的。更麻烦的是滑膜增益K_slide的选取也很讲究增益太大抖振加剧增益太小滑膜面到达速度慢动态响应差。而且这个增益还跟电机参数电感、电阻相关不同电机要重新调通用性差。2.2 PLL锁相环的核心优势PLL的思路完全不同。它不直接求角度而是构造一个误差信号让估计角度通过PI调节器去跟踪实际角度。具体来说从滑膜观测器或者龙伯格观测器得到反电动势的αβ分量E_α、E_β之后构造误差ε -E_α * cos(θ_est) - E_β * sin(θ_est)当θ_est接近实际角度θ时ε近似等于K*(θ - θ_est)也就是说误差信号与角度差成正比。然后把这个误差送进PI调节器PI的输出就是估计转速转速积分得到估计角度。这样就形成了一个闭环锁相结构。PLL的优势在于第一PI调节器本身就是一个低通滤波器高频抖振被自然抑制不需要额外的LPF也就没有额外的相位延迟第二PI参数可以根据带宽需求设计跟踪性能和抗扰性能可以量化第三角度输出连续平滑不会出现反正切函数的跳变问题。我实测对比过两种方案在同一台电机上的表现指标滑膜观测器LPF滑膜观测器PLL角度抖动1000rpm±15°±3°电流THD12%5%最低稳定转速800rpm300rpm突加负载恢复时间200ms80ms参数整定难度高增益LPF截止频率中PI带宽从表里能看出来PLL方案在各项指标上都有明显优势。尤其是最低稳定转速从800rpm降到300rpm这意味着低速应用场景比如电动工具、云台也能用无感方案了。2.3 STM32F4的硬件适配性分析选STM32F4来做这件事主要是看中几点第一F4系列有FPU浮点运算单元PLL的PI运算和三角函数运算都是浮点操作有FPU的话单次运算只要几个时钟周期不会成为瓶颈第二F4的定时器资源丰富TIM1和TIM8都是高级定时器支持互补PWM输出和死区插入正好用来驱动三相逆变桥第三F4的ADC采样速率够快12位精度下最高可达2.4MSPS三电阻采样或者单电阻采样都够用。具体型号我选的是STM32F407VGT6168MHz主频192KB SRAM1MB FlashLQFP100封装。这个配置对于FOC来说绰绰有余PLL的运算量大概只占CPU的5%不到。如果你用的是F401或者F411主频低一点84MHz或100MHz但跑PLL也完全够只是PWM频率和电流环频率可能要适当降低。注意STM32F4的定时器位数不一样TIM1和TIM8是16位高级定时器TIM2~TIM5是32位通用定时器TIM6/TIM7是16位基本定时器。做FOC的时候PWM用TIM1或TIM8电流环触发用TIM2或TIM332位方便做长周期计数不要搞混了。3. 核心细节解析PLL锁相环的数学原理与参数计算3.1 从反电动势到角度误差信号PLL的输入是反电动势的αβ分量。假设电机反电动势为正弦波E_α -ω * ψ_f * sin(θ) E_β ω * ψ_f * cos(θ)其中ω是电角速度ψ_f是永磁体磁链θ是实际电角度。估计角度为θ_est构造误差信号ε -E_α * cos(θ_est) - E_β * sin(θ_est)展开ε ω * ψ_f * sin(θ) * cos(θ_est) - ω * ψ_f * cos(θ) * sin(θ_est) ω * ψ_f * sin(θ - θ_est)当θ - θ_est很小时sin(θ - θ_est) ≈ θ - θ_est所以ε ≈ ω * ψ_f * (θ - θ_est)这个误差信号与角度差成正比比例系数是ω * ψ_f。注意这个系数与转速有关低速时系数小误差信号幅值也小所以PLL的带宽需要根据转速自适应调整或者用归一化处理。3.2 PI调节器参数计算PLL的环路是一个典型的二阶系统。PI调节器的传递函数G_pi(s) Kp Ki/s整个闭环传递函数忽略反电动势幅值变化θ_est(s) / θ(s) (Kp*s Ki) / (s^2 Kp*s Ki)这是一个标准二阶系统自然频率ω_n和阻尼比ζ分别为ω_n sqrt(Ki) ζ Kp / (2*sqrt(Ki))通常取ζ 0.707最佳阻尼ω_n根据期望的带宽确定。如果希望PLL带宽为f_bw则ω_n 2 * π * f_bw Ki ω_n^2 Kp 2 * ζ * ω_n我实际用的参数是f_bw 50Hzζ 0.707算下来ω_n 2 * 3.14159 * 50 314.16 rad/s Ki 314.16^2 98696 Kp 2 * 0.707 * 314.16 444.2但这是连续域的参数实际在STM32F4上跑的是离散域需要做离散化。我用的是后向差分法Kp_d Kp Ki_d Ki * Ts其中Ts是电流环周期。我的电流环频率是10kHzTs 0.0001s所以Kp_d 444.2 Ki_d 98696 * 0.0001 9.87提示PLL带宽的选择要折中。带宽太高抖振抑制不够带宽太低动态响应慢突加负载时角度跟踪不上。我试过20Hz到100Hz最后50Hz是最平衡的。如果你的电机惯量大、负载变化慢可以降到30Hz如果要求快速动态响应可以升到80Hz但要注意抖振会相应增大。3.3 离散化实现与定点/浮点选择STM32F4有FPU所以直接用浮点运算就行不用折腾定点。代码里用float类型编译时开启FPU在Keil里勾选Use FPU在STM32CubeIDE里默认开启。离散化后的PLL迭代代码大概长这样// PLL状态变量 float theta_est 0.0f; // 估计角度 float omega_est 0.0f; // 估计转速 float pll_kp 444.2f; // PI比例增益 float pll_ki 9.87f; // PI积分增益 // 每次电流环调用 void PLL_Update(float E_alpha, float E_beta, float Ts) { // 计算角度误差 float sin_theta arm_sin_f32(theta_est); float cos_theta arm_cos_f32(theta_est); float error -E_alpha * cos_theta - E_beta * sin_theta; // PI调节器 float omega_delta pll_kp * error; omega_est pll_ki * error * Ts; // 积分项 // 限幅 if (omega_est OMEGA_MAX) omega_est OMEGA_MAX; if (omega_est -OMEGA_MAX) omega_est -OMEGA_MAX; // 积分得到角度 theta_est (omega_est omega_delta) * Ts; // 角度归一化到0~2π if (theta_est 2.0f * PI) theta_est - 2.0f * PI; if (theta_est 0.0f) theta_est 2.0f * PI; }这里用了ARM的DSP库里的arm_sin_f32和arm_cos_f32比标准库的sinf/cosf快不少。实测在168MHz下一次PLL_Update大概耗时2.5μs10kHz电流环周期是100μs占用率2.5%完全没压力。注意theta_est的归一化很重要。如果不做归一化theta_est会一直累加float精度有限累加到一定程度后小数部分会丢失导致角度精度下降。我一般用2π归一化也有同行用65536归一化对应16位角度效果差不多。4. STM32F4实操从定时器配置到PLL代码落地4.1 定时器与PWM配置PWM用TIM1中心对齐模式频率设16kHz。为什么选16kHz因为人耳听觉范围上限是20kHz16kHz刚好在听觉范围边缘电机啸叫不明显同时16kHz的开关损耗也可以接受。如果你对噪声不敏感可以降到10kHz开关损耗更低如果要求静音可以升到20kHz但MOSFET发热会增加。TIM1的配置关键参数// TIM1初始化中心对齐模式 htim1.Instance TIM1; htim1.Init.Prescaler 0; // 不分频168MHz htim1.Init.CounterMode TIM_COUNTERMODE_CENTERALIGNED1; htim1.Init.Period 5250; // 168MHz / (2 * 16kHz) 5250 htim1.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; htim1.Init.RepetitionCounter 0; htim1.Init.AutoReloadPreload TIM_AUTORELOAD_PRELOAD_ENABLE;Period的计算中心对齐模式下PWM频率 定时器时钟 / (2 * Period)。所以Period 168000000 / (2 * 16000) 5250。死区时间设200ns对应死区寄存器值 200ns * 168MHz 33.6取34。死区时间的选择取决于MOSFET驱动器的开关速度和MOSFET本身的开关时间一般取100ns到500ns。我用的IR2101驱动器加IRF3205 MOSFET200ns够用。// 死区配置 sBreakDeadTimeConfig.DeadTime 34; // 200ns sBreakDeadTimeConfig.BreakState TIM_BREAK_DISABLE; sBreakDeadTimeConfig.DeadTimeConfig TIM_DEADTIME_DTG_0;4.2 ADC采样与电流重构电流采样用三电阻方案在PWM下桥臂导通时采样。具体来说用TIM1的CH4触发ADC触发点设在中心对齐模式的下溢事件这时候下桥臂全部导通采样电阻上的电压就是相电流。ADC配置// ADC1初始化 hadc1.Instance ADC1; hadc1.Init.ClockPrescaler ADC_CLOCK_SYNC_PCLK_DIV4; // 42MHz hadc1.Init.Resolution ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode ENABLE; hadc1.Init.ContinuousConvMode DISABLE; hadc1.Init.DiscontinuousConvMode DISABLE; hadc1.Init.ExternalTrigConv ADC_EXTERNALTRIGCONV_T1_CC4; hadc1.Init.ExternalTrigConvEdge ADC_EXTERNALTRIGCONV_EDGE_RISING; hadc1.Init.DMAContinuousRequests ENABLE; hadc1.Init.NbrOfConversion 2; // 采两相第三相计算得出采样两相电流比如Ia和IbIc -Ia - Ib。采样时机很关键必须在PWM下溢点附近这时候下桥臂导通采样电阻上有电流。如果采样点偏了采到的就是开关噪声电流波形会乱七八糟。提示ADC采样到PLL更新之间要做Clarke变换和滑膜观测器更新。我的顺序是ADC中断 - 读取Ia/Ib - Clarke变换 - 滑膜观测器更新 - PLL更新 - Park变换 - 电流PI - 反Park - SVPWM输出。整个链路在10kHz中断里跑完实测耗时约8μs余量充足。4.3 滑膜观测器与PLL的衔接PLL的输入是滑膜观测器输出的反电动势。滑膜观测器的离散化实现// 滑膜观测器状态 float I_alpha_est 0.0f, I_beta_est 0.0f; float E_alpha_est 0.0f, E_beta_est 0.0f; float slide_gain 0.5f; // 滑膜增益 void SMO_Update(float I_alpha, float I_beta, float V_alpha, float V_beta, float Ts) { // 电流估计误差 float I_alpha_err I_alpha_est - I_alpha; float I_beta_err I_beta_est - I_beta; // 滑膜控制项用饱和函数代替sign减少抖振 float Z_alpha slide_gain * sat(I_alpha_err, 0.1f); float Z_beta slide_gain * sat(I_beta_err, 0.1f); // 电流估计更新 I_alpha_est (V_alpha - R * I_alpha_est - E_alpha_est) * Ts / L; I_beta_est (V_beta - R * I_beta_est - E_beta_est) * Ts / L; // 反电动势估计低通滤波 E_alpha_est (Z_alpha - E_alpha_est) * Ts * LPF_FC; E_beta_est (Z_beta - E_beta_est) * Ts * LPF_FC; }这里用了饱和函数sat代替sign饱和阈值0.1A。饱和函数比sign函数平滑抖振本身就小一些再配合PLL效果更好。LPF_FC是低通滤波截止频率我设的是500Hz这个LPF只是为了提取反电动势不参与角度计算所以相位延迟不影响角度。然后PLL的输入就是E_alpha_est和E_beta_estPLL_Update(E_alpha_est, E_beta_est, Ts);这样整个链路就通了ADC - Clarke - SMO - PLL - Park - PI - SVPWM。4.4 参数整定与调试步骤参数整定我一般按这个顺序来第一步先不跑PLL用开环强拖的方式让电机转起来确认PWM输出正常、电流采样正常、SVPWM扇区判断正确。这一步可以用示波器看相电流波形应该是正弦波如果波形畸变严重先查硬件。第二步跑滑膜观测器但不接PLL直接把E_alpha和E_beta做反正切求角度观察角度波形。这时候角度应该有明显抖动这是正常的。如果角度完全乱跳说明滑膜增益不对调slide_gain直到角度大致跟踪实际角度。第三步接入PLL先把PLL带宽设低一点比如20Hz观察角度是否平滑。如果角度平滑但跟踪不上突加负载时角度偏差大逐步提高带宽到50Hz。如果角度又开始抖说明带宽太高了降回去。第四步调电流环PI。电流环带宽一般设PLL带宽的5到10倍我设的是500Hz。电流环PI参数可以用零极点对消法算Kp L * ω_cKi R * ω_c其中ω_c是电流环带宽。注意调试的时候一定要先低压比如12V小电流试确认没问题再升压。我见过有人直接上48V参数不对直接炸MOSFET的。另外PLL的积分项一定要限幅不然启动瞬间误差大积分饱和了角度会飞。5. 常见问题与排查技巧实录5.1 角度抖动依然大怎么办如果换了PLL之后角度还是抖先查这几个地方第一滑膜观测器的反电动势估计是否干净。用DAC输出E_alpha_est示波器看波形。如果反电动势上叠加了大量高频噪声说明滑膜增益太大或者LPF截止频率太高。把slide_gain降一半LPF_FC降到200Hz试试。第二ADC采样时机是否准确。如果采样点不在下溢点采到的电流里有开关噪声这个噪声会一路传到PLL。用示波器同时看PWM下桥臂驱动和ADC触发信号确认触发点在下桥臂导通中间。第三PLL带宽是否过高。把带宽从50Hz降到30Hz如果抖动明显减小说明就是带宽问题。但带宽降了动态响应会变慢需要折中。第四电机参数是否准确。滑膜观测器依赖R和L如果这两个参数偏差大反电动势估计就不准。用LCR表实测电机相电阻和相电感填到代码里。5.2 低速时角度跟踪不上低速时反电动势幅值小PLL的误差信号也小跟踪能力下降。解决办法有两个一是用归一化PLL把误差信号除以转速或者反电动势幅值这样低速时误差信号不会被衰减二是低速时切换到IF强拖模式等转速上来了再切到PLL。我用的是归一化PLL代码里加一行float E_mag sqrtf(E_alpha_est * E_alpha_est E_beta_est * E_beta_est); if (E_mag 0.01f) { error error / E_mag; // 归一化 }这样低速时误差信号不会被幅值衰减跟踪能力明显改善。实测最低稳定转速从800rpm降到了300rpm。5.3 启动时角度飞掉启动时电机静止反电动势为零PLL没有输入角度是随机的。如果直接跑PLL角度可能锁到错误的位置导致启动失败。我的做法是启动前先做一次预定位给d轴通一个固定电流比如额定电流的30%持续500ms把转子拉到d轴对齐位置这时候角度设为0。然后再切到PLL闭环。预定位电流不能太大不然电机会发热也不能太小不然拉不动。30%额定电流是个比较安全的经验值。5.4 常见问题速查表现象可能原因排查方法解决措施角度抖动大PLL带宽过高降低带宽到30Hz折中带宽与动态响应角度抖动大滑膜增益过大减小slide_gain配合饱和函数使用角度抖动大ADC采样噪声示波器看采样点调整触发时机低速跟踪不上反电动势幅值小检查E_mag归一化PLL或IF强拖启动角度飞初始角度随机检查预定位加预定位流程高速发散PLL积分饱和检查限幅加积分限幅电流波形畸变死区时间不对示波器看相电流调整死区值电机发热严重PWM频率过低检查TIM1配置提高到16kHz以上提示这张表是我调试过程中实际遇到的问题汇总每个问题都踩过坑。尤其是ADC采样噪声那个我一开始没注意调了三天PLL参数都没用后来用示波器一看采样点偏了2μs正好采在开关瞬间改过来之后角度立刻稳了。5.5 独家避坑经验第一个坑STM32F4的FPU默认可能没开。在Keil里要在Target选项里勾选Use FPU在STM32CubeIDE里要在项目属性里设置Float ABI为Hardware。如果FPU没开浮点运算会走软件模拟速度慢10倍以上10kHz中断根本跑不完。第二个坑arm_sin_f32和arm_cos_f32的输入范围是0到2π如果theta_est超出这个范围输出会不对。所以每次更新完theta_est一定要归一化。我一开始忘了归一化跑了半小时后角度突然跳变查了半天才发现是float精度丢失。第三个坑PLL的PI输出是转速但实际代码里我把它拆成了比例项和积分项分别处理。比例项直接加到角度增量上积分项累加到omega_est上。这样做的原因是比例项只影响瞬态积分项影响稳态分开处理方便限幅和调试。第四个坑滑膜观测器的LPF截止频率不能太低。我试过设到100Hz反电动势估计倒是干净了但幅值衰减严重PLL的误差信号太小低速时根本锁不住。后来设到500Hz幅值和噪声都平衡得不错。6. 实测效果与性能对比6.1 波形对比用同一台电机24V额定转速3000rpm额定电流5A分别跑滑膜LPF和滑膜PLL用DAC输出角度估计值示波器抓波形。滑膜LPF方案1000rpm时角度波形上有明显的高频毛刺峰峰值大约±15°电流波形THD实测12.3%。滑膜PLL方案同样1000rpm角度波形平滑峰峰值±3°以内电流THD降到4.8%。低速段对比更明显滑膜LPF在800rpm以下就开始失步PLL方案能稳定跑到300rpm角度抖动仍然在±5°以内。6.2 动态响应对比突加50%额定负载滑膜LPF方案角度恢复时间约200ms转速跌落约15%PLL方案角度恢复时间约80ms转速跌落约8%。PLL的动态响应明显更好原因是PI调节器可以设计成最佳阻尼而LPF的相位延迟会恶化动态性能。6.3 CPU占用率在STM32F407上168MHz主频10kHz电流环PLL_Update耗时约2.5μsSMO_Update耗时约3μs整个FOC中断耗时约8μsCPU占用率8%。加上串口通信、保护逻辑等总占用率约15%。余量充足还可以跑一些上层逻辑。项目滑膜LPF滑膜PLL角度抖动1000rpm±15°±3°电流THD12.3%4.8%最低稳定转速800rpm300rpm突加负载恢复时间200ms80msCPU占用率7%8%参数整定难度高中从表里能看出来PLL方案在性能上全面优于滑膜LPF代价是CPU占用率高了1个百分点这个代价完全可以接受。6.4 不同转速下的表现我测了从300rpm到3000rpm的全转速段PLL方案在300rpm时角度抖动±5°1000rpm时±3°3000rpm时±2°。高速时抖动更小因为反电动势幅值大PLL的误差信号信噪比高。低速时抖动稍大但通过归一化处理已经能满足大部分应用需求。如果你需要更低速比如100rpm以下PLL可能就不够了需要考虑高频注入或者IF强拖配合。但对于大多数风机、水泵、电动工具应用300rpm的最低转速已经够用了。7. 代码结构与工程组织建议7.1 文件划分我的工程里FOC相关代码分成这几个文件foc_config.h电机参数、PLL参数、SMO参数的宏定义foc_math.c/hClarke、Park、反Park、SVPWM等数学变换foc_smo.c/h滑膜观测器实现foc_pll.c/hPLL锁相环实现foc_current.c/h电流环PI控制foc_main.c/hFOC主状态机负责调度各模块这样划分的好处是模块解耦换电机只需要改foc_config.h里的参数换观测器算法只需要改foc_smo.c和foc_pll.c不影响其他部分。7.2 中断优先级安排STM32F4的中断优先级安排很关键。我的配置是ADC中断电流环优先级0最高TIM1更新中断PWM优先级1串口中断优先级2系统滴答优先级3ADC中断必须最高因为电流环对时序要求最严格。如果ADC中断被其他中断打断电流环周期就会抖动影响PLL性能。7.3 参数宏定义示例// foc_config.h #define MOTOR_RS 0.5f // 相电阻欧姆 #define MOTOR_LS 0.001f // 相电感亨利 #define MOTOR_PSI_F 0.01f // 永磁体磁链韦伯 #define MOTOR_POLE_PAIRS 7 // 极对数 #define PWM_FREQ 16000 // PWM频率Hz #define CURRENT_LOOP_FREQ 10000 // 电流环频率Hz #define PLL_BANDWIDTH 50.0f // PLL带宽Hz #define PLL_DAMPING 0.707f // PLL阻尼比 #define SMO_SLIDE_GAIN 0.5f // 滑膜增益 #define SMO_LPF_FC 500.0f // 滑膜LPF截止频率Hz这些参数里MOTOR_RS、MOTOR_LS、MOTOR_PSI_F、MOTOR_POLE_PAIRS必须根据实际电机实测填写不能随便估。其他参数可以按经验值先填调试时再微调。注意MOTOR_PSI_F的准确测量比较麻烦可以用反电动势法用另一台电机拖动被测电机旋转测开路反电动势幅值E则ψ_f E / ω其中ω是电角速度。如果没有拖动条件可以用额定电压和额定转速估算但精度差一些。8. 扩展思路从PLL到更高级的观测器PLL解决的是角度平滑问题但它的输入还是滑膜观测器的反电动势。如果滑膜观测器本身在低速时反电动势估计不准PLL也救不了。所以下一步可以考虑用龙伯格观测器或者扩展卡尔曼滤波EKF替代滑膜观测器从源头提高反电动势估计精度。龙伯格观测器的全阶形式可以同时估计电流和反电动势没有滑膜观测器的抖振问题低速性能更好。但龙伯格观测器对电机参数更敏感R和L的偏差会直接影响观测精度。EKF则更进一步可以同时估计转速和角度但计算量大STM32F4上跑EKF可能有点吃力需要优化。我目前正在试龙伯格PLL的组合初步结果看低速能到200rpm角度抖动±4°比滑膜PLL稍好。等调稳定了再分享。另外PLL的参数也可以做成自适应低速时降低带宽保证稳定高速时提高带宽保证跟踪。这样全转速段都能有比较好的性能。实现方式是根据omega_est动态调整Kp和Ki代码里加个分段函数就行。这个方案后续还可以扩展到无感FOC的弱磁控制。弱磁区反电动势幅值下降PLL的误差信号变小需要配合电压反馈或者电流反馈做补偿。这部分我还在摸索有进展了再写。最后分享一个小技巧调试PLL的时候可以用串口把theta_est和实际角度如果有编码器的话同时输出到上位机用Python画个对比图一眼就能看出跟踪效果。没有编码器的话可以用开环强拖时的角度作为参考虽然不准但至少能看出PLL有没有锁住。我用的串口波特率是92160010kHz下每100个周期发一次数据上位机用matplotlib实时显示调试效率高很多。
阅读完成 · 觉得有帮助?