
新手调无刷电机FOC最痛苦的往往不是算法看不懂而是参数调不出来。明明程序下载进去没报错电机就是嗡嗡叫不转或者转起来一顿一顿电流大得吓人。我自己刚开始玩FOC的时候也是这样对着教程一步一步敲代码结果卡在调参这一步好几周。后来回头看其实整套调校工作就两条主线一是PID参数能不能把三个闭环稳住二是转子相位准不准也就是编码器和电角度是不是对上了。这篇文章就把我实际调试无刷电机FOC过程中用过、踩过、总结过的东西完整过一遍围绕PID整定和相位校准这两件最核心的事来写。全文不会绕弯子基本按“先看整体、再动电流环、再动速度环、再对相位、最后排问题”的顺序来安排新手照着这个流程走能省掉大量瞎猜的时间。1. 调校这件事本质上是在解决三个控制环的匹配问题1.1 从电机转动的最底层逻辑说起FOC控制的最终目标是让电机转子按照我们想要的力矩、速度和位置来运动。但电机的运动本质上由电磁力矩决定而电磁力矩又直接取决于定子电流在转子磁场方向上的分量。所以FOC算法的核心就是先把三相电流解耦成力矩分量和磁通分量然后分别控制最后逆变换回三相电压输出。就拿常用的STM32F103RCT6平台来说它的主频只有72MHz算力和资源都有限但跑一整套完整的FOC中断服务程序还是够用的。常见的执行流程是定时器触发ADC采样三相电流然后做Clarke变换和Park变换得到dq轴电流送进电流PI调节器输出dq轴电压再做逆Park变换最后用SVPWM算法生成六路PWM波形。这一整套流程里有三个环从上到下嵌套在一起最内层是电流环响应最快中间是速度环带宽比电流环低很多最外层是位置环通常只在需要精确位置控制时才启用。新手拿到代码以后最容易犯的错误就是上来直接调整体不去区分自己动的是哪个环。实际上每个环的参数互相关联电流环没整定好速度环再怎么调也是白费力气。1.2 为什么PID必须是级联结构我在知乎和论坛上看到不少人问“FOC能不能只用一个PID”答案是不建议而且实际工程里几乎都是级联PID。原因在于电流环的响应速度远快于速度环如果只用一个PID去同时控制速度和电流相当于让一个调节器同时满足两个时间尺度完全不同的需求最终结果就是参数怎么选都别扭。级联结构的价值在于“内环先稳、外环才好办”。电流环带宽做到1000Hz左右速度环就算只有几十赫兹带宽依然能稳定运行。反过来如果电流环没调好速度环检测到的转速波动都是假的是电流振荡带来的不是真实的机械转速波动这种情况不管怎么动速度环PID都没用。刚开始调的时候一定要克制住“我想把三个环一口气装满”的冲动。先让电流环干净利落再让速度环平稳最后才去碰位置环。这个顺序不能乱乱了就是在给自己埋雷。2. 电流环PID整定调校路上第一道坎2.1 电流采样和坐标变换是前提电流环PID盯的是dq轴电流所以前提是采样值和真实电流能对得上。STM32F103RCT6做FOC电流采样方案常见的有两种三电阻采样和单电阻采样。三电阻采样精度最高程序也简单但要求硬件上三相下桥臂都有采样电阻单电阻方案省成本但重构三相电流的算法相对复杂低速时容易采不准。我用的板子是三电阻方案ADC触发方式和PWM中心对齐配好了采样点设定在下桥臂导通的中点附近。这里有个很容易被忽略的细节采样电阻的阻值和放大倍数直接决定了ADC读到的电压范围。比如采样电阻10毫欧放大倍数50倍母线电压12V那满量程电流大概是12除以(0.01×50)等于24A实际项目用到10A以内这个量程是合适的。ADC参考电压是3.3V分辨率为12位每字节对应的电流分辨率约为4095分之24A算出来大概是0.00586A。如果采样出来的电流乱跳先别怀疑PID参数先拿万用表或示波器看看电流采样波形。我见过有人花了两三天调参数最后发现是采样电路的地线没接好ADC读数全是噪声。先把采样数据打印出来确认静止状态下电流采样稳定不跳再开始调PID。2.2 电流环PI参数初值和调优方法电流环在dq轴上各有一个PI调节器因为d轴和q轴参数可以取一样的初值它们的电机电感电阻参数在理想情况下近似对称。初始值怎么给最简单的方法是把电机看成RL串联负载PI参数按“零极点对消”的思路来估算。电机相电阻如果是0.5欧姆相电感是0.2毫亨那么电气时间常数就是电感除以电阻等于0.0004秒也就是0.4毫秒。如果想把电流环带宽做到1000弧度每秒也就是约159Hz那么Kp 电感 × 带宽 0.0002 × 1000 0.2Ki 电阻 × 带宽 0.5 × 1000 500这就是一组可以上电验证的初始值。实际调试时先给一个很小的目标电流比如1A让电机堵转堵转的时候转子不动电流环输出会直接反映在电压上观察dq轴电流能不能快速跟随目标值且不振荡。如果电流响应慢适当增加Kp如果电流尖叫或高频振荡赶紧减小KpKi不要单独加太大因为积分作用容易让电流超调。网上流传的那张“PID最优曲线图”其实是个参考示意真实示波器上的电流阶跃响应很难做到教科书那么完美只要超调量控制在5%左右稳态误差在1%以内就能往下一环走了。2.3 前馈控制电流环快速响应的加速器热词里有人提到“PID前馈怎么使用”这里简单展开一下。在电流环里前馈的本质是“提前把反电动势和交叉耦合项补进去”让PI调节器只需要处理小误差而不是全靠反馈去追着误差跑。具体到dq轴电压方程d轴电压 电阻×d轴电流 电感×d轴电流的微分 - 电角速度×电感×q轴电流q轴电压 电阻×q轴电流 电感×q轴电流的微分 电角速度×电感×d轴电流 反电动势其中反电动势约等于电角速度×永磁磁链。如果不加前馈电机高速旋转时q轴PI要花很大力气去克服反电动势积分项会积得很大加了前馈之后PI只负责补偿模型误差和扰动响应速度和稳定性都有明显提升。新手可以先把前馈放一边等电流环反馈调节器调稳了、电机能正常转了再逐步把前馈项加进去。前馈系数先取理论值的一半观察高速下电流波形是否变平直。如果出现抖动说明前馈过强往回退一点就行。3. 速度环PID整定让电机转得稳、跟得准3.1 速度反馈的获取方式决定整定难度速度环和电流环最大的区别在于反馈量的获取。电流环的反馈来自ADC采样速度快、噪声小速度环反馈来自编码器或霍尔传感器有量化误差而且低速时候数据会变得稀疏。我用的是增量式编码器1024线四倍频后每圈得到4096个脉冲。测速方式有两种M法测速在固定时间窗口内数脉冲数适合中高速T法测速测量相邻两个脉冲的时间间隔适合低速。实际项目里经常用M法和T法结合的方案低速用T法高速用M法。如果速度反馈本身就有很大波动速度环PID是调不好的。我之前做过一个对比测试同样的PID参数用4096线编码器反馈速度波动大概正负5转每分钟换成霍尔传感器速度波动立刻变成正负20转每分钟。这个差异直接影响了速度环Kp的选择。反馈质量差的时候Kp不敢调大因为调大就会把测速噪声放大成扭矩波动。3.2 速度环参数整定的具体流程速度环参数在电流环稳定的前提下进行。给一个目标速度比如500转每分钟从很小的Kp开始比如0.02Ki先给0Kd一律先置0。观察速度响应波形。逐步增大Kp直到速度出现振荡记下这个临界值然后把Kp回退到临界值的60%到70%。接着慢慢加Ki目的是消除稳态误差。每次加完Ki要等转速稳定后再观察因为积分作用有滞后。最后如果启动过程中有明显的超调可以考虑加一点微分作用或者用位置式PID的输出限幅来限制加速度。我在实际调的时候发现速度环的积分限幅比积分参数本身还重要。如果积分限幅设得太大启动时积分项会冲得很高转速会猛超调如果限幅太小满载时又会有稳态误差。一个比较好用的经验是把积分限幅设为额定扭矩对应的电流值的10%到20%。比如额定电流5A积分输出限幅就给0.5A到1A之间。3.3 位置环、速度环和电流环的参数匹配原则带位置控制的项目里位置环一般直接用比例控制就够了位置环的输出就是速度环的给定值。三个环的带宽从内到外逐级递减通常电流环带宽为速度环的5到10倍速度环带宽为位置环的5到10倍。如果位置环参数太大电机会出现“嗡”的持续震动如果太小电机到达目标位置后像“软脚虾”一样停不住。我用过一种很简单的整定方法先调位置环的比例系数让电机从一个位置阶跃到另一个位置时不振荡、不超调然后微调速度环的阻尼效果来改善到位过程中的顿挫感。4. 相位校准比PID更隐蔽的坑4.1 电角度和转子角度的关系说到FOC就绕不开电角度这个概念。电角度是电气上磁场方向的角度它和机械角度之间相差一个极对数倍数。对于一个4对极的电机转一圈机械角度对应4圈电角度。FOC的Park变换必须知道当前转子磁极指向的电角度才能把静止坐标系下的三相电流正确变换到旋转坐标系下。这个角度从哪里来如果有编码器可以通过安装位置换算得到如果是无感方案需要通过估算算法来获取。问题是编码器安装时的零点并不一定和电机A相绕组轴线对齐所以必须做一个校准找到“编码器读数”和“真实转子电角度”之间的偏移量。我犯过的错误是估算了电角度偏移量但忘记把它加进去结果电机在开环下能转但在闭环时一给负载就抖动甚至反转。后来排查了半天发现就是初始角度偏移没校准干净。4.2 开环强制对齐法和编码器零位计算最简单的相位校准办法是开环强制对齐。具体操作如下先把位置环和速度环都禁用只保留电流环甚至直接在开环模式下输出一个固定的电压矢量。给一个方向固定、幅值合适的电压矢量让转子被电磁力矩拉到一个已知位置。通常情况下把d轴电流设为0q轴电流设为一个正向小电流转子就会被拉到与q轴对齐的位置也就是电角度等于90度或某个已知值。此时读取编码器计数值记下来这就是零点基准。接着让程序每次计算电角度时都用“编码器当前值减去零点基准”再乘以极对数得到当前电角度。如果用的是增量式编码器每次上电都要先做一次对齐。这也是为什么很多FOC代码里有一个“上电强制对齐”的过程电机上电时“咔”地响一声其实就是转子在对齐。对齐过程的电流不能太大不然会把转子撞出去、机械结构受损也不能太小否则摩擦阻力大的负载会对不齐。我用过的经验值是给额定电流的5%到10%。比如额定电流5A对齐电流给0.25A到0.5A这个力度足够克服静摩擦力且不伤结构。4.3 霍尔传感器方案下的初始位置检测带霍尔传感器的无刷电机换向逻辑依赖三个霍尔信号组合但霍尔得到的只是60度或120度电角度区间的粗略位置不能直接用于FOC。霍尔传感器的作用更像是给FOC提供一个“粗略初始角度”然后通过反电动势或编码器进行细化。带霍尔的三相无刷电机霍尔信号在任意时刻可以组合成6个扇区。比如三个霍尔信号分别为H1、H2、H3每60度电角度变化一次组合状态。如果霍尔信号和电机反电动势波形之间的相位差没有校准FOC算法里的初始电角度会有一个比较大的偏差电机启动时会顿挫甚至反转。校准方式也很直接让电机以固定方向缓慢转动同时记录霍尔状态变化时刻对应的编码器电角度把这些对应关系做成表或者直接求出平均偏移量。如果电机已经装了编码器可以用编码器角度来标定霍尔信号的边界。4.4 无感FOC的相位问题为什么更难热词里频繁出现“滑模观测器”和“无感FOC”这里补充说几句。无感FOC不依赖电机轴上的传感器转子角度全靠电流和电压重构出来本质上是在估算反电动势的相位。低速时反电动势很小信噪比差估算精度直线下降所以目前无感方案普遍对低速大扭矩这种工况不友好。如果项目必须走无感方案相位校准的核心就不再是“安装零位”了而是要调整观测器的收敛速度和增益。滑模观测器里的滑模增益不能只按一个定值来一般要结合反电动势幅值做自适应。我的建议是新手不要一上来就挑战无感先把带传感器、有编码器的方案调通把FOC的基础逻辑彻底吃透再去碰无感代码否则出了故障你根本分不清是控制算法的问题还是参数估算的问题。5. 实操演示从零调通一个STM32F103RCT6平台的FOC项目5.1 硬件连接和软件框架搭建很多新手拿着“stm32f103rct6无刷电机foc驱动代码”去搜发现网上代码版本五花八门不知道用哪份。我建议不要一上来就上复杂的开源库先用最简单的裸机代码把链路打通一个定时器产生中心对齐PWM另一个定时器触发ADC采样外部中断或定时器编码器接口读取编码器计数。硬件连接大体是这样STM32F103RCT6的TIM1输出六路PWM三路高边三路低边ADC1的三个通道通过采样电路接电机的三相下桥臂采样电阻编码器A/B相接到TIM3的编码器接口模式。软件层面中断频率通常设到10kHz到20kHz。以10kHz中断为例每个中断周期内要做的事情包括读ADC电流值、电流坐标变换、电流环PI计算、速度环PI计算可以隔几个周期跑一次、逆变换、SVPWM装载比较值。速度环如果每次中断都跑CPU负载会偏高而且速度环带宽不需要那么高所以常见做法是每5个或10个中断周期才计算一次速度环。我调试时用串口把d轴电流、q轴电流、目标速度、反馈速度、电角度这五个变量以200Hz的频率发到上位机用串口绘图软件直接看波形。这一招对排查问题极其有效比用示波器还直观因为你能同时看到多个内部变量。5.2 相位校准实操第一步程序烧录后先不要闭环运行先开一个开环测试模式给定一个固定的电压矢量。比如给q轴电压2Vd轴电压0V同时把坐标变换角度设为一个常数90度。这时候电机会把转子拉到某个固定位置用手去感受转子是否被“锁住”。如果转子没动静先确认电机是否真的通上了电压用万用表量一下电机端电压如果转子在振荡或者发热明显大概率是电流太大或者占空比不对。第二步确认转子被锁住后读取编码器计数把这个值存下来设为encoder_zero。需要留意的是这里锁定的位置对应的是q轴方向也就是电角度等于90度的位置。如果后续程序里用“电角度 (编码器当前值 - encoder_zero) × 极对数”这个公式那对齐后的初始电角度就自动是90度。第三步做一个验证让电机开环转动给一个递增的电压矢量角度观察电机的力矩和电流波形是否平滑。如果角度方向正确转速会随电压幅值线性增加如果方向反了转速会乱或者直接反转这时需要把编码器信号A/B相交换或者把电角度计算公式里的符号取反。5.3 电流环参数实测记录我用一块55mm云台电机做测试再配上400线的磁编码器。电机参数没法直接知道就用调电桥粗略凑了一下相电阻大概8.5欧姆相电感大约0.18毫亨。按零极点对消的思路算初始值Kp 0.00018 × 800 0.144Ki 8.5 × 800 6800不过这个Ki算出来偏大实际从2000开始试。给1A电流阶跃录到的波形显示上升时间大概1毫秒有小幅超调。把Kp降到0.1、Ki降到1000之后超调基本消失稳态误差在0.02A以内电流环完成。这时我特意做一个对比如果直接把论坛里流传的一套“万用FOC参数”灌进去电流波形出现持续振荡和尖锐噪声电机发热极快。这说明没有哪个参数是全工况通用的必须现场整定。5.4 速度环参数实测记录电流环稳住后我设了500转每分钟的阶跃目标。整个速度响应过程大致是这样的Kp从0.005开始转速慢慢爬升但到450转附近上不去加Ki到0.01后转速逐步追到500转再加Kp到0.02转速略超调到520转随后回落。最终Kp取0.015、Ki取0.05稳态误差在正负2转每分钟以内。在调试过程中我注意到速度环的输出直接作为电流环的目标电流值。如果速度环PI输出太大比如瞬间给出8A的电流目标电机会突然猛加速机械冲击很大。所以速度环输出的限幅也一定要有一般限制在2A到3A。这个限幅相当于是“电流保护”非常关键。6. 常见问题与排查技巧实录6.1 电机启动失败、抖动、反转怎么定位这可能是新手遇到最多的三类现象。先给个结论反转八成是相位或相序问题抖动八成是电流环参数或采样问题启动失败不出力则是电流太小或位置估算不对。先看相序是否接反。方法很简单开环让电机缓慢转动如果电机转动方向正确反电动势波形与编码器角度对齐如果相序接反电机的电磁转矩会来回拉扯出现明显顿挫。此时更换任意两相电机线再试一次能解决大部分反转问题。再看采样波形。把示波器夹在采样电阻两端看三相电流波形正不正常。FOC目标是让三相电流呈正弦分布如果电流波形是乱跳的锯齿波问题大概率是采样时刻不对。我记得有一次把ADC触发点设在PWM周期开始处结果采到的是开关噪声电流波形全部失真后来把采样点移到PWM中心后立刻恢复正常。6.2 电机发热严重、效率低电机发热大先别急着怪散热不好。电流环调好之后q轴电流应该能稳定输出力矩d轴电流应该非常接近0。如果运行中发现d轴电流不为0说明电角度不准d轴和q轴没有完全解耦导致一部分电流白白变成了热量。用上位机观察d轴电流如果它在旋转过程中有规律地波动基本可以断定相位校准没做干净。重新执行对齐过程并确认编码器零点是否可靠。另一个容易忽略的点是PWM的死区时间。死区时间设置过短会导致上下桥臂直通电流尖峰巨大发热严重设置过长则输出波形畸变、效率下降。一般在0.5到2微秒之间具体要看MOS管的开关速度。6.3 参数调好之后一换工况就崩同一个电机空载时参数调得好好的一加负载就失控这种情况我也遇到过。原因之一是没有给速度环输出做限幅导致大负载下积分项疯狂上升原因之二是电流环带宽不够带载时电流需求急剧变化但电流环响应不过来。解决方法是把速度环的积分限幅和输出限幅都加上同时重新验证电流环在大电流阶跃下的响应。如果电流环在5A阶跃下出现明显振荡说明Kp和Ki需要针对大信号重新微调。为了兼顾小信号和大信号可以尝试对电流环PI输出做抗饱和处理避免积分在限幅期间越积越大。6.4 一套完整的排查路径表现象优先排查项排查方法参考处理方案电机完全不动供电、使能、PWM输出万用表测量母线电压和控制板供电检查程序是否进入控制循环修复供电或初始化配置电机振动厉害电流采样、电流环参数用串口打印dq电流观察是否振荡降低电流环Kp调整采样点启动反转相序、编码器方向更换任意两相确认电机转向调整相序或编码器方向位启动卡死对齐电流太小、负载过重增大对齐电流但不超过额定电流10%重新做强制对齐高速上不去前馈缺失、电流环带宽不足高速下观察q轴电压是否饱和增加前馈补偿拉高电流环带宽位置到位后晃动位置环参数偏大、速度环阻尼不足减小位置环比例系数微调位置环Kp、增加速度环微分6.5 参数调试过程中的日志习惯最后提一个容易被忽略但影响长期效率的点每一次修改参数都要记录。我在电脑桌上贴了一张表格记录日期、电流环Kp、Ki、速度环Kp、Ki、相位偏移值、现象描述。这个习惯帮我避过了一个大坑有一次我把编码器换了个型号结果忘了更新零点偏移值电机表现怪怪的。翻记录表才发现零点偏移还是上一块编码器的值。调参是一项反复试验的工作过程数据就是你的经验资产。一个新项目总是从零开始摸索如果之前的数据有沉淀上手速度会快很多。我自己的流程是先看重载工况下电机能不能稳定运行再回看日志里的参数分布范围再结合负载特性做局部微调。这样每次开发新项目就像在已有基础上做小幅迭代而不是从头再碰一次壁。如果你正在调的电机一直“不听话”建议先把注意力放回电流环和相位校准这两个基础环节上。基础稳了后面的路会顺畅很多。