ARTICLE DETAIL

资讯详情

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

STM32无感FOC完整实现:IF启动到滑模观测器代码解析

STM32无感FOC完整实现:IF启动到滑模观测器代码解析 手把手教你用STM32实现PMSM无感FOC从IF启动到滑模观测器的完整代码解析做电机控制这些年我最大的感受是PMSM无感FOC这套东西理论资料满天飞但真正能把代码一行行写明白、把启动到闭环整条链路跑通的教程少之又少。很多人卡在同一个地方——原理看得懂一上板子就抓瞎或者启动那一下都过不去更别提切闭环之后观测器发散的问题。这篇文章我就把自己从IF启动到滑模观测器的完整实现过程扒开来讲代码全部基于STM32平台C语言编写配合实际调试中踩过的坑和参数整定心得希望能帮你把这条技术路线彻底走通。这篇文章适合三类人一是刚接触无感FOC、想找一个可落地参考方案的在校学生二是做电机驱动产品、需要快速完成样机验证的工程师三是想把IF启动和滑模观测器这两个核心模块单独拎出来吃透的进阶玩家。内容会涉及坐标系变换、电流环、位置估算等基础概念但我不会堆公式而是用实际代码配合工程经验把每个环节讲透。1. 整体方案架构与核心原理拆解1.1 为什么选“IF启动 滑模观测器”这套组合无感FOC的难点归根结底只有一个低速和零速时反电动势太小没法准确估算转子位置。目前业界主流的解决思路无非那么几条高频注入法、龙伯格观测器、滑模观测器、模型参考自适应。我最终选了“IF开环启动 滑模观测器”的组合原因很直接——这套方案对硬件要求低、参数整定相对简单、转速适用范围宽而且代码量可控在STM32F103这种中等性能的MCU上就能跑得动。IF启动I/F启动电流-频率启动的思路是先给电机通一个幅值恒定的电流矢量然后让这个电流矢量的相位以设定的速率旋转。因为电流环的存在定子电流会被强制锁定在给定相位上转子在电磁转矩的牵引下跟着旋转起来当转速提升到反电动势足够可观的范围后再切换成闭环运行。相比直接VF开环IF启动的优势在于全程有电流环兜底启动过程可控性强过流风险小相比高频注入IF启动不需要额外的信号注入和解调逻辑实现起来简单太多。滑模观测器则负责中高速阶段的转子位置估算。它基于电机的电压方程构造一个观测器利用滑模变结构控制的特性迫使观测电流收敛到实际电流从而提取出反电动势信息再从反电动势里解算出转子角度和转速。这套方法鲁棒性强对电机参数变化不敏感非常适合工程落地。1.2 FOC控制框架回顾Clarke变换、Park变换与双闭环结构在进入代码之前有必要把FOC的基本框架过一遍因为后面所有的启动和观测器代码都建立在这些变换之上。FOC的本质是把三相交流电机的控制问题通过坐标变换等效成直流电机的控制问题。第一步是Clarke变换把abc三相静止坐标系下的电流变换到αβ两相静止坐标系Iα Ia Iβ (Ia 2*Ib) / √3第二步是Park变换把αβ静止坐标系变换到dq旋转坐标系。Park变换需要一个角度θ这个角度就是转子电角度的预估位置。有感FOC里这个角度来自编码器无感FOC里来自观测器Id Iα * cosθ Iβ * sinθ Iq -Iα * sinθ Iβ * cosθ变换之后Id直轴电流和Iq交轴电流就变成了互相独立的两个控制量。Id控制励磁Iq控制转矩对于表贴式PMSMId0控制策略下电机的电磁转矩和Iq成正比Te 1.5 * P * ψf * Iq其中P是极对数ψf是永磁体磁链。这就是FOC的核心——通过控制Iq来线性控制转矩。整个控制回路分两层外环是速度环内环是电流环。速度环把目标转速和实际转速的误差通过PI调节器输出Iq给定电流环把Id、Iq的给定与实际反馈的误差分别通过两个PI调节器输出Vd、Vq再经过反Park变换得到Vα、Vβ最后送入SVPWM模块生成六路PWM波形驱动逆变器。1.3 IF启动和纯VF开环的本质区别很多初学者容易把IF启动和VF开环搞混。VF开环是不管电流直接给电机施加幅值和频率按比例变化的电压IF启动则是保持电流幅值恒定通过电流环强制电流跟随给定相位旋转。两者对电机状态的控制程度完全不同。VF开环的问题在于没有电流反馈意味着电机内部的实际状态是不受控的负载突变时很容易失步甚至烧毁。IF启动因为有电流环实际相电流始终被锁定在给定电流附近相当于在“电流-频率”模式下运行对负载扰动的容忍度高得多。这也是我为什么强调IF启动的代码实现里电流环参数一定要调好——它是整个启动过程稳定性的基石。2. IF开环启动的完整代码实现2.1 IF启动的核心思想与数学描述IF启动的实现逻辑非常清晰我们手动构造一个旋转的电流角度θ_ref然后把目标电流的大小分别映射到dq轴上。典型做法是让Id0、IqI_boost然后把θ_ref输入给Park逆变换计算出对应的Iα_ref和Iβ_ref作为电流环的给定值。由于电流环会快速跟踪给定定子电流合成矢量就会始终指向θ_ref方向转子会被逐步牵入同步。θ_ref的生成很关键。不能直接让θ_ref匀速增长就完事还要加入电流幅值斜坡避免启动瞬间电流冲击。整个IF启动可以分成两个阶段预定位阶段把θ_ref固定在一个角度通一个小电流持续一段时间通常200-500ms让转子的d轴被牵引到和定子电流矢量对齐的方向。这一步是为了消除初始位置的不确定性确保后续牵入过程方向一致。恒加速阶段θ_ref以恒定加速度增加转速从0逐步爬升到预设的切换速度。加速度决定了启动时间加速度太大容易失步太小又浪费时间。IF启动阶段的电角速度可以表示为ω_ref k_accel * t θ_ref 0.5 * k_accel * t² θ_initial其中k_accel是电角加速度θ_initial是预定位角度。2.2 启动参数的工程整定方法IF启动效果好坏完全取决于三个参数I_boost、预定位时间、加速斜率。这三个参数的整定我踩过不少坑分享一下我的经验值。I_boost启动电流幅值的大小直接决定启动转矩。理论上只要大于负载转矩折算的电流就能启动但实际工程中我一般取额定电流的20%~50%。取太小了转子牵入不进去会有明显的顿挫甚至反转取太大了电流冲击大母线电压会被拉低反而容易触发硬件过流保护。我的习惯是先用示波器看启动瞬间的直流母线电压跌落如果跌落超过5%就适当降低I_boost。预定位时间一般取300ms左右。这个时间不能太短因为转子从静止到对齐需要经历一段机械振荡尤其是有负载的场合。太短会导致预定位不彻底后面加速阶段转子初始角度偏差大容易失步。加速斜率是IF启动最微妙的一个参数。电角加速度不能超过电机的最大牵入同步加速度否则转子跟不上定子电流矢量的旋转速度就会失步。这个最大加速度和负载惯量、电机极对数都有关系。我的经验做法是先给一个比较保守的值比如10电角度/s²然后通过实验逐步加大直到出现失步迹象再退回80%左右。2.3 IF启动的STM32代码解析下面直接看代码。我以STM32F103为例主频72MHzPWM频率16kHz电流环每100us执行一次10kHz全部用C语言书写。首先是IF启动的状态切换结构typedef enum { MOTOR_IF_ALIGN 0, MOTOR_IF_RAMP, MOTOR_IF_SWITCH, MOTOR_CLOSED_LOOP } Motor_State_t; typedef struct { float theta_ref; // IF启动参考角度 float omega_ref; // IF启动参考速度 float i_boost; // 启动电流幅值 float accel; // 电角加速度 float align_time; // 预定位时间 float ramp_time; // 加速时间 Motor_State_t state; } IF_Start_t;然后是IF启动的主函数在电流环中断里调用void IF_Start_Run(IF_Start_t *if_start, float *id_ref, float *iq_ref) { float dt 0.0001f; // 10kHz执行周期 static float timer 0.0f; switch(if_start-state) { case MOTOR_IF_ALIGN: // 预定位角度固定只给Iq电流 if_start-theta_ref 0.0f; *id_ref 0.0f; *iq_ref if_start-i_boost; timer dt; if(timer if_start-align_time) { timer 0.0f; if_start-state MOTOR_IF_RAMP; } break; case MOTOR_IF_RAMP: // 恒加速角度按加速度积分Iq保持恒定 if_start-omega_ref if_start-accel * dt; if_start-theta_ref if_start-omega_ref * dt; *id_ref 0.0f; *iq_ref if_start-i_boost; // 判断是否达到切换速度 if(if_start-omega_ref MOTOR_SWITCH_SPEED) { if_start-state MOTOR_IF_SWITCH; } break; case MOTOR_IF_SWITCH: // 切换到闭环后的处理在外部进行 *id_ref 0.0f; *iq_ref if_start-i_boost; break; default: break; } }这里有两点需要注意。第一IF启动阶段Id0、IqI_boost这个Iq_ref会被直接作为电流环的给定值电流环会输出对应的电压矢量到电机。第二θ_ref依然要送进Park变换和逆Park变换用来给电流环反馈做坐标变换。双闭环FOC的电流环执行函数如下这里面会调用IF启动模块、编码器角度读取无感模式下用观测器角度、坐标变换和PI调节器void Motor_Control_ISR(void) { float ia, ib, ic; float ialpha, ibeta; float id_fb, iq_fb; float vd, vq, valpha, vbeta; float theta 0.0f, omega 0.0f; static float id_ref 0.0f, iq_ref 0.0f; // 读取三相电流实际只需两相第三相用基尔霍夫计算 ia Get_Phase_Current_A(); ib Get_Phase_Current_B(); ic -ia - ib; // Clarke变换 ialpha ia; ibeta (ia 2.0f * ib) * INV_SQRT3; // IF启动阶段用theta_ref闭环阶段用观测器角度 if(motor_state MOTOR_IF_ALIGN || motor_state MOTOR_IF_RAMP) { theta if_start.theta_ref; } else { theta smo.theta_est; omega smo.omega_est; } // Park变换 id_fb ialpha * cosf(theta) ibeta * sinf(theta); iq_fb -ialpha * sinf(theta) ibeta * cosf(theta); // 电流环PI调节 vd PI_Update(pi_id, id_ref, id_fb); vq PI_Update(pi_iq, iq_ref, iq_fb); // 反Park变换 valpha vd * cosf(theta) - vq * sinf(theta); vbeta vd * sinf(theta) vq * cosf(theta); // SVPWM输出 SVPWM_Set_Output(valpha, vbeta); // 运行IF启动模块更新电流给定 IF_Start_Run(if_start, id_ref, iq_ref); }2.4 IF启动阶段容易踩的坑IF启动阶段我总结出三个最容易出问题的点全是实战经验。第一个是电流环带宽不够。IF启动要求电流环快速跟踪给定电流如果电流环PI参数调得太软实际电流跟不上给定相位就会产生相位滞后。这个滞后在低速时不明显但随着加速进行会累积最终导致转子位置偏离电流矢量方向轻则抖动重则失步。我的经验是电流环PI参数至少要保证带宽在1kHz以上对应到10kHz的采样率Kp和Ki大概在几十的量级具体数值可以用TI的电流环设计工具反推。第二个是母线电容容量不足。IF启动阶段电流冲击较大如果直流母线电容偏小母线电压会出现明显的周期性纹波该纹波会耦合进电流采样导致电流环工作异常。我遇到过启动时母线电压跌落超过10%导致过压欠压保护误触发的情况后来加了一颗470uF的电解电容才解决。第三个是角度零点不统一。IF启动的θ_ref初始为0度但该角度对应的磁极位置是0度通常会有一个固定偏差。这时候如果直接切换闭环观测器和IF启动的角度有一个较大的跳变会造成电流冲击。解决办法是在IF启动的预定位阶段就把当前的Iα、Iβ记录下来估算出实际转子位置偏差在切换时把这个角度加到观测器输出上做补偿。3. 滑模观测器的原理与代码实现3.1 从反电动势到转子位置滑模观测器到底在观测什么滑模观测器的本质是一个电流观测器。它把电机的电压方程作为模型基础用实际测量的电流和施加的电压作为输入重构出电机的反电动势。在αβ静止坐标系下PMSM的电压方程可以写成Vα R*Iα L*dIα/dt - Eα Vβ R*Iβ L*dIβ/dt - Eβ其中Eα、Eβ是反电动势分量Eα -ψf * ω * sinθ Eβ ψf * ω * cosθ可以看出反电动势里包含了转子电角度θ和转速ω的信息。所以只要能把Eα、Eβ估算出来就能解算出转子位置。滑模观测器的构建思路是构造一个和真实电机结构相同的模型用滑模控制律让模型电流逼近期望电流即用滑模函数u来等效代替电压方程中的反电动势项。当电流观测误差收敛到滑模面之后控制律的输出实际上就包含了反电动势的等效信息。具体来讲d轴、q轴感应在αβ坐标系中的反电动势误差就是滑模函数经过低通滤波后的输出。滑模观测器的s函数表达式是u K * sign(i_hat - i)其中i_hat是观测器估计电流i是实际测量电流K是滑模增益sign是符号函数。3.2 滑模面设计与电流观测方程的离散实现滑模面选择的经典做法是让电流误差s i_hat - i₀ 0。当系统进入滑模状态后误差会收敛到0此时观测器的等效控制就反映了真实的电机反电动势。把电机的电压方程改写成观测器形式d(i_hatα)/dt (Vα - R*i_hatα - uα) / L d(i_hatβ)/dt (Vβ - R*i_hatβ - uβ) / L其中uα、uβ是滑模控制律输出uα K * sign(i_hatα - iα) uβ K * sign(i_hatβ - iβ)当误差收敛到滑模面后uα、uβ经低通滤波后的值就等于Eα、Eβ。在STM32上需要用一阶离散化来处理这个微分方程。我采用前向欧拉法采样周期Ts100usi_hatα(k1) i_hatα(k) Ts * (Vα - R*i_hatα - uα) / L i_hatβ(k1) i_hatβ(k) Ts * (Vβ - R*i_hatβ - uβ) / L离散化之后就可以丢进中断服务函数里循环执行了。需要注意的是这里的Vα、Vβ应该使用上一周期SVPWM输出的实际电压值而不是前馈给定值。虽然两者在理想情况下相等但考虑死区等因素如果能反馈实际母线电压进行补偿观测精度会提高不少。3.3 滑模观测器的ST代码实现我贴出一段核心的滑模观测器实现代码包含滤波和角度补偿#define SMO_KF 1500.0f // 滑模增益 #define SMO_FC 200.0f // 低通滤波截止频率(Hz) #define SMO_FCOEF (2.0f*3.14159f*SMO_FC*0.0001f) typedef struct { float ialpha_hat; float ibeta_hat; float ealpha_f; float ebeta_f; float theta_est; float omega_est; } SMO_t; void SMO_Run(SMO_t *smo, float valpha, float vbeta, float ialpha, float ibeta) { float ialpha_err, ibeta_err; float ualpha, ubeta; float ealpha, ebeta; // 当前周期的估计电流 float ialpha_hat_local smo-ialpha_hat; float ibeta_hat_local smo-ibeta_hat; // 计算误差 ialpha_err ialpha_hat_local - ialpha; ibeta_err ibeta_hat_local - ibeta; // 滑模控制律sign函数 ualpha (ialpha_err 0) ? SMO_KF : -SMO_KF; ubeta (ibeta_err 0) ? SMO_KF : -SMO_KF; // 电流观测方程离散化R0.5ΩL0.35mHTs1e-4 smo-ialpha_hat ialpha_hat_local 0.0001f * ((valpha - 0.5f*ialpha_hat_local - ualpha) / 0.00035f); smo-ibeta_hat ibeta_hat_local 0.0001f * ((vbeta - 0.5f*ibeta_hat_local - ubeta) / 0.00035f); // 滑模输出等效于反电动势经一阶低通滤波 ealpha ualpha; ebeta ubeta; smo-ealpha_f SMO_FCOEF * (ealpha - smo-ealpha_f); smo-ebeta_f SMO_FCOEF * (ebeta - smo-ebeta_f); // 注意此处加入了低通滤波相位补偿后面会细讲 smo-theta_est atan2f(-smo-ealpha_f, smo-ebeta_f); // 速度估算用角度差分加低通滤波 smo-omega_est (smo-theta_est - smo-theta_prev) / 0.0001f; smo-theta_prev smo-theta_est; }这段代码里有几个细节要展开讲一下。第一滑模增益SMO_KF的选择。这个值必须大于系统扰动的上界包括反电动势幅值、参数偏差、死区影响等因素的总和。K选小了观测器无法进入滑模状态电流误差不收敛K选大了抖振大会带来明显的噪声。我的经验做法是先按预期最高转速下的反电动势幅值取一个值比如最高电转速3000rpm、磁链0.1Wb反电动势幅值E ψf*ω ≈ 0.1 * 314 ≈ 31V那么K取50V左右就足够覆盖。然后在实际调试中用示波器观察观测电流误差的收敛情况适当微调。第二sign函数带来的抖振问题。理论上可以直接求角度导数得到转速但工程上通常不用因为抖振太严重。我的做法是对θ做差分后接一阶低通滤波滤波截止频率通常取转速环带宽的5到10倍。如果对速度精度要求更高可以考虑用自适应滤波器或者锁相环但核心思路是滤掉高频抖动。第三θ_est的计算。反电动势Eα和Eβ分别为-sinθ和cosθ的固定倍数所以θ_est atan2f(-Eα, Eβ)可以直接得到转子电角度。使用atan2f的四象限反正切函数可以返回[-π,π]范围内的角度这样换相和解算都方便。3.4 低通滤波的相位滞后补偿滑模观测器输出的反电动势经过低通滤波器后会引入相位滞后。这个滞后在转速升高时会越来越大如果不补偿估算角度会落后于实际角度导致电流矢量和转子磁极方向不一致浅则效率下降重则失步。相位滞后的补偿公式来源于一阶RC低通滤波器的相频特性θ_comp atan2(ω(实际角频率), ω_c(滤波器截止角频率))即滞后角度等于当前电角速度除以滤波器截止角速度的反正切。在代码实现上我在计算θ_est之后加上这个补偿角// 相位滞后补偿 float w_c 2.0f * 3.14159f * SMO_FC; float theta_lag atan2f(smo-omega_est_raw, w_c); smo-theta_est sm-theta_est theta_lag;这里有个需要注意的细节补偿用的ω应该是“未被延迟的”电角速度在实际中我用的是上一周期的估算值或者对θ做无延迟差分得到的速度。如果直接用补偿后的θ求差分再补偿就会形成正反馈循环角度会震荡甚至发散。另外一个常见的做法是在观测器前加超前校正环节从根轨迹上抬高系统的相位裕度。这种方案在工程上也常用但实现复杂度略高适合对动态性能要求很高的应用。我的做法是把低通滤波器的截止频率选得比较高通常是电频率的10到20倍这时候相位滞后很小然后剩下的残余滞后用前馈查表或者在线计算来补偿。3.5 滑模观测器参数整定的实操经验滑模观测器参数整定是一个反复迭代的过程我整理一下我的整定步骤第一步把电机参数R、Ld、Lq、ψf准确测出来或从数据手册中查到。这里的难点在于Ld和Lq可能会有10%以上的偏差如果查不到准确参数可以用电桥在静止状态下测量或者用辨识算法离线辨识。我实测发现L参数用不准观测器在低速段的收敛速度会受到明显影响。第二步先把K_F设成一个偏大的值保证能正常进入滑模状态。这时候不要急着看角度准不准先看电流误差是否收敛。如果误差一直在抖振而减小不了就是K_F不够大。第三步调整低通滤波截止频率。这个参数对观测质量的影响非常大。截止频率高了滤出来的反电动势毛刺多角度噪声大截止频率低了相位滞后严重动态响应变差。我的经验是从电机最高电频率的10倍开始调逐步降低直到角度波形光滑但又不明显滞后为止。第四步最后微调相位补偿。让电机在开环状态下空载运行用示波器对比观测器输出角度和实际角度用编码器对比。如果观测角度滞后就增大补偿如果超前就减小补偿。4. 从IF启动到闭环控制的无缝切换4.1 切换条件的判定IF启动阶段结束的标志一般是转速达到设定值但实际工程中不能只看转速还得看观测器状态。因为IF启动阶段反电动势是逐渐增大的观测器在前半段可能还在收敛过程中角度误差很大。此时贸然切换闭环会造成电流冲击甚至停机。我的做法是在IF启动达到目标转速后再加一个“观测器确认窗口”持续一段时间通常50~100ms在这段时间内持续检查观测器的状态。判定条件我一般用两个观测器电流误差的平均值小于某个阈值。这个阈值和电机额定电流相关一般取额定电流的1%~2%。估算角度在连续N个周期内的变化率平稳没有发生跳变或剧烈抖动。满足这两个条件后才真正切换到闭环状态。4.2 渐进式切换策略即使满足了切换条件直接一次性切换也会带来问题。因为IF启动阶段的θ_ref和观测器的θ_est之间总会有残余偏差即使在切换瞬间做了对齐速度上的偏差也会导致一个瞬态电流冲击。因此我采用渐进式切换策略在切换过程中设定一个混合角度它从IF阶段的θ_ref逐渐过渡到观测器的θ_estθ_mix (1 - α) * θ_ref α * θ_est其中α从0线性增长到1切换周期一般取50ms左右。在这个过渡期内速度环不会立刻接管而是先把Iq给定保持不变等角度过渡完成后再逐步切换速度环控制权。这样整个切换过程非常平滑电流几乎看不到冲击。4.3 切换逻辑的代码实现切换逻辑集成在状态机里控制函数如下void Motor_Switch_Control(float target_speed) { static float switch_alpha 0.0f; static float speed_int 0.0f; if(motor_state MOTOR_IF_SWITCH) { float dt 0.0001f; switch_alpha SWITCH_RATE * dt; // SWITCH_RATE 20/s50ms完成 if(switch_alpha 1.0f) { switch_alpha 1.0f; motor_state MOTOR_CLOSED_LOOP; } // 混合角度 float theta_mix (1.0f - switch_alpha) * if_start.theta_ref switch_alpha * smo.theta_est; theta theta_mix; // 渐进切换到速度环输出 float iq_speed PI_Update(pi_speed, target_speed, smo.omega_est); float iq_total (1.0f - switch_alpha) * if_start.i_boost switch_alpha * iq_speed; iq_ref iq_total; } }这段代码的关键在于混合角度的权重α按线性斜率渐进变化这个斜率决定切换时间。我推荐切换时间不要太短50ms是一个比较安全的初始值等到运行稳定后可以适当缩短。iq_ref也是渐进过渡的从IF阶段的I_boost切换到速度环PI的输出。这样避免速度环突然接管导致Iq突变。4.4 切换失败的表现与应对切换失败通常有两种典型表现。第一种是电流波形在切换瞬间出现尖峰或畸变说明角度跳变过大可能是切换前没有充分确认观测器收敛。第二种是切换后转速出现持续性振荡甚至越振越大这通常是速度环增益过大或者观测器角度存在高次谐波导致的速度反馈噪声过大。应对措施上我一般先检查观测器的角度波形质量。如果波形有明显毛刺把低通滤波截止频率降低一点如果波形有畸变确认相位补偿是否正确。速度环增益方面切换初期将PI参数设为偏弱稳定后再逐步加大千万不要一步到位。5. 常见问题与排查技巧实录5.1 典型问题速查表现象可能原因解决方案IF启动阶段电机不转或振动I_boost过小、预定位时间过短、负载惯量过大增大I_boost、延长对齐时间、降低加速斜率启动过程中电流冲击过大电流环带宽不足、角度跳跃、母线电容过小提升电流环Kp/Ki、检查切换时角度对齐、加大母线电容切换瞬间电流尖峰θ_ref和θ_est偏差过大、切速度环过快延长混合切换时间、确保观测器充分收敛切换后转速振荡速度环增益过大、观测器角度噪声大降低速度环Kp/Ki、增加观测器滤波平滑高速时观测器角度滞后低通滤波截止频率偏低、相位补偿不足适当提高SMO_FC、增大相位补偿角重载时失步滑模增益偏小、I_boost不足增大SMO_KF、提升启动电流母线电压跌落导致保护误触发直流母线电容不足、电流变化率过大增加母线电容、平滑Iq给定5.2 调试顺序建议无感FOC的调试顺序有讲究我强烈建议按照“开环→观测器→闭环”的顺序来不要跳级。第一步先跑开环IF启动只调电流内环确保母线电压、过流保护、SVPWM输出都正常。用示波器看三相电流波形是否正弦正弦度越高说明SVPWM和电流环工作越好。同时用编码器或者观察轴的转向确认旋转方向正确。第二步在IF启动运行过程中把滑模观测器的估算角度和实际角度用编码器同时打出来对比两者的波形。此时重点检查收敛性、相位滞后的方向、抖振大小等。第三步在第二步确认观测器角度已经稳定、误差可接受之后再进行IF到闭环的切换调试。这一步要重点观察切换瞬间的电流波形和转速动态响应。5.3 一些需要特别注意的工程细节最后分享几个容易被忽视的细节都是真金白银换来的教训。其一角度计算中的反三角函数代价比较高。STM32F103是M3内核没有硬件浮点单元软件浮点跑cosf、sinf、atan2f这些函数比较费时间。如果它们的执行时间占用了过多CPU可以改用查表法或者CORDIC算法来加速。实测下来在72MHz主频下一个atan2f大约需要10us左右如果三个都做一遍情况会变得很紧张。其二PID饱和处理和抗积分饱和一定不要省略。在启动阶段速度环输出Iq会持续饱和如果没有抗饱和处理积分项会累积一个非常大的值切换闭环后冲击会非常恐怖。我的做法是把积分项限制在-5A到5A的范围内同时在输出饱和时停止积分更新。其三电流采样时刻要尽量靠近PWM中心点。因为电流采样时机若不准确采样到的电流噪声会大幅影响反馈质量。我的习惯是把采样同步触发设计在PWM计数器到达中心点的时刻这样能最大程度避开上下管开关产生的噪声尖峰提高采样信噪比。其四死区补偿不能省。在无感FOC这种低速高精度控制场景下死区带来的电压误差是主要噪声源之一。我建议在电流方向判断准确的基础上做前馈死区补偿至少要在零电流交叉处做特殊处理否则低速段的观测器会比较难收敛。我在实际调试中最大的体会是无感FOC这套东西原理图多看几遍不如亲手调一遍来得深刻。IF启动、滑模观测器、切换逻辑每一个模块单独拎出来都有坑但把这些坑逐个趟平的过程才是对电机控制理解真正加深的过程。如果你按这篇文章的思路把代码搭起来遇到问题可以从排查表里找方向也可以多对照波形分析相信很快就能跑通整个链路。
返回列表