
B-G431B-ESC1 这个板子我用了挺长一段时间前阵子一个同行发来一个问题电机没接、动力电也没上打开 Motor Pilot 看电流波形Iq 直接冒出来一个不小的数值问是不是板子的采样电阻烧了。我让他先别急这类现象在 FOC 调试里太典型了——不是硬件坏了多数情况下是零点没校准。这篇文章就把我排查这个问题的完整链路、背后的原理、以及最终的修复方法好好梳理一遍给后面踩到同一个坑的人一个参考。1. 先别怀疑硬件Iq 非零的物理背景与现象边界1.1 确认你看到的是“哪个 Iq”先说个容易被忽略的点界面里显示的 Iq 到底是以什么单位、从哪个环节读出来的Motor Pilot 默认的电流观测窗口里你可以选择看实际电流单位 A也可以看经过标幺化之后的内部数值比如百分比或 Q 格式甚至可以直接看 ADC 原始码。同样是“Iq 非零”含义完全不同。我一般拿到这种问题第一件事不是打开原理图而是让对方把 Motor Pilot 的截图上发来。很多时候界面上显示的所谓“Iq”其实是内部变量Iq的标幺化表示。在做 FOC 时内部电流环的基准值和反馈值通常是 Q15 或 Q24 格式的定点数0 这个点在内部并不一定对应 0 电流。如果你看的是原始内部变量那么一个非零的Iq可能只是定点数换算偏差甚至就是一两百个码值换算成实际电流只有几十毫安根本不值得一提。真正需要警惕的是单位明确是安培A显示值却有 0.5A 甚至更高。这时候才说明电流采样链路里有东西不对。1.2 未接电机为什么还能“测”到电流很多初学者会把“电流采样”理解成一个简单的测量过程有电流就有读数没电流读数就是零。但在 FOC 的硬件设计里电流采样电路始终是上电工作的它不会因为电机没接而“睡着”。B-G431B-ESC1 这类板子的电流检测结构是低侧采样电阻shunt把相电流变成毫伏级电压再经过运放放大进入 STM32G431 内部的 ADC。G431 内置了三路可编程运放正好配合三电阻采样方案。关键问题来了运放是单电源供电的只能输出 0~3.3V 之间的电压而相电流是双向的正负都会流。如果 0 电流时运放输出 0V那负电流就没办法表示了。所以电路设计上必须给运放设定一个直流工作点通常就是 VREF/2也就是 1.65V。也就是说无电流时运放输出不是 0V而是 1.65V。这个电压进入 ADC 之后12 位采样得到的理想码值大约是 2048。这本身是正常的但如果你在软件里没有把“2048”这个基准扣掉而是直接把 2048 当成电流换算的起点那结果就会是一个巨大的虚假电流。可以用一个生活化的类比这就跟电子秤一样空秤状态下如果没有先做去皮tare上面放一个空箱子也会显示 10 公斤。你这时候不能说称坏了而是没清零。1.3 不校准的话最大虚报电流能有多少我习惯把这个误差量化出来因为只有知道极限值才能判断当前显示的数值是否落在“未校准偏移”的量级范围内。换算公式很简单I_fake_max (VREF / 2) / (Gain * Rshunt)其中 VREF 是 ADC 参考电压通常是 3.3VGain 是运放增益Rshunt 是采样电阻阻值。B-G431B-ESC1 的采样电阻具体值以板子原理图为准不同批次可能有区别。我用两个典型参数算一下采样电阻 Rshunt运放增益满量程电流范围未校准时虚报电流0.05 Ω16±2.06 A≈ 2.06 A0.01 Ω10±8.25 A≈ 8.25 A看到没有如果完全不处理零点Iq 直接显示一个接近满量程的电流值而且这个值比很多小电机的额定电流还大。别说外行有些做过一阵子驱动的人看到这个数也会第一时间怀疑采样电阻烧了、运放坏了、甚至板子的地线有问题。实际上这只是“没做 offset 校准”的典型症状。2. 从运放偏置到 Park 变换Iq 究竟是怎么算出来的2.1 电流采样链路盘点电阻、运放和 ADC要真正理解这个问题得把从电流到 Iq 的完整信号链捋一遍。FOC 控制算法本身是不知道“电流”这个东西的它能看到的只是 ADC 数字。整个链路是这样的相电流流过采样电阻 → 产生差分电压 → 运放按固定增益放大 → 加上直流偏置 → ADC 采样得到 12 位码值 → 软件换算成实际电流值 → 经过 Clarke 变换得到 Ialpha/Ibeta → 经过 Park 变换得到 Id/Iq。任何一个环节的误差都会反映到最后 Iq 上。在没有接电机、没有动力电的情况下采样电阻上不可能有真实的相电流但运放输入端的共模电压还在运放本身的失调电压也还在。换句话说链路的前半段依然在输出一个“有意义的电压信号”只是这个电压不代表电流。经常被忽略的一点是G431 内置运放的增益并不是无限可调的它有几档固定的增益配置比如 2、4、8、16、32 倍具体型号略有差异。MC Workbench 生成工程时会根据你填的采样电阻和最大电流值自动选增益。如果这块配置和实际硬件对不上也会导致电流读数成比例偏大或偏小。2.2 单电源运放的“1.65V 谜团”为什么偏偏是 1.65V因为 ADC 的参考电压是 3.3V而电流需要双向测量所以电路设计者会把零电流点放在量程正中间。这样一来正电流 → 运放输出高于 1.65V零电流 → 运放输出约等于 1.65V负电流 → 运放输出低于 1.65V这个 1.65V 就是“零电流偏置”。ADC 采样到 1.65V 时码值是 2048。软件必须记录这个 2048并且在之后每一次读取 ADC 时都先减掉它再去做电流换算。问题往往出在这里如果初始化阶段没有执行零点采样或者采样的时机不对adc_offset变量就是 0。那么下一次实时电流换算时I (raw_adc - 0) * resolution2048 这个码被当成真实电流信号算出来的当然不是 0。实测下来如果运放增益和采样电阻的乘积比较大这个虚假电流甚至会触发过流保护导致电机根本启动不了——这是比“Iq 显示非零”更严重的连锁反应。2.3 Clarke/Park 变换对偏移量做了什么那么问题来了既然三相采样电路基本对称各路的零点偏移都接近 2048经过 Clarke 变换后两个偏移量相减是不是就抵消了理论上如果三相 ADC 的偏移量完全一致Clarke 变换确实能消除共模偏移。但现实中不可能完全一致三路运放的失调电压不同三路采样电阻的阻值有误差ADC 各路通道的偏置也略有差异。所以经过 Clarke 变换后Ialpha 和 Ibeta 上会残留一个很小的直流分量。Park 变换呢在电机未启动、状态机处于 IDLE 阶段时转子电角度通常是一个固定值或无效值。很多实现里此时角度保持为 0而 Park 变换在 θ0 时的表达式是Iq -Ialpha * sin(0) Ibeta * cos(0) Ibeta也就是说这时候 Iq 基本上直接等于 Ibeta 采样残差。如果 Ibeta 因为零点偏置没消干净Iq 自然就显示非零。这也就解释了为什么很多人只盯着 Iq 看因为在界面里 Iq 是控制环最关心的量最容易被关注到。实际上此时 Ialpha、Ibeta 同样非零只是没那么显眼。3. 完整排查链路顺着显示值一路往根上挖3.1 第一步冻结现象看清单位与变化规律拿到问题后我先让他做这样几件事确认 B-G431B-ESC1 通过 USB 供电ST-LINK 的 3.3V 正常输出。之所以强调这点是因为如果连控制电都没接MCU 根本不会工作更谈不上显示 Iq。所以“没接 power”指的是没接主回路动力电板子的控制电路必须在工作。在 Motor Pilot 里停掉电机其实本来就没启动打开电流观测窗口记录 5 秒钟的 Iq 波形。观察这个非零值是恒定直流还是有规律波动。这一步的区分意义很大如果 Iq 是一条水平直线大概率是零点偏移问题如果 Iq 随角度在 sin 曲线附近波动那可能是有外部干扰或者角度信号本身在更新如果是杂散噪声量级又很小这就纯属正常不需要处理。3.2 第二步抓原始 ADC 码把“电压”和“电流”分开看这一步是判断问题在硬件还是软件的关键。用调试器比如 ST-LINK 自带的 SWD 接口连接板子直接读取 ADC 数据寄存器或者把 MC Workbench 生成的工程里电流采样函数返回的原始ADC_DR值打出来。重点看三个东西三路 ADC 原始码是否都在 2048 附近三路之间的差异是否在几十个码以内把板子静止放置几秒码值是否稳定。如果三路都接近 2048说明运放和 ADC 硬件工作正常问题百分百在软件换算端——没有正确扣 offset。如果某一路偏差特别大比如只有 1500 或者 2500那才需要怀疑那一相采样电阻虚焊、运放增益配置错误、或者 PCB 走线干扰。我当时让同行读出来的三路 ADC 码分别是 2042、2051、2047非常标准的三路均偏。这就直接排除了硬件故障锁定了软件 offset 环节。3.3 第三步核对 SDK 生成的校准流程是否执行B-G431B-ESC1 搭配 STM32 Motor Control SDKMC Workbench 生成工程使用时偏移校准是内置状态机的一部分。正常情况下在电机启动之前、主回路 PWM 还没有输出的时候SDK 会先执行一次偏移校准采样若干次 ADC 值取平均存成内部偏移量。需要检查的两个点一是确认 MC Workbench 工程里电流采样配置是否选对了采样方式。如果是三电阻采样那三路 ADC 的触发必须和 PWM 同步并且在同一个时刻一起采样。二是确认工程代码里有没有被改过。很多人在调试时会手动加代码、屏蔽初始化流程可能把校准这段状态机跳过了。SDK 的状态机里MCI_CalibrateCurrent()这类操作名称可能随 SDK 版本不同略有差异必须保持在启动流程中。如果被注释掉或者被用户自己的初始化代码覆盖就会出现“未校准直接开跑”的情况。3.4 第四步检查校准时序是否被破坏还有一个隐蔽的坑校准函数确实执行了但执行的时机不对。偏移校准的逻辑是“在当前时刻所有采样点都处于零电流状态的前提下把 ADC 输出记录为基准”。如果校准那一刻 PWM 已经启动电机绕组里已经有电流在流动那么这次校准采到的“基准”里混入了真实电流。更典型的场景是电机启动后你手动触发了一次重新校准。这相当于把正在运行的电流当成了零点后面的 Iq 输出会出现一个巨大的直流偏置。校准只能在零电流状态下做这个前提一旦打破校准结果就是垃圾。另外提醒一句如果电机接了但没接电源你在校准时顺手把电机轴转了一下电机处于发电机状态绕组里会产生反电动势电流同样会污染校准结果。所以标准做法是校准期间 PWM 关闭、低侧桥臂不导通、电机轴完全静止。4. 修复与验证把零点校准真正跑通4.1 首选使用 Motor Control SDK 自带的校准流程对于 B-G431B-ESC1 的用户我最推荐的做法是不要自己重新发明轮子直接用 SDK 的标准校准流程。具体操作如下用 MC Workbench 重新打开工程检查“Current Sensor”页面中的参数采样电阻值、运放增益、最大电流范围。确认这些参数和板子原理图一致。这一步非常关键因为 SDK 会根据这些参数自动计算电流换算系数如果参数填错即使偏移校准正确显示的电流值也会成比例偏移。重新生成工程代码保持默认初始化顺序不变确保校准状态机在 PWM 使能之前完成。编译烧录后不接电机、不接动力电用 Motor Pilot 连接观察 Iq 读数。正常情况下的读数应该在 ±0.02A 以内甚至更小。这个数值取决于 ADC 的量化噪声和运放本身等几十毫安的抖动是可接受的。如果稳定显示在 0 附近故障就排除了。4.2 备选从零搭建 FOC 时手动实现 offset 校准如果你没用 SDK而是自己从零写 FOC 控制代码那偏移校准完全要靠自己实现。原理很简单在 PWM 输出前对每路 ADC 连续采样多次取平均值存为偏移值。之后每次换算电流时都先减掉这个偏移。下面是一个可以直接参考的实现思路#define ADC_FULL_SCALE 4096u #define ADC_VREF_V 3.3f #define ADC_OFFSET_SAMPLES 256u /* 假设采样电阻为 0.01Ω运放增益为 10 */ #define SHUNT_RESISTOR_OHM 0.01f #define OPAMP_GAIN 10.0f static uint16_t ia_offset, ib_offset, ic_offset; void current_offset_calibration(void) { uint32_t sum_a 0, sum_b 0, sum_c 0; /* 校准条件PWM 尚未使能电机处于零电流状态 */ for (uint32_t i 0; i ADC_OFFSET_SAMPLES; i) { sum_a adc_read_a(); sum_b adc_read_b(); sum_c adc_read_c(); } ia_offset (uint16_t)(sum_a / ADC_OFFSET_SAMPLES); ib_offset (uint16_t)(sum_b / ADC_OFFSET_SAMPLES); ic_offset (uint16_t)(sum_c / ADC_OFFSET_SAMPLES); } float phase_current_a(uint16_t raw_adc, uint16_t offset) { float resolution ADC_VREF_V / (ADC_FULL_SCALE * OPAMP_GAIN * SHUNT_RESISTOR_OHM); int32_t code (int32_t)raw_adc - (int32_t)offset; return (float)code * resolution; }这段代码里有两个容易踩的细节第一采样次数不能太少。单次采样噪声太大尤其是开关电源纹波耦合到模拟电路上时单次采样值可能偏差几十个码。取 256 次平均能把随机噪声压到比较低。第二必须确保校准期间 PWM 是关闭的。如果校准函数在 main 初始化阶段就被调用此时定时器还没配置PWM 自然也没输出这个条件通常满足。但如果在校准函数之前就初始化了 PWM而你在初始化里把输出比较通道配置为立即输出高电平那低侧桥臂可能已经导通电流回路就建立了。4.3 验证校准效果的三个标准校准完不要只看 Iq 是 0 就算完我每次都会做三组验证第一组不接电机只给控制电看三相电流采样值是否都在 0 附近且三相之和接近 0。如果三相电流和明显不为 0说明偏移没扣干净或者三路 ADC 协调采样有问题。第二组用示波器测运放输出引脚确认无电流时各运放输出都在 1.65V 左右且没有明显的高频纹波。如果纹波大要检查模拟地和功率地的分割或者 ST-LINK 供电时的开关噪声。第三组接上电机但依然不接动力电用手缓慢转动电机轴。此时因为电机是永磁体转动会产生反电动势和很小的电流Iq 应该跟随转速发生变化但变化量级应该在几十毫安以内而且停止转动后回到 0 附近。如果手不转了 Iq 还停在一个偏置上那说明还有零漂没消除。5. 这个坑教我的排查方法论5.1 看电流之前先问三个问题经历这件事之后我给自己定了个规矩任何人拿“电流显示异常”来问我先让他回答三个问题——现在显示的是什么单位是安培还是 ADC 码还是内部定点数这个电流有没有形成物理回路如果电机没接、主回路没电那就不可能有真实电流怀疑采样和换算。换算公式里的偏移和增益是否经过校准如果 offset 是 0 或者用的默认值那非零显示几乎是必然的。这三个问题能过滤掉至少一半的“假故障”。很多时候问题根本不在板子而在软件对“零”的定义。5.2 相似现象的快速类比这个“没接电机却显示 Iq 非零”的问题和下面几类现象本质是同一个根源刚上电就报过流故障电机完全没动。这是最危险的一种因为过流保护会把 PWM 永久关闭导致你查来查去以为驱动电路有问题。电机的三相电流观测值总是偏向某一个方向比如 Ia 始终偏大。这往往是某一路 ADC offset 校准不完整或者运放增益配置不一致。电机低速运行时电流波形有明显的直流偏置速度越高越不明显。这个偏置就是零点偏移没扣干净速度高时相电流幅值大直流偏置被“淹没”了但低速时特别扎眼。如果你遇到的是这几类问题排查思路完全复用先回到零电流状态校准零点再谈其他。5.3 把“零电流基线”写进调试习惯最后分享一个我自己的习惯每次拿到一块新板子烧录完固件之后第一件事不是接电机而是先把板子放在桌上不接动力电打开电流观测窗口记录一段基线波形。这个基准值我会截图存下来之后任何电流异常都以这个基线为参照。为什么强调这个因为同一块板子在不同温度、不同供电电压下ADC 偏移是会漂移的。1.65V 这个零点会随着运放的温漂慢慢移动。如果你只在校准那一刻记了一个固定偏移长期运行后难免会出现很小的零漂。有了基线你至少能分辨某个非零 Iq 是“偏移没扣干净”还是“真实电流”不至于一上来就怀疑硬件。电机控制是个很吃经验的领域很多“灵异现象”说到底都是信号链路上某个基准点没弄对。B-G431B-ESC1 这个板子本身的硬件质量是很可靠的遇到 Iq 非零先按我上面这条链路查一遍比盲目换板子、换电机有效得多。也希望你在自己的项目里碰到类似问题时第一反应不是“硬件坏了”而是“零点有没有被正确清零”。