ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

STM32电机控制:基于MCSDK 5.4.8的三电阻改两电阻电流采样详解

STM32电机控制:基于MCSDK 5.4.8的三电阻改两电阻电流采样详解 做电机控制的朋友对ST的MCSDK应该不陌生但这个库大部分示例工程默认走的是三电阻电流采样真正到了量产项目很多人想把三电阻砍成两电阻省一个采样电阻、一个运放、一路ADC通道顺便把PCB面积和BOM成本都压下来。这篇LAT1334应用笔记记录的就是基于MCSDK 5.4.8电机库把默认三电阻采样改成两电阻采样的完整过程包括修改思路、代码位置、时序调整方法和调试中遇到的坑。如果你正在做风机、水泵、电动工具这类对成本敏感的项目用的是STM32加MCSDK又想把电流采样方案从三电阻改成两电阻这篇笔记应该能帮你省不少时间。前半段先把原理和取舍讲清楚中间给出可操作的修改路径最后是调试和排障经验跟着走基本上不会跑偏。1. 为什么动这个三电阻到两电阻的取舍逻辑1.1 三电阻采样听着简单账算下来并不便宜三电阻采样在原理上是最直觉的方案每个下桥臂都放一个采样电阻在PWM周期某个合适的状态下同时采集三相电流然后直接做Clarke变换得到Ialpha、Ibeta。因为三相电流是独立测的算法简单、重构可靠低调制区也能正常采所以ST的库默认走这条路是有道理的。但它的成本是实打实的。三个采样电阻三个运放三路ADC注入通道再加上配套的RC滤波、防护电路每一路都是真金白银。在多路电机驱动的产品里这个成本还要翻倍。而且PCB上要给三路采样电路留位置布线的难度和干扰风险也随之上升。很多小体积产品的板子本来就很挤三路采样电路塞进去要么影响布局要么把功率区和采样区拉得太远信号质量反而变差。这时候两电阻采样的价值就出来了省一路采样通道省一颗电阻省一颗运放省一片布线面积对成本敏感的项目来说非常香。1.2 两电阻采样的原理和边界条件两电阻采样依据的是基尔霍夫电流定律三相电流之和为零知道任意两相第三相直接取负和就行。硬件上只需要在两个下桥臂装采样电阻比如装在V相和W相U相就不装了这样省掉一路采样通道。这个方案听起来很划算但代价是“免费”的第三相引入了重构问题。采样窗口不是任意时刻都有必须保证PWM处于某个有效开关状态让采样电阻上流过的电流和对应相电流之间存在确定关系。在低调制区有效矢量持续时间很短采样窗口可能不够重构结果会明显失真。在高速高调制区问题同样存在某些扇区边界上甚至会出现完全采不到的情况。所以决定要不要用两电阻先看你的应用有没有长时间低速大转矩工况。如果是风机水泵这种运行转速区间相对固定的两电阻完全够用如果伺服定位、堵转启动之类工况很重就要评估低调制区补采策略能不能兜住底。这一点想不清楚后面改完代码也很难调稳。1.3 MCSDK 5.4.8为什么默认不直接给两电阻ST的Workbench里图形化配置主要把三电阻当成高性能默认方案单电阻作为低成本方案。两电阻在底层其实不是没有你看看驱动文件名就知道了r3_2_f4xx.c这类文件里的R3_2就是三电阻和两电阻共用的驱动缩写底层框架是留了位置的。但问题在于5.4.8这个版本里两电阻的逻辑并没有在图形化界面里完整暴露很多参数生成之后还得靠手工改。Workbench生成的工程默认按三电阻的ADC通道、触发方式、重构函数来初始化你如果只是把电路板上的第三颗电阻拆了不改代码采样结果一定是错的。所以就有了这篇笔记存在的意义把底层机制讲清楚然后一步步把它改成两电阻。2. 改哪里MCSDK 5.4.8代码路径与关键配置2.1 找到核心驱动文件别改错地方MCSDK 5.4.8的工程生成之后和电流采样直接相关的文件主要集中在两个位置工程根目录/ ├─ Middlewares/ST/ST_MC_Interface/MotorControl/ │ └─ MCSDK_MC_Library/ │ ├─ inc/ │ │ ├─ r3_2_f4xx.h │ │ ├─ r3_2_f4xx_priv.h │ │ └─ pwm_curr_f4xx.h │ └─ src/ │ ├─ r3_2_f4xx.c │ └─ pwm_curr_f4xx.c └─ Projects/你的工程/ ├─ Inc/mc_config.h └─ Src/mc_config.c注意mc_config.c和mc_config.h是Workbench生成的项目配置文件电机参数、电流环参数、采样句柄的初始化都汇总在这里。真正干活的底层是r3_2_f4xx.c和pwm_curr_f4xx.c这两个文件在Middlewares目录里属于库文件。我的建议是尽量不要直接改库文件。因为库文件更新很容易被覆盖而且团队里如果有人没同步编译出来行为都不一样。更好的做法是把需要改的r3_2_xxx.c复制到自己的应用目录下改完编译链接时优先使用你的版本。实际操作时我一般是在工程里新建一个App/MotorControl/目录把要改的文件放进去再在编译选项里调整头文件搜索路径这样既不影响原库也方便版本管理。2.2 R3_2句柄里面到底藏着什么mc_config.c里会定义一个R3_2_Handle_t类型的句柄以及对应的R3_2_Params_t初始化参数结构体。这个句柄就是电流采样驱动的门面初始化的时候传入ADC句柄、定时器句柄、注入通道配置、采样时间等参数。三电阻和两电阻的差别翻译成数据结构层面的变化大概是这么几处采样通道数量从3变成2注入组的通道序列长度从3变成2两个采样通道的ADC触发事件需要错开对应PWM定时器的触发源配置会变电流重构时不再直接对三路采样值做Clarke变换而是要根据扇区重建第三相。我用一段示意配置来说明字段名以你本机生成代码为准但思路是一致的/* 示意结构不是从某个版本原样复制的 */ static const R3_2_Params_t R3_2_Params { .pPWM PWM_Handle, .pADC[0] hadc1, .pADC[1] hadc2, .channelCount 2u, /* 只使能两路采样 */ .adcInjectedCh[0] ADC_INJECTED_CH_0, /* 对应V相采样 */ .adcInjectedCh[1] ADC_INJECTED_CH_1, /* 对应W相采样 */ .sampleTime ADC_SAMPLETIME_15CYCLES, .twoShuntPhaseShift 36u, /* 移相量单位是PWM计数步 */ };我在实际工程里见过的版本字段名称可能叫twShuntShift也可能直接就是定时器的比较寄存器映射总之你只要知道两电阻需要多一个“移相量”参数就行了。这个移相量不是随便给的它决定第二个采样窗口落在哪个PWM状态上直接影响重构正确性。2.3 Workbench里先按三电阻跑通再谈改造改两电阻之前我强烈建议先在Workbench里按三电阻方案生成工程然后把电机转起来。这一步不是为了验证什么高级功能而是确认电机本体参数、电流环初始PI值、编码器或霍尔方向都是对的。如果三电阻版本还没跑过就直接改两电阻出了问题你很难判断是电机参数的问题还是采样时序的问题。把变量隔离掉后面改起来会清醒很多。三电阻跑通之后把整个工程备份一份再开始改。这样出了问题可以随时回滚不用从头来过。3. 怎么改两电阻采样改造实操步骤3.1 硬件上先确认两件事动代码之前先看硬件设计是否满足两电阻采样的条件。第一采样电阻放在哪两相。有些板子习惯放在V相和W相有些放在U相和V相这本身没有绝对的对错但MCSDK底层代码里对采样通道和相电流的映射是有默认约定的。改代码之前你一定要确认电阻位置和ADC通道的对应关系如果不一致要么改硬件要么改软件里的通道映射不然采样值极性就是反的。第二运放增益和ADC量程是否匹配。估算公式很简单我直接给一个例子假设最大相电流 30A采样电阻 2mΩ则 采样电阻峰值压降 30 × 0.002 60mV 运放增益取 10 倍输出峰值 0.6V ADC参考电压 3.3V0.6V 约占量程的 18%这个比例偏低采样精度不太够。如果换成采样电阻 5mΩ压降 150mV运放增益 10 倍输出 1.5V约占量程45%精度就合理多了。不过采样电阻变大功耗也会变成原来的2.5倍需要算好散热。两电阻采样省掉一路剩下的两路功耗和成本更要仔细权衡。3.2 mc_config.h和mc_config.c具体怎么动先打开mc_config.h找到和电流采样相关的宏定义。默认生成代码里会有三个采样通道对应的ADC通道宏、注入通道使能宏之类你可以把第三路的宏注释掉或者直接改成两电阻模式对应的宏。同时确认ADC时钟配置采样时间不能太长不然采样窗口不够用。再看mc_config.c里的R3_2_Params初始化。把通道数量改成2把注入序列长度改成2确保第三路ADC不参与注入转换。这里有一个细节很多人会漏如果你用的是一个ADC的注入组注入序列长度必须改回实际需要的长度否则第一次触发会把序列里所有通道都扫一遍两次触发信号就失去了错开采样的意义。注意改完mc_config之后不要直接编译烧录先全局搜一下还有没有引用第三路采样结果的地方比如过流保护的ADC比较值、采样校准函数这些位置如果不一起改运行时会报错或者出现过流误触发。3.3 PWM触发配置与移相原理这是两电阻采样改造里最核心的地方。三电阻采样可以“一枪三响”在PWM中心某个状态同时触发所有ADC通道直接采到三相。两电阻不行两个采样窗口必须落在两个不同的有效开关状态上。用中心对齐PWM来理解。假设某一时刻三相占空比大小关系是 Da Db Dc那么在一个PWM半周期内开关状态会按 000、100、110、111 的顺序依次出现后半周期再反向回去。在100状态A相上桥臂导通V相和W相的下桥臂导通此时V相采样电阻上的电流和V相电流之间存在确定关系在110状态又是另一组确定关系。两电阻采样的思路就是在两个不同的有效状态上分别采样两路电阻再通过电流重构得到第三相。要让两路ADC分别在两个不同状态触发必须有至少两个错开的触发事件。MCSDK底层做法一般是这样第一路ADC注入触发挂在PWM周期事件上第二路挂在PWM比较匹配事件上比较匹配点的位置就是那个“移相量”控制的。移相的本质就是把第二个采样点从PWM中心向一侧偏移让它的采样窗口落到另一个有效矢量上。如果使用的是单个ADC触发信号还得配置成只转换对应的注入通道。这块说多了容易晕我的建议是先在现有生成代码里找到ADC注入触发源配置一般藏在pwm_curr_f4xx.c的PWM初始化里或者在R3_2_Init函数里。把默认的一个触发源改成两路一路保持周期触发另一路用定时器比较通道触发再调移相量逐个验证。3.4 电流重构函数的实现思路底层把两路ADC值采回来之后下一步要做的不是直接做Clarke变换而是先把三相电流重构出来。重构逻辑依赖当前扇区因为不同扇区下两路采样值对应的相电流组合不一样。我提供一个伪代码框架方便你理解/* 根据扇区从两路采样结果重构三相电流 */ void ReconstructPhaseCurrents(uint8_t sector, int32_t I_sample1, int32_t I_sample2, int32_t *Ia, int32_t *Ib, int32_t *Ic) { switch (sector) { case 0: *Ia I_sample1; *Ib I_sample2; *Ic -I_sample1 - I_sample2; break; case 1: *Ia I_sample1; *Ic I_sample2; *Ib -I_sample1 - I_sample2; break; /* 其他扇区按SVPWM状态表映射 */ default: break; } }实际MCSDK版本里底层函数名大概率是R3_2_GetCurrents它返回的通常是Ialpha和Ibeta不是原始三相电流。所以在两电阻模式下这个函数内部必须知道当前扇区才能正确重构。问题是扇区号在SVPWM计算里才有而采样函数执行时不一定能直接拿到很多版本的方案是把扇区号缓存到一个全局变量里或者通过PWM比较值方向反推。这也是改造时最容易被忽略的地方。如果库里的R3_2_GetCurrents没有预留两电阻分支那就得自己写一个函数在PWM中断里替代它。我建议在改之前先把原来的三电阻代码完整读一遍弄懂采样结果是怎么传递到电流环的再下手替换不要上来就改函数体。4. 怎么调移相量、采样窗口与电流环整定4.1 先把电流采样波形调真再谈PI参数两电阻改造完成之后先不要直接带载跑FOC不要直接闭环跑高速。先用开环V/f模式给一个固定幅值、较低频率的三相电压让电机空载旋转然后通过调试器或者Motor Profiler观察Ialpha和Ibeta波形。正常的波形应该是两个相位差90度的正弦波幅度和转速匹配。如果看到的是扇区状台阶、削顶、或者周期性毛刺那说明采样时刻或者通道映射还有问题先去查PWM触发配置和代码里的通道对应关系不要急着调PI。4.2 采样窗口不够用怎么算怎么调两电阻采样对采样窗口长度有硬性要求。我们把一次有效采样需要的时间拆开看t_window_min 死区时间 电流建立时间 ADC采样时间 ADC转换时间 余量以STM32F407为例ADC采样时间配置为15个周期ADC时钟30MHz采样时间就是0.5μs12位分辨率转换时间约0.4μs。假设死区0.3μs电流建立0.3μs再留0.3μs余量最小窗口大约是1.8μs。现在把PWM周期拉出来对比。如果PWM频率16kHz周期是62.5μs看起来窗口时间绰绰有余。但到了高调制区某个有效矢量的持续时间可能只有整个
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进