十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

STM32无感FOC实战:PMSM初始位置检测与闭环调试全记录

STM32无感FOC实战:PMSM初始位置检测与闭环调试全记录 做FOC磁场定向控制的人应该都有这种体会看着仿真波形跑起来很简单一到真机就各种幺蛾子。我这阵子正好在整理手里的无感FOC项目版本号懒得起什么霸气名字直接叫FOC-P2-DRAFT_V2.0——P2是Project二期DRAFT表示还在调试中的草稿版本V2.0则是推翻第一版框架后的重构。这个项目要解决的核心问题就是用STM32做一套PMSM无感矢量控制的最小系统把转子初始位置检测、电流环速度环整定、开环强拖切换闭环这几块硬骨头啃下来同时把整套流程跑顺方便后面接不同的电机和负载。这篇文章会把这一版的设计思路、调试难点、波形陷阱和踩坑记录全部摊开讲适合刚接触FOC、正准备从Simulink仿真往真机移植的同学参考。1. 项目定位与整体设计思路1.1 版本命名里的演进脉络FOC-P2-DRAFT_V2.0这个名字看着像随手敲的其实含义很明确。P2说明这个项目已经进入第二个阶段不是从零开始讲概念而是在已有基础上做迭代DRAFT说明它目前仍然是调试中的草稿版本很多参数还在边跑边改V2.0则表示我把第一版的整体框架推倒重来了不是简单地在旧代码上打补丁。第一版最大的问题是把控制逻辑、底层驱动和故障保护全部写在同一个.c文件里导致调试时改一个PI参数都要重新编译整个工程更别提波形抓取和上位机交互。所以V2.0一开始我就把代码拆成了模块同时把电流环中断频率从10kHz提到20kHz。第一版做这个改动的时候中断周期里的计算量差点扛不住换成G4系列之后才真正跑起来。这一版项目的核心目标是用STM32G474系列MCU做一套PMSM无感FOC控制器的最小系统。之所以选择G4系列是因为它内部带了CORDIC和数学加速单元坐标变换和SVPWM计算能省不少CPU周期而且ADC触发可以直接由定时器产生比较适合做20kHz电流环。项目要覆盖的内容包括无感转子初始位置检测、电流环速度环参数整定、无感启动策略、波形调试以及从Matlab/Simulink模型到嵌入式代码的移植。这套流程走通之后再往别的电机平台迁移基本就是改参数和调采样电路的事。对于刚接触FOC的读者我建议你也照着这个节奏来先跑通位置检测再整定电流环最后碰速度环和启动别一上来就追求各种高级无感算法。1.2 无感FOC的主控制链路不管是不是无感FOC的核心链路都绕不开那几步采集两相或三相电流做Clarke变换把abc轴系的电流转到αβ轴系再做Park变换转到dq旋转坐标系在dq坐标系里把电流解耦成励磁分量id和转矩分量iq分别走两个PI调节器输出d轴和q轴电压再做逆Park变换得到αβ轴系的电压矢量最后通过SVPWM生成六路PWM波形驱动逆变器。无感和有感的最大区别就是坐标变换需要的转子角度和电角速度不是来自编码器或霍尔传感器而是靠观测器估算出来的。这个角度估算的准确度直接决定了电流环能不能解耦也决定了电机高速运行时会不会发烫、会不会震动。我在V2.0里用的是滑模观测器来估算反电动势进而得到转子位置和速度。滑模观测器的好处是鲁棒性强、参数依赖少坏处是会有抖振滤波之后会带来相位滞后所以需要在低速段做角度补偿。这个补偿量跟转速和负载有关不能设成一个固定值后面波形调试的部分我会详细说。整条控制链的调度是这样的定时器产生PWM中间对齐信号触发ADC采样三相电流采样完成后进入ADC中断在中断里完成Clarke、Park、电流PI、逆Park和SVPWM计算最后更新比较寄存器速度环放在主循环里以2kHz的频率运行通过一个系统tick来节流。这样分频的好处是电流环响应快速度环又不会因为占用太多CPU而拖垮中断周期。实际测试下来20kHz电流环加上2kHz速度环CPU负载大概在四成左右还有余量跑通讯和故障保护。2. 转子初始位置检测无感FOC第一道难题2.1 为什么初始位置检测让人头疼PMSM无感控制最尴尬的阶段就是启动那一刻。电机没转起来的时候转子反电动势等于零滑模观测器完全没有输入信号位置估算自然就是瞎猜。如果带着负载直接给一个固定方向的电压矢量转子可能会短暂抖动然后朝一个不确定的方向启动严重的时候直接过流报警。表贴式PMSM的转子结构是对称的在静止状态下从定子侧看过去电感几乎不随转子位置变化这就把高频注入法的一个关键前提给堵住了。内嵌式永磁电机因为存在凸极效应高频注入信号在d轴和q轴上的阻抗响应不同能够解算出位置角但表贴式电机凸极性非常弱解调信噪比很低处理不好根本看不出位置信息。这个问题的本质是在没有反电动势可用、又缺乏凸极特征的情况下从零开始给系统提供一个转子位置初值。对启动性能要求不高的场景比如风机、水泵通常允许启动瞬间有几次抖动用预定位就足够了但对伺服或机器人关节这样要求快速响应且不能反转的场合就必须上高频注入或者更复杂的信号激励方案。我在项目里先选了预定位来保证可靠性因为第一优先级是把整套FOC流程跑通而不是一上来就研究高难度的启动算法。不过我也在底层代码里预留了高频注入的接口等预定位方案稳定之后再慢慢往上迭代。2.2 V2.0里用的预定位方案V2.0的启动流程里我把预定位放在最前面。具体做法是在闭环电流环运行之前直接给逆变器输出一个固定的电压空间矢量方向选在某一相绕组上。这个矢量的幅值不能太大我给的是额定电压的10%到15%持续200ms左右。在这个电压作用下定子电流会产生一个固定方向的磁动势把转子拉到一个已知的电气角度。对于120°或60°的扇区选择只要保证这个拉力足够大能克服静摩擦和负载力矩转子就会转到与空间矢量对应的位置上。预定位结束后控制代码把观测器的初始角度设成这个已知角度而不是默认的0这样电流环一启动就能工作在正确的dq坐标系下。这个方案操作简单代码量也很小但它有明显代价如果负载扭矩超过定位力矩转子根本转不到位后续启动会失败另外预定位必然伴随着一次开环的电流冲击在机械结构比较脆弱的场合不太友好。所以我把这个方案定义为DRAFT版本的过渡方案后面会上高频注入。不过实际测试时我用一个200W的小型PMSM做了验证空载和轻载情况下预定位都能在100ms左右完成切换到闭环后没有任何反转效果比我预想的好。如果你只是做风机、泵类负载预定位其实已经够用了不要为了追求算法复杂度而给自己挖坑。2.3 后续准备替换的高频注入思路高频注入法并不是直接把高频电压信号加到电机上而是在原来电压指令的基础上叠加一个高频正弦或方波信号然后通过带通滤波器把相应的高频电流响应提取出来再经过特定的解调算法得到转子位置误差信号。对表贴式PMSM来说最常用的是旋转高频电压注入法或者脉振高频电压注入法。脉振高频注入法是只在估计的d轴注入高频电压由于凸极性引起的磁饱和效应就算表贴式电机会有微弱的饱和凸极也会在q轴感应出位置误差信号。解调出来的位置误差信号再进一个锁相环收敛之后就能得到转子角度和速度。V2.0的底层驱动里我已经预留了叠加高频分量的接口电流环输出之后、逆Park变换之前可以插入一个高频电压分量。注入频率一般选在载波频率的1/10到1/5之间比如20kHz的电流环注入频率2kHz到4kHz比较合理。注入幅值需要折中太小了解调出来全是噪声太大了会带来明显的转矩脉动和损耗我身边朋友的经验是先从母线电压的5%开始试然后观察高频电流响应波形逐步调整。解调环节通常需要在采样后的电流上做带通滤波、与注入信号相乘、再低通滤波这一串操作在G4系列MCU上跑起来比较顺畅但放在老一些的芯片上就得注意CPU负载。注意高频注入的电压幅值一定要受逆变器直流母线电压余量约束注入电压加上正常FOC输出电压不能超过SVPWM的最大线性输出范围否则会产生畸变导致解调失效。3. 电流环与速度环的实现细节3.1 电流采样和坐标变换FOC算法的质量很大程度取决于电流采样准不准。V2.0用三电阻采样方案在下桥臂三个开关管的源极各放一个采样电阻然后在PWM中间对齐的瞬间也就是上下桥臂切换时通过ADC一次性采集三相电流。这个方案的优点是成本低、信号没有相移只要采样窗口避开开关管的开通关断噪声就能拿到比较干净的电流值。问题是三相电流并不是在所有占空比组合下都能采到比如某一相占空比太极端对应采样电阻上的导通时间太短ADC还没完成采样电流就换向到续流二极管了。所以我在软件里加了个最小脉宽限制SVPWM输出前会对调制比做削顶处理保证每相的脉宽都大于一个阈值。坐标变换的代码实现里最容易出错的是角度对齐。Park变换用的角度必须是转子磁链的电气角度如果观测器输出的角度有偏差dq轴电流就会出现耦合id和iq互相干扰。调试时我发现一个现象给定iq为正实际iq和id都有响应而且id和iq的纹波相位相近这基本可以判断是角度偏了。另外电流采样值的零点偏移也要校准我通常在电机上电后、未使能PWM之前采集100次电流取平均作为一个偏置保存下来。每次开机都这样做一次能显著降低低速时的电流谐波。不要小看这个步骤很多空载电流大、电机嗡嗡响的问题最后查下来就是零点偏移没校准。3.2 电流环PI参数的计算方法电流环是FOC中最内层的环响应速度必须快。我采用的是经典的带宽法来整定PI参数。对于表贴式PMSMd轴和q轴电感基本相等都在L值附近在连续域里电流环的传递函数可以近似成一个一阶惯性环节设计闭环带宽为ωbw那么PI参数可以直接用以下公式估算Kp L * ωbw Ki R * ωbw这里的单位需要统一。L的单位是亨利R是相电阻ωbw的单位是rad/s。比如一个2mH、0.5Ω的电机想要电流环带宽2kHz也就是约12566 rad/s那Kp就是2e-3 × 12566 ≈ 25.1Ki就是0.5 × 12566 ≈ 6283。这个公式只是起点因为实际系统有PWM延迟、采样保持、死区以及逆变器非线性直接套公式往往偏激进需要根据阶跃响应微调。我的经验是先把Kp设成计算值的50%调好之后再慢慢往上加观察相电流是否出现高频振荡。Ki可以先保持计算值但如果稳态误差已经很小可以适当减小Ki避免积分项在动态过程中添乱。离散化的时候电流环PI的输出限幅也要对上SVPWM的调制范围。我用的表贴式电机没有弱磁需求所以id的给定一般设成0id环的输出限幅可以放宽iq环的输出限幅则要根据最大相电压预留一部分给死区补偿和初始位置检测。限幅值设得太小会限制电机的高速性能太大会在过载时把调制比推向非线性区导致电流波形畸变。我实际取的是0.95倍相电压峰值给死区和电压跌落留一点余量。调试时通过串口或上位机实时查看id、iq、vd、vq的值比看一大堆寄存器方便得多。3.3 速度环整定与抗饱和速度环在电流环外面响应速度慢一个数量级。V2.0里速度环用2kHz频率运行转速给定来自上位机或者内部斜坡发生器。速度环PI参数如果用手工试凑会非常痛苦我建议用工程设计法起步先把速度环简化成一个积分环节加一个一阶惯性环节把系统的开环截止频率设计在电流环带宽的1/10到1/20之间然后按典型I型系统整定。比如设定速度环开环截止频率为50Hz即约314 rad/s那么速度环的比例系数大致等于电机转动惯量乘以截止频率除以转矩常数再乘以一个采样周期相关的缩放系数。实际操作时我会先用Simulink里的线性分析工具算出理论值再上真机微调。速度环最常遇到的问题不是参数而是积分饱和。当电机被堵转或给定转速突变时积分项会积到一个很大的值速度一旦恢复这个积分值释放出来会让系统超调甚至震荡。我在代码里做了两种处理一是积分分离当速度误差超过一定阈值时暂停积分二是输出限幅后把PI输出与限幅值的差反馈回积分项做anti-windup。第二种方法比较平滑相当于把多余的控制量往回冲销实测下来对启动阶段的速度过冲改善非常明显。如果你用的是位置伺服速度环前面还要加位置环位置环通常是纯比例控制加前馈这里的经验是先整定速度环再反过来调位置环的比例不要倒着来。4. 无感启动策略与波形调试4.1 I/F强拖切换到闭环的完整流程无感FOC的启动不能像有感电机那样直接切速度环因为在静止状态下反电动势为零观测器算出来的速度可能是零角度也可能是错的。V2.0里我采用I/F强拖的方式启动时电流环仍然工作但电流给定不是来自速度环而是来自一个固定的电流幅值和递增的电角度。这个电角度由软件生成一个斜坡频率从零缓慢上升相当于一个虚拟的旋转磁场拖着转子同步启动。斜坡的加速度要控制好通常设成2到5Hz每秒钟带载时还要再慢一点太快的加速度会丢失同步导致转子失步电流迅速增大。当虚拟频率上升到约10Hz电频率时反电动势已经足够大滑模观测器能收敛出一个可信的位置和速度这时就可以做闭环切换。切换的瞬间最怕角度和速度突变我在代码里做的是在强拖过程中持续运行观测器但不用它控制切换时先用锁相环把观测器的速度对齐到当前虚拟速度角度则累加到一个公共变量里之后再逐步把给定电流的来源从强拖斜坡切到速度环的输出。这个先对齐再切换的过程说白了就是让观测器的输出平滑地接管原来虚拟量所扮演的角色避免电机因为控制量跳变而抖动。我在这里吃过亏第一次切换时没有做角度对齐结果切换瞬间电流直接从3A飙到12A触发了过流保护。4.2 示波器上该看哪些FOC波形调试FOC没有示波器基本上等于盲人摸象。我最常抓的波形有这么几路相电流、母线电流、估算速度、估算角度和SVPWM的相电压输出。相电流波形用电流探头看重点看是否接近正弦、有没有明显的削顶或畸变。如果速度稳定时电流包络出现周期性波动多半是角度估算误差在变化如果电流高频振荡先检查电流环PI是不是太激进再看采样是否踩到了开关噪声。母线电流和母线电压要一起看特别是在启动和加载瞬间母线电压跌落如果超过5%说明母线电容容量不够或者输入线太细。估算速度和实际速度的对比也很重要我在调试板上留了一个编码器接口方便用编码器做参照。当观测器估算速度与实际速度的偏差在稳态时低于1%并且动态时能跟上才认为观测器调好了。SVPWM输出波形主要用来检查死区是否设置合理如果死区时间太长相电压波形上会出现明显的台阶太短则会因为上下桥臂直通炸掉功率管。我一开始用1.5μs死区对于关断延迟200ns的驱动芯片够用后面提高载波频率到20kHz后死区占比变大电流波形谐波也变大后来调整到1μs才平衡了可靠性和波形质量。这里顺便提醒一句示波器探头的接地线一定要用最短的接地弹簧别用那个长鳄鱼夹否则你看到的开关尖峰全是地环路引出来的假象。5. 从Simulink仿真到STM32移植5.1 仿真模型的搭建要点在真机上调试之前在Simulink里做一版PMSM无感FOC仿真模型可以帮你提前躲开很多低级错误。模型里最重要的事情不是拖动几个模块而是把离散系统的延迟模拟出来。很多初学者直接用一个连续模型跑得到的结果在真机上完全对不上因为连续模型忽略了采样保持和PWM零阶保持器的延迟。我建议在反馈回路上加一个单位延迟模块再把PWM逆变器用零阶保持器等效这样仿真出来的电流环阶跃响应和真机测试比较接近。仿真步长也可以设成和真实电流环周期一致比如1/20000秒这样模型和代码之间可以逐拍对比。Simulink里的PMSM模型要用标么值还是实际值取决于你后面打算做代码生成还是手工编码。如果只是验证算法必须关注坐标变换的方向和角度定义。我记得自己在第一版仿真里踩过一个大坑Matlab的PMSM模块默认转子角度是机械角度加上极对数关系而我自己编的坐标变换用的是电气角度两者没对齐导致仿真里电流环完全发散。后面我干脆不用自带的PMSM模块而是直接用dq轴的电压方程自己写了一个电机模块这样角度、电流、反电动势的关系完全透明反而更容易排查问题。想省事的话可以用Simscape Electrical里的PMSM模型但一定要确认它的角度单位和方向说明。5.2 STM32代码框架与关键配置V2.0的嵌入式代码我尽量把算法写成与芯片无关的C语言函数底层驱动单独放一层。核心代码是一个状态机包括初始化、预定位、强拖、闭环运行、故障保护几个状态。初始化状态里完成ADC校准、观测器初值清零、PWM输出禁用预定位状态给固定矢量强拖状态执行I/F路径闭环状态走正常的矢量控制流程。主循环里跑状态机、速度环和通讯ADC中断里跑电流环和观测器。状态机的好处是任何异常都能跳到故障保护状态防止电机失控烧掉功率板。关键的配置信息可以做成一个结构体方便在调试过程中一键修改。比如typedef struct { float pole_pairs; // 极对数 float rs; // 相电阻单位欧姆 float ls; // 相电感单位亨 float flux_linkage; // 永磁体磁链单位韦伯 float current_bw; // 电流环带宽单位rad/s float speed_bw; // 速度环带宽单位rad/s float pwm_freq; // PWM载波频率单位Hz float deadtime; // 死区时间单位s float start_accel; // 强拖加速度单位Hz/s float i_start; // 强拖电流幅值单位A } foc_motor_config_t;这些参数我建议全部放在一个config文件里每个电机一套配置换电机时直接切换配置结构体就行。ADC触发配置上我用的定时器中央对齐模式两个通道分别触发ADC1和ADC2确保在PWM周期中点采样电流。DMA把所有采样结果搬到内存中断里直接取数。这里的时序一定不能错错了轻则电流波形杂乱重则过流。如果你不想用DMA也可以在中断里直接读ADC寄存器但要注意寄存器组切换不然读到的是上一周期的数据。5.3 FOC电路板设计的几个注意点电路板和算法其实是相辅相成的算法再好板子上采样电阻选大了发热就够喝一壶的。三相采样电阻的阻值选择需要用采样电阻压降不超过运放输入范围同时损耗可接受这个原则来算。比如电流峰值30A采样电阻1mΩ压降30mV再经过运放放大几十倍送到ADC如果选10mΩ压降300mV损耗就有9W这个功率对电阻来说太狠了。所以大电流场景下采样电阻得往小了选然后用低噪声运放做放大。运放的带宽要足够高至少是电流环带宽的5到10倍否则采样信号会滞后。驱动电路的死区电阻电容、自举电容的容量也是老坑。自举电容太小高占空比时上桥驱动电压会掉到欠压阈值以下导致上管关断异常电容太大虽然在低频时稳定但会拉长自举充电时间影响启动。我一般按经验公式把自举电容选在100nF到1μF之间同时保证PWM死区时间大于驱动芯片的传输延迟。另外电流采样回路的走线要远离功率管的开关节点最好走差分对绕过电感、MOS管的G极和D极跳变区域否则你的ADC采到的全是尖峰。PCB布局上母线电容要尽量靠近逆变器桥臂减小母线的寄生电感否则开关瞬间的电压尖峰会非常高轻则干扰采样重则击穿功率管。6. 常见问题与排查技巧实录6.1 问题现象对照表我把这版调试过程中遇到的最典型问题整理成了表格方便大家对照排查。现象可能原因排查方法解决办法启动时过流报警预定位角度不对或强拖加速度过快先降低I/F电流幅值观察启动电流增大预定位时间减慢加速度检查电机相序高速时相电流畸变发烫角度补偿不足SVPWM过调制抓相电流波形查看削顶增加观测器角度补偿减小最大调制比空载电流大且嗡嗡响电流采样零点偏移未校准上电后采集ADC偏置打印加入开机自动校准采样均值保存强拖能转一切闭环就抖动观测器角度追赶不上切换瞬间角度跳变抓虚拟角度和估算角度波形对比先锁相环对齐速度再平滑切换电流源母线电压跌落严重母线电容容量不足或走线电感过大用示波器看母线电压纹波增加电解电容缩短母线回路长度相电流有毛刺采样窗口踩到开关噪声调整采样触发点或增加滤波器扩大最小脉宽限制加RC滤波这张表看着简单但每一项背后都对应着好几天的调试。特别是相序问题如果电机的UVW三相对调或者霍尔方向反了系统会完全不受控然而代码层面一点错误提示都没有只能靠检查连线。我后来在做完一套板子后先写一个简单的开环测试程序让电机按照固定的六个电压矢量依次通电如果电机能一格一格地正向转动就说明相序和坐标变换方向是对的。别小看这个测试它能帮你排除掉一半以上的底层问题。6.2 几条独家避坑心得第一点是调试前先确认PWM波形和ADC触发时序。不要一上电就开始跑FOC先给一个固定占空比的PWM用手转动电机轴在示波器上看电流采样点是否干净。没有这个准备后面所有波形异常都很难定位。我见过很多人调了半天电流环最后发现是ADC触发沿搞反了采样的电流全是错的这种问题光看代码根本发现不了。第二点是参数标定要自动化。我把相电阻、相电感和磁链的测量都用脚本实现上电后自动跑一遍短路测试和直流衰减测试把数据存到Flash里。手动拿万用表量出来的电阻值包含了线缆和接触电阻和驱动器里实际值差不少用自动标定能稳定很多。尤其是温度变化之后铜绕组的电阻变化很明显不考虑的话电流环参数就漂了。第三点是版本管理要细。FOC调试过程中PI参数、观测器增益、启动参数会反复改我吃过很多次这次调好了但忘了记参数的亏。现在每个版本草稿都会把关键参数写进文件名比如FOC-P2-DRAFT_V2.0_iq_start_4A_acc_3Hz回滚或者对比测试都方便。另外每次调参后顺手截一张示波器波形图标注当时的参数后面写调试记录时整理成文档会省很多时间。最后再分享一个小技巧无感FOC最难判断的其实是观测器到底准不准。如果你手头有编码器别急着拆掉把它当成一个对照仪表一直放在系统里调试时同时看编码器角度和观测器角度两个角度的差就是估算误差。等确认观测器在全速度范围内都可靠了再彻底丢掉编码器这样能减少非常多排查半天结果发现是观测器没收敛的痛苦。FOC控制本身并不神秘但每一环都藏着很多细节把这些细节一个一个抠过去你的无感FOC项目就离稳定落地不远了。
返回列表