
FOC 无刷电机驱动最近在社区里出现的频率很高尤其是 STM32 方案。很多人看到“磁场定向控制”几个字就觉得门槛高但我实际跑过几轮之后发现真正容易出问题的并不是 FOC 公式本身而是电流采样、角度获取和 PWM 触发时机这三件事没对齐。这篇文章就围绕从零开始做 STM32 无刷电机 FOC 驱动这条路把硬件准备、开环验证、电流采样、闭环切换和常见排查整理一遍。适合两类人看一类是刚接触 FOC 想跑最小代码的工程师另一类是自己画过板子但程序一直调不稳定的朋友。下面按我实际落地的顺序来拆先解决“能不能跑起来”再解决“跑得稳不稳”。1. FOC 不是玄学先确认它在无刷电机驱动里到底解决什么问题1.1 无刷电机为什么需要 FOC无刷电机本身是交流电机定子绕组需要按转子位置通入交变电流。问题是三相电流怎么分配、什么时候换相直接决定了电机是安静地转还是嗡嗡响、是省电还是发热。方波驱动简单六个扇区轮流换相很多航模电调就是这么干的。但方波驱动的问题在于转矩波动大、噪音大低速时尤其明显。FOC 的思路是换到旋转坐标系里看问题把定子电流分解成产生磁场的 d 轴电流和产生转矩的 q 轴电流然后像控制直流电机一样分别控制这两个量。这样一来电机在低速、高速、负载突变时都能保持比较平滑的转矩输出噪音和效率也比方波驱动好很多。所以 FOC 解决的不是“能不能让无刷电机转起来”而是“能不能让无刷电机转得稳、转得准、效率高”。如果你只是做一个简单的风机或玩具车方波驱动可能完全够用但如果是伺服、机械臂、车规水泵、无人机这类对力矩和动态响应有要求的场景FOC 基本是绕不过去的一环。1.2 新手最容易误解的三件事第一FOC 不是某个固定库的专利。很多人搜 FOC 代码找到的是 ST 或 TI 的评估工程但这不代表你必须依赖某个闭源库。FOC 的核心是电流采样、坐标变换、PI 调节器和 SVPWM 输出这些步骤完全可以用自己的工程搭出来。第二不是必须用高配芯片才能学。STM32G4 和 STM32H7 确实因为主频高、带 CORDIC 或数学加速外设更适合做高频 FOC但 STM32F103 这类经典芯片也能跑入门级别的小电机 FOC。区别在于算力和外设余量F103 跑 10kHz 电流环也能跑只是调试和扩展时会更紧张。第三算法只占一半另一半在硬件和采样时序。我调试过程中最常遇到的不是帕克变换写错而是电流采样值跳变、ADC 触发点选错、编码器方向接反、PWM 死区不够导致开关管发热。这些问题是公式层面看不出来的必须靠波形和日志去定位。2. 硬件准备主控、驱动板、采样方案别想一口吃成胖子2.1 主控和驱动板选型主控优先从 STM32 系列里挑因为网上参考资料最多、调试工具齐全。如果只是学习手头有 F103 开发板也能先跑开环如果准备长期做项目我建议直接看带 CORDIC 或者数学加速单元的型号比如 STM32G4 系列后面写三角函数、电流环运算会省不少 CPU 资源。驱动板部分常见架构是“MCU 栅极驱动芯片 三相全桥 MOS 采样电阻”。栅极驱动负责把 MCU 的 3.3V PWM 信号放大到足以驱动 MOS 管采样电阻把相电流变成电压信号再经过运放送到 ADC。我不建议一上来就自己画驱动板。可以先买一块现成的 FOC 评估板或者开发板先跑通程序、理解信号波形再根据自己的母线电压、电流和控制需求去设计。驱动板要和主控分开供电或做好隔离处理。马达启动瞬间母线电流波动大如果逻辑电源和功率电源共用很容易导致 MCU 复位。调试时先把母线电压限制在低电压平台比如 12V 或 24V 电源慢慢加。2.2 电流采样方案对比FOC 需要至少两相电流才能重构三相电流。常见方案有三种双电阻采样、三电阻采样、单电阻采样。双电阻采样是目前最常用的方案在低侧两个桥臂各接一个采样电阻通过两个 ADC 通道同时采样两相电流。优点是比较均衡成本适中也是很多入门工程默认用的方案。三电阻采样在三相低侧各放一个采样电阻好处是每个采样周期都能获得完整的相电流对 PWM 占空比限制更小但三个运放和 ADC 通道占用更多。单电阻采样只在母线串一个采样电阻成本最低但需要在不同 PWM 矢量下多次采样并重构电流算法复杂度明显更高新手不建议先碰。有工程师会问“双电机采样组扫描双触发”和这个有没有关系。其实这类热搜词讨论的是采样 ADC 触发如果芯片支持多个 ADC 采样组可以分别配置不同的触发条件比如一组用于相电流采样另一组用于母线电压或编码器信号扫描。这对双电机或多传感器应用更有意义单电机入门先不要被这个概念带偏。2.3 编码器和反电动势采样准备如果要先做闭环编码器或霍尔传感器能大大降低角度获取难度。增量式编码器安装时要注意 Z 相或索引位置的标定需要记录电机转子与编码器零位之间的电角度偏移。绝对值编码器更省事但成本高。如果直接做无感就需要通过相电压检测或反电动势采样来估算转子位置。这时硬件上要有比较器或 ADC 通道接电机三相端电压。我建议新手从带编码器或霍尔的电机开始先把电流环、速度环跑熟再切到无感。不要一上来就无感否则后期分不清是算法问题还是角度估算问题。3. 最小 FOC 任务从开环开始角度、变换、SVPWM3.1 先跑开环而不是直接闭环很多入门资料第一步就贴闭环代码我觉得这是劝退新手的主要原因。闭环 FOC 要求电流采样、角度、PWM 输出全部正确任何一个环节不对电机表现就是抖动、飞转或过流。开环 FOC 验证的路线非常直接给定一个角度按这个角度输出三相电压电机应该匀速旋转如果电机能转说明 PWM 和逆变桥是好的。开环时角度用一个斜坡发生器或者直接给一个递增的弧度值。d 轴电压给 0q 轴电压给一个固定的值比如 0.5V 到 1V然后再经过反 Park 和 SVPWM 输出。如果电机不转先确认 PWM 波形是否正常、三相输出是否平衡、母线电容是否充足。开环跑通的意义在于后续做闭环时你能确定“电机不动”是采样或算法问题而不是驱动板和 PWM 输出问题。3.2 电角度校准和坐标变换从开环改成闭环最先要对齐角度。对带编码器的电机需要找到 d 轴位置给 U 相和 V 相通电让转子锁到一个已知机械位置记录编码器读数。这个读数就是编码器零位与电机电气零位之间的偏移。之后每次计算电角度都要用“编码器角度 偏移量”换算。坐标变换分两步。Clark 变换把三相静态坐标转换到两相静止坐标系 alpha/betaPark 变换再把 alpha/beta 转到随转子旋转的 d/q 坐标系。在 d/q 坐标系里d 轴电流对应磁场建立q 轴电流对应转矩。FOC 的电流环就是让 d 轴电流等于 0让 q 轴电流跟随目标转矩。这个变换本身公式不长但如果角度符号不对电机就会出现“带着电流也转不动”或“越转越快然后过流”的现象。所以调试时先打印角度和 d/q 电流确认反正切和正弦余弦关系正确。3.3 SVPWM 输出和死区配置Park 反变换得到的两相电压需要通过 SVPWM 生成三相 PWM 占空比。SVPWM 相比 SPWM 的好处是母线电压利用率更高输出波形也更适合无刷电机。这里最容易被忽略的是死区时间。同一桥臂上下两个 MOS 管不能同时导通否则会直通烧板。死区时间通常几纳秒到几百纳秒具体由 MOS 管关断延迟决定。死区太小容易直通死区太大会造成电流波形畸变和噪音。个人经验是从几百纳秒开始试用电流探头或电流波形观察畸变程度。4. 电流采样和 ADC 触发FOC 稳定性一半在这里4.1 为什么 ADC 触发必须在 PWM 低边导通中点FOC 电流采样不是随便哪个时刻都可以采。三相全桥的 PWM 高频开关在开关切换瞬间会有很大的 dv/dt 噪声。如果 ADC 正好在切换瞬间采样读到的电流值会叠加尖峰干扰导致电流环反馈异常。正常做法是让 ADC 在 PWM 低边导通且电流稳定时触发。这个时刻通常是 PWM 周期中点附近因为低边导通已经持续了一段时间电流采样电阻上的电压可以代表相电流平均值。使用定时器比较事件触发 ADC而不是在主循环轮询采样是保证采样一致性的关键。4.2 双电阻采样补采和最小脉宽限制双电阻采样有一个绕不开的问题当某相占空比接近 0 或接近 1 时低边导通时间太短采样窗口不够。此时无法从这一相采样电阻读到一个有效电流值。常见做法是只采样两相电流如果某一相采样窗口不够就利用“三相电流之和等于零”的关系用另一相电流反算或者通过当前扇区提前切换采样组合。这个过程中容易踩坑的是采样优先级。不要在主循环里用软件判断“现在占空比太小我改一改采样通道”因为 PWM 周期只有几十微秒软件轮询根本赶不上。正确思路是在硬件层面提前预设好采样组合规则比如根据 PWM 计数器标定值在指定时刻触发 ADC并固定从两个通道读取电流。4.3 采样电路和参数示例ADC 输入前一般需要 RC 低通滤波和运放放大电路。RC 时间常数要适中太小则滤波不足太大则电流信号延迟太大导致电流环相位滞后。下面是一个通用配置思路不代表某种特定芯片的具体配置落地时还要以你的数据手册为准// 伪配置示意PWM 定时器 ADC 触发 DMA PWM_FREQ 20kHz // 载波频率 DEADTIME 500ns // 死区初始值根据器件调整 ADC_TRIG PWM_CENTERUP // 在周期中点向上计数时触发 ADC_CH CH_PHASE_A, CH_PHASE_B // 双电阻采样 DMA_BUFF 2 // 两个通道结果同步搬运20kHz 是常用载波频率兼顾噪音和电流环带宽。如果只是入门学习10kHz 也能跑但电流环采样率和调节率会更低。4.4 常见采样问题排查电流采样数值经常出现三个问题零漂、偏置和跳变。零漂是运放输入偏置和 PCB 走线噪声造成的可以在启动前记录一个“零电流 ADC 值”运行时减去这个值。偏置是指两相采样比例不一致多半是运放电阻误差或 PCB 布局不对称用标准电流校准后可以软件补偿。跳变则优先怀疑 ADC 触发时刻太靠近 PWM 边沿或者采样保持时间太短。先把触发点在硬件上移向 PWM 中心再考虑改 RC 或运放参数。5. 从开环到闭环编码器、无感反电动势和观测器5.1 有编码器时的角度获取使用增量式编码器做 FOC最关键的是把编码器位置转换成电角度。电机极对数决定机械角度和电角度的比例。例如 7 对极电机转子转一圈电角度已经走了 7 圈。做 Park 变换时必须用“编码器角度 × 极对数 初始偏移”来计算电角度。编码器方向很关键。如果方向反了d/q 坐标系跟随的是相反旋转方向电流环输出会变成正反馈。判断方法很直接给电机一个很小的 q 轴电流看编码器读数是否朝预期方向增加。如果方向反了交换编码器 A/B 相或者在代码里反转位置增量。5.2 无感 FOC 的反电动势估算角度无感 FOC 在热搜词里被反复问核心问题是“如何通过反电动势估算角度”。反电动势是永磁体旋转在定子绕组上感生的电压它的大小和转子速度有关。中高速时反电动势波形明显可以通过检测反电动势与相电压、相电流的关系估算出转子角度。一种经典方法是滑模观测器 SMO。它构造一个电机模型让观测器输出跟随真实电流再利用观测得到的反电动势估算转子角度。这种方法在 STM32F103 上也能实现只是运算量要安排好。另一种方法是磁链观测器。通过定子电压减去定子电阻压降得到磁链变化率再积分得到磁链矢量最终从磁链矢量方向推导角度。这个思路听着简单但在低速和零速时电压很小积分漂移会被放大所以通常还要和电流模型或高频注入结合。无感 FOC 的实际难点是启动。电机静止时没有反电动势无法直接估角度。常见方案是先用开环强制旋转等转速达到一定阈值后切换到闭环估算。这个切换过程如果角度突变电机会抖动或失步所以要在开环角度和闭环估算角度之间做平滑过渡。5.3 有效磁链的计算到底是怎么回事“FOC 控制中有效磁链怎么计算”这个问题很多初学者会被术语拦住。简单地说有效磁链通常指能够产生反电动势的转子磁链也就是永磁体磁链。它可以通过反电动势波形积分估算也可以通过额定参数和电机实测得到。需要注意的是磁链不是直接能测量的只能通过模型间接获得。不同估算方法的误差来源也不同反电动势积分受采样零漂影响高频注入法受电感参数误差影响。所以在一个实际项目中磁链参数通常是通过离线辨识或对电机铭牌参数修正得到的而不是每次运行都重新算。如果你在做一个无感 FOC 项目不要一上来就追求磁链估算精度。先用默认参数让电流环稳定再逐步加入磁链观测和角度补偿。这个顺序能避免你同时面对电流噪声、角度噪声和磁链误差排错时一次只解决一个变量。6. 调参与排查参数、波形、日志和故障定位6.1 电流环 PI 参数怎么调FOC 的电流环是内环速度环是外环。调参顺序必须是先电流环后速度环。电流环 PI 初始值建议给得保守一点。比例系数从很小开始比如先给一个不会让电流过冲的值积分系数也从小开始。然后让目标 q 轴电流从一个固定值跳变观察电流实际响应波形。调参时看三个指标响应速度、超调量、稳态误差。响应太慢就加大比例超调太大就减小比例或者增强微分阻尼稳态误差明显就加积分。但需要注意电流环的积分不能加得太猛否则母线电压饱和后会产生积分饱和导致过流。实际项目中不建议在代码里频繁改动参数。可以先把 PI 参数做成上位机可调变量记录一组响应好的参数后再写回代码。6.2 启动失败、噪音、飞车的排查顺序遇到问题先看现象再查输入再查环境最后查参数。启动失败电机不动或轻微抖动优先看角度。如果开环角度没有持续递增或者编码器方向反了电机就不会正常转动。其次看电流采样值如果样值为 0 或跳变PI 输出到 SVPWM 的结果就不对。电机噪音大优先看采样触发点和死区。采样点靠近 PWM 边沿时电流反馈噪声会被放大声音会很暴躁。死区太大或太小时电流波形会产生低频振荡或高频谐波噪音也明显。飞车和过流是最危险的故障。出现这种情况先断开电机或限制母线电流再查角度符号、PI 输出限幅、编码器偏移和采样偏置。很多飞车问题的根源是角度在某个方向上没有正确递增导致电流环在错误的坐标系里持续输出正向电压。务必在初始调试时加入电流保护代码或者使用限流电源。不要等过流了再保护电调或驱动板可能已经烧了。6.3 调试工具和日志建议FOC 调式不能只靠仿真器看变量。我建议把以下变量通过串口或调试器打印成波形三相电流原始值电角度d/q 轴电流目标电流与实际电流SVPWM 输出的三相占空比母线电压故障标志有了这些数据你才能确认某个现象到底是采样问题、角度问题还是参数问题。没有日志只凭电机声音判断很容易走弯路。如果使用 STM32CubeMonitor 或类似工具做实时波形更好。即使没有图形化工具也可以用串口把数据框拉出来自己在 Python 或 MATLAB 里画图。6.4 双电机或双触发采样的注意点如果后期要做双电机 FOC需要考虑的不只是算法复杂度翻倍还有外设资源冲突。两个电机各需要一套 PWM 定时器、ADC 采样通道和电流采样电路。假设芯片只有一个 ADC 或多个 ADC 但共享同一个触发源就要规划好触发顺序。“双电机采样组扫描双触发”热搜词在实践中的含义是两个 ADC 采样组可能需要不同触发条件比如第一个电机在 PWM 周期中点采样第二个电机在另一个相位延迟点采样或者一组采样相电流另一组扫描编码器、霍尔和电压信号。这种场景下建议先单独验证每个电机单机 FOC 稳定再合并到同一个工程。不要一开始就写双电机联合控制否则出现问题很难定位是哪一路电机引起的。7. 从 Demo 到产品边界与流程7.1 学习场景和生产场景的差异如果你的目标只是把 FOC 跑通默认配置通常够用。你可以用开发板、编码器、低速小电机慢慢调。但如果是要做成产品场景就不同了。产品需要考虑母线电压波动、过流保护、过温保护、欠压保护、堵转检测、宽电压输入、不同批次电机参数差异等问题。软件上还要考虑故障恢复、参数标定、上位机和批量测试。一个常见误区是“开发板能转所以方案成熟”。开发板环境是理想环境电压稳定、没有电磁干扰、电机参数清楚、负载不大。产品现场可能电压下降、线缆更长、电机负载突变FOC 代码需要加对应的保护逻辑才能长期运行。7.2 建议的工程化流程如果从零做项目我建议按下面这个顺序推进先做硬件验证确认 PWM 输出、死区、母线电压、过流保护都正常。先跑开环确认电机能转方向正确。再做电流采样校准检查零漂、偏置和 ADC 触发点。然后闭环电流环d 轴电流追踪 0q 轴电流追踪目标值。最后加速度环/位置环根据应用需求套外环。如果做无感最后再切无感算法并增加启动和切换策略。这个过程会比其他“直接套库”的方式慢但每一步都有明确的验收标准后续排错会省很多时间。7.3 写在最后的经验踩过几次坑之后我发现FOC 里很多问题不是工具能力不够而是前置环境和输入材料没有处理干净。电流采样时序不对、编码器方向反了、母线电容不足、调试日志太乱这些问题累积起来会让代码看起来“有 bug”实际上硬件和程序各占一半责任。如果你刚接触 FOC不建议同时做太多功能。先跑通单电机、单电阻或双电阻、单闭环把波形和日志看明白再扩展无感、双电机、高速弱磁。 FOC 能跑起来不难难的是在异常情况下还能稳定下电和输出正确转矩那才是真正要花时间的地方。如果你是初学者先别急着追求复杂观测器用一个带编码器的电机跑通 10kHz 电流环把每一步波形都看懂就已经比很多人强了。