ARTICLE DETAIL

资讯详情

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

电机驱动电流采样:AMC1200隔离运放与STM32 ADC实战解析

电机驱动电流采样:AMC1200隔离运放与STM32 ADC实战解析 做直流电机驱动器的时候电流采样是躲不掉的第一道坎。电压、转速、位置都能靠估算凑合电流不行——启动冲击、堵转、换向瞬间任何一个环节电流失控功率管可能在几毫秒内直接烧掉。我最早用的是采样电阻加普通运放小电流测试时波形干干净净一上大电流就原形毕露地线上全是开关毛刺ADC读数跳得没法用PID调得再好也白搭。后来换成AMC1200隔离运放才算真正把电流反馈这条路走通。这篇就把整个过程完整过一遍从采样电阻选型、AMC1200外围电路设计到STM32侧ADCDMA配置、软件滤波和标定方法既有原理也有可直接抄的代码。适用对象是H桥驱动的直流电机如果你后面想入门无刷电机FOC这套采集链路的基本逻辑也是通用的换汤不换药。1. 为什么电机电流采样必须“隔离”从地弹噪声说起1.1 电机驱动里的“脏地”会毁掉高速ADC读数很多人第一次做电机驱动习惯性地把采样电阻的一端直接接到功率地再用运放放大输出给单片机的ADC。小电流下确实能工作但一旦母线电压升高、电流变大问题就出来了。原因在于功率地不是理想的“0V”。MOSFET开关瞬间电流在PCB寄生电感上会产生很大的di/dt压降这个压降会让局部地电位瞬间跳动几伏甚至几十伏也就是常说的“地弹”。普通运放的参考地往往是模拟地和功率地在PCB上做不到完全电位一致两地之间存在电位差运放输出里就混入了这个差值。更麻烦的是功率地到模拟地之间还会通过寄生电容耦合高频噪声这些噪声直接叠加在采样信号上ADC读到的数值就成了一堆乱码。隔离运放解决的就是这个问题输入侧和输出侧之间没有电气连接信号通过隔离栅以差分方式传递。对AMC1200来说输入侧的GND1接功率地输出侧的GND2接单片机模拟地两侧地完全分开功率地上的噪声再凶也很难直接串进ADC的参考地回路里。用生活类比就是普通运放等于两个人共用一根电话线这边说话那边能串音隔离运放等于给两边各装了独立电话机中间隔了道墙声音只以规定的方式传过去。所以电机驱动里做电流采样只要电流超过一两安培、母线电压超过24V隔离方案基本是必须的不是可选项。1.2 AMC1200与霍尔、隔离ADC的取舍做隔离电流采样市面上主流有三条路线方案原理优点缺点适用场景隔离运放AMC1200采样电阻压降经Σ-Δ调制后通过电容隔离传输输出为模拟差分电压带宽高、成本适中、精度可控、体积小需要隔离电源、需要外围滤波、信号需差分处理中小功率电机、FOC相电流采样霍尔电流传感器通过磁场感应电流无需采样电阻完全隔离、无插入损耗、不怕过流带宽低、温漂大、体积大、成本高大功率、低频、对损耗敏感的场景隔离式ADC采样电阻压降直接在隔离侧完成数字化通过SPI等接口传给MCU抗干扰强、数字接口简单、精度高成本高、带宽受限于采样率、需隔离电源高精度、多通道同步采集场合霍尔传感器最大的问题是带宽和相移高速动态响应跟不上隔离式ADC精度高但贵而且调试多一层。AMC1200算是平衡点固定增益8倍差分输入范围约±250mV带宽约100kHz足够覆盖绝大多数直流电机和无刷电机的电流环带宽需求成本也比霍尔低不少。要注意AMC1200本身不带隔离电源输入侧的VDD1和输出侧的VDD2必须分别供电这两个电源之间也要隔离。常见做法是用一个隔离DC-DC模块或者带隔离输出的电源芯片从单片机侧电源隔离出一路给输入侧用。这一条很多人第一次做时会漏导致上电后隔离运放完全不工作或者信号乱跳。2. 采样电阻选型与AMC1200外围电路的设计要点2.1 采样电阻阻值、功率与开尔文连接采样电阻是整个采样链路的源头取值直接决定信噪比和发热。选型要按峰值电流而不是额定电流来算原则是让峰值电流在电阻上的压降落在AMC1200线性输入范围的60%到80%左右也就是150mV到200mV附近。举例来说一个额定10A、峰值20A的直流电机选10mΩ采样电阻20A峰值时压降是200mV刚好在AMC1200的线性范围内连续10A时压降100mV对应隔离运放输出差分电压0.8V信噪比依然充足。此时电阻的功率也要算清楚。连续电流下的功耗是I²R10A×10mΩ算下来是1W选2W到3W的合金电阻才安全如果工况有持续堵转或频繁启动建议直接上5W。峰值状态下的瞬态功耗虽然高但持续时间短热容量足够就行。还有一个很容易被忽略的点大电流流过PCB铜箔时铜箔本身的电阻也会产生压降这部分压降会和采样电阻的真实压降混在一起导致采样不准。正确做法是采用四线制开尔文连接从采样电阻两端单独引两条细线到AMC1200的输入引脚让采样式走线和大电流路径完全分离。原理上就是让电压采样回路尽量不流过负载电流只承担微安级别的测量电流线阻上的压降就可以忽略不计了。2.2 AMC1200的供电、输入和输出接线AMC1200的引脚不算多但接线很容易踩坑。输入侧VDD1和输出侧VDD2各自供电范围是3.0V到5.5V一般都用3.3V。两边电源都必须加去耦电容建议在电源引脚附近放一个0.1μF陶瓷电容加一个1μF到10μF的钽电容或大容量陶瓷电容防止高频噪声串进供电回路。输入侧需要注意的是共模电压范围。AMC1200是差分输入VINP和VINN之间可测量的差分为±250mV但这两个引脚相对GND1不能超出供电范围太多否则输入级会饱和或损坏。所以在H桥驱动直流电机的场景里比较稳妥的拓扑是双低边采样电阻分别在H桥左下管和右下管的源极到功率地之间各放一个采样电阻这样每个电阻上的压降始终是单方向的AMC1200可以直接差分测量不会出现负压。具体接法采样电阻靠近MOSFET源极的一端接VINP靠近功率地的一端接VINNVINN同时连到GND1附近确保输入共模不会飘得太离谱。两个通道各用一个AMC1200分别采集两路电流。软件里根据当前PWM占空比和换向逻辑判断哪一路是有效电流或者直接用两路之和。输出侧VOUTP和VOUTN是差分输出0输入时两脚电压都约等于VDD2的一半比如3.3V供电时大约1.65V。差分输出电压等于输入差分电压乘以固定增益8。所以AMC1200输出侧的共模电压很高信号以差分形式存在于1.65V的偏置之上这就直接决定了下游电路必须用差分方式处理不能当普通单端信号用。2.3 RC滤波参数怎么定才不伤信号AMC1200内部是Σ-Δ调制再解调的结构输出信号上会残留高频调制噪声必须在输出侧加低通滤波器。典型做法是在VOUTP和VOUTN之间并联一个电容配合两侧串联的电阻构成差分低通。我常用的参数是每一路串一个100Ω电阻两路之间跨接一个1nF电容。这样形成的差分滤波器截止频率大约是1/(2π×2RC)把两个100Ω等效看成串联200Ω算下来约800kHz足够滤掉调制噪声又不会对100kHz以内的有效信号造成明显衰减。输入侧也可以加一个RC低通用来滤掉开关节点引起的毛刺。这里要注意输入电阻太大会和AMC1200内部的输入电容构成分压带来增益误差。建议输入串联电阻控制在10Ω到100Ω之间电容1nF到10nF截止频率选在几百kHz到几MHz这个区间不要为了滤波而把信号衰减掉。滤波参数不是一个固定值它和你的控制频率强相关。如果做FOC电流环频率通常在10k到20kHz滤波截止频率建议不低于100kHz否则相位延迟会拉低控制带宽。如果只是做简单的过流保护和慢速调速可以把截止频率压低一些换取更干净的波形。3. 输出端接STM32的方式差分采样才是正确姿势3.1 单端采样的坑共模1.65V和满量程饱和我见过不少人在AMC1200输出端犯了同一个错图省事只把VOUTP接到STM32的ADC引脚上VOUTN直接悬空或者接地然后发现电流一上去ADC值就顶满。这个问题的根源在于AMC1200输出共模电压是VDD2的一半。3.3V供电时零输入状态下VOUTP大约1.65V满量程差分信号是±2V±250mV乘以8这意味着VOUTP的理论摆动范围大约是从0.65V到2.65V。细算你会发现正向满量程的2.65V还在ADC量程内但留给正方向的余量只有约2V的一半左右如果输入信号稍微超一点或电源电压有波动输出就会超过3.3VADC直接饱和。最要命的是负向电流。如果只采VOUTP这一路负电流对应的电压是从1.65V往下走到0.65V以下就失真了哪怕负方向电流本身在AMC1200的线性范围内反映到单端信号上也没有表达空间。所以单端采样根本没把AMC1200的差分能力用起来等于白花了这个芯片的钱。3.2 双ADC通道同步采集与软件相减正确姿势是把VOUTP和VOUTN分别接到STM32的两个ADC通道用同步模式同时采样然后在代码里做差值运算。这样共模电压被完全扣掉剩下的就是真实的差分信号乘以固定增益。具体接法很简单VOUTP经过RC滤波后接ADC_IN0VOUTN经过同样的滤波网络后接ADC_IN1。注意两路的RC参数必须严格一致否则两条路径的相位和增益会有差异软件相减后会有残余误差。电阻电容最好用同一批次、精度1%的元件。软件里拿到两个ADC值后电流原始值可以这样表达int16_t diff_raw (int16_t)adc_buf[0] - (int16_t)adc_buf[1];为什么要用int16_t来承接因为两路ADC值相减的结果可能是负的无符号变量直接相减会溢出必须先转成有符号型再算。这个细节在整型运算里特别容易埋坑。有一个替代方案是用带差分ADC的STM32型号比如STM32G4或部分F3系列它们内部有真正的差分ADC输入可以直接把VOUTP和VOUTN接成差分对由硬件完成相减。但从通用性和成本考虑普通双ADC通道加软件处理的方案依然很能打代码里多做一步减法而已实测性能和硬件差分ADC差别不算大前提是两路采样时刻足够接近。4. STM32工程配置与代码实现4.1 CubeMX里ADCDMA配置要点我平时用STM32CubeMX生成初始化代码再在用户代码区里补业务逻辑。以STM32F401为例ADC1开启两个通道分别对应PA0和PA1使用扫描模式加DMA循环传输。配置时有几个关键点ADC分辨率选12位采样时间尽量选长一档比如12到15个周期以上降低源阻抗对采样保持电容的影响开启扫描模式通道顺序设置为 sequence1: IN0, sequence2: IN1DMA设置为循环模式数据宽度为半字16位这是ADC12位输出的默认宽度开一个定时器触发ADC启动不要用软件连续转换后面会细说为什么。DMA配置好以后ADC转换结果会自动写入一个数组CPU不需要关心数据搬运。这里有个隐藏前提DMA缓冲区类型要定义成uint16_t数组并且确保它在内存中的对齐没问题否则部分型号的DMA会在总线访问上卡顿。CubeMX生成的MX_ADC1_Init函数已经够用但有一点要改默认情况下DMA工作在Normal模式转换一轮就停了。要改成Circular模式不然采一次就断后续数据不更新。4.2 中点触发采样避开MOSFET开关毛刺电机PWM驱动下电流波形存在周期性开关噪声MOSFET开通和关断的瞬间噪声最强。如果让ADC随机采样大概率采到噪声尖峰数据抖动会非常大。解决方法是利用PWM定时器的TRGO事件作为ADC触发源让采样点精确落在PWM周期的中间时刻。因为PWM中点通常是电流纹波的均值位置同时也是开关暂态结束、信号相对稳定的区间在这里采样可以拿到一周期内最有代表性的电流值。以高级定时器TIM1为例配置如下逻辑TIM1输出PWM的中心对齐模式1或模式2TIM1的更新事件或者某个比较通道匹配事件映射到TRGOADC1的触发源选择Timer 1 Trigger Out eventADC工作在注入组或规则组都可以但采样触发外部事件要开启。中心对齐模式下PWM周期中点恰好是计数器的周期值附近TRGO在计数器上溢或下溢时产生天然对应每个PWM周期的中心。把ADC触发到这个点上就避开了开关沿的高噪声区间。代码上不用额外做太多事主要是在初始化时把ADC外部触发使能打开hadc1.Init.ExternalTrigConv ADC_SOFTWARE_START; // 修改前 hadc1.Init.ExternalTrigConv ADC_EXTERNAL_TRIGCONV_T1_TRGO; // 修改后 hadc1.Init.ExternalTrigConvEdge ADC_EXTERNAL_TRIGCONVEDGE_RISING;注意如果ADC配置为主从多通道扫描DMA要配合外部触发一起工作触发一次转换一个序列。触发频率就是PWM频率每个周期采一组VOUTP和VOUTN数据量完全够电流环使用。4.3 数据处理均值滤波、零漂消除与电流换算拿到ADC差分原始值之后不能直接当电流用要经过三步处理滤波、去零漂、换算成物理电流。一阶低通滤波是最常用的动态滤波方式公式很简单float current_filtered 0.9f * current_filtered 0.1f * (float)diff_raw;系数0.1可以根据实际噪声水平调节噪声大可以降到0.05动态响应要求高就提到0.2。这个滤波主要是为了削掉高频残余毛刺过度滤波会引入相位延迟影响电流环带宽要平衡。零漂消除是隔离运放特有的问题。AMC1200的输出级有失调电压STM32的ADC也有零点误差两路通道不完全对称时差分结果本身就不是严格的0。所以必须在系统上电后、电机未启动时采集一组数据存为offset值在后续每次采样中都减去它。int16_t zero_offset adc_buf[0] - adc_buf[1]; // 电机关断时采集 int16_t current_adc adc_buf[0] - adc_buf[1] - zero_offset;物理电流换算最简单的标定思路是先理论计算ADC满量程4096对应3.3V隔离运放输出差分电压 输入差分电压 × 8输入差分电压 电流 × 采样电阻阻值。所以合并起来电流与ADC值的关系是float voltage (float)current_adc / 4096.0f * 3.3f; float sense_voltage voltage / 8.0f; float current sense_voltage / 0.01f; // 采样电阻10mΩ这个计算依赖3.3V参考电压和增益8的准确性实际标定时会有一定偏差所以更推荐用已知电流做两点标定下面的实测章节会讲。5. 实测标定与高频噪声处理的经验5.1 零电流偏置标定与死区处理零电流标定听着简单做起来有讲究。光在代码里“电机关断时采一次”不够因为电机关断瞬间母线电容还在放电漏电流可能不为零。最稳妥的方法是在电机上电初始化阶段确认PWM输出为高阻或全部下拉之后连续采集几十个周期的差值取平均作为零点偏移。我一般会在main函数开头加一段自校准逻辑uint32_t sum 0; for (uint16_t i 0; i 64; i) { sum (uint16_t)(adc_buf[0] - adc_buf[1]); HAL_Delay(1); } zero_offset (int16_t)(sum / 64);取平均的意义是消除单次采样的随机噪声64次平均基本能把几毫伏的随机波动压下去。如果硬件上两路采样通道对称性好这个offset会非常接近0x0000但也可能测出几十个LSB的偏移这是正常现象不需要担心。死区处理是针对小电流场景的。电机零电流附近采样信号的噪声可能比真实信号还大如果不做处理系统会把这个噪声当成电流反馈轻则产生电流环抖动重则让电机在停止时出现微小的嗡嗡声。可以在软件中加一个死区判断当差分ADC值绝对值小于某个阈值时强制输出0。if (current_adc -10 current_adc 10) { current_adc 0; }阈值大小取决于你的噪声水平需要通过示波器或串口监视实际数据来确定。我是建议这个阈值宁小勿大太大会损失低速下的电流解析力造成控制不平顺。5.2 增益标定与温度漂移应对理论计算的电流换算公式能给出数量级正确的电流值但如果要做闭环控制精度不够。AMC1200的增益有典型值8实际可能是7.9或8.1采样电阻精度只有1%或5%3.3V参考电压也有误差这些误差会叠加到最终电流上。标定方法很简单让电机工作在恒定负载下用一块精度高的钳形电流表或万用表读出实际电流同时记录代码里滤波后的ADC值计算出一个增益系数。实际操作时可以在两个不同电流点各采一次做一个线性拟合。float current_lsb (current_ref1 - current_ref2) / (adc_avg1 - adc_avg2);增益标定最好在系统稳定运行温度下进行因为采样电阻是合金材料温漂系数一般不大但AMC1200的增益温漂和失调温漂是存在的。如果对温漂敏感可以在采样电阻旁边加一个温度传感器做软件补偿但这对绝大多数应用来说都过度设计了硬件布局上让采样电阻远离发热器件是更实用的做法。5.3 ADC读数抖动时的排查思路实际调试中遇到ADC读数抖动不要一上来就改滤波参数。先区分抖动来源比盲目堆滤波更高效。排查顺序我一般是这样用示波器看滤波后的输出电压波形。如果波形毛刺频率和PWM开关频率一致问题在采样时刻没避开开关沿重点检查PWM触发配置如果毛刺是宽频杂散信号大概率是电源或布局问题。检查VOUTP和VOUTN两路ADC的共模是否一致。在零输入时分别打印两路原始ADC值如果差值不为零且在数十字节范围内跳动多半是供电噪声或参考电压不稳定。给AMC1200输出侧电源单独加一级LC滤波往往能明显改善。断开电机只给单片机供电观察ADC输入是否依然抖动。如果依然抖说明问题在单片机侧的参考电压或地线布局和电机部分无关如果断开后变干净说明噪声是从功率侧耦合进来的重点检查隔离电源和布局。采样电容采样保持时间太短也会引起读数异常。如果源阻抗很高ADC内部采样电容还没充满就开始转换了读数就会偏小且不稳定。适当增加ADC采样时间比如配到几十个周期能稳妥解决这个问题。如果做完这些还是抖最后再考虑加大RC滤波的时间常数或提高均值滤波的次数。但记住一点滤波器只是掩盖问题前期把布局和触发做好后期根本不需要太强的滤波。我个人的体会是AMC1200这类隔离运放硬件上只要把电源滤波、差分走线和RC参数这三件事做好软件上把差分采样和零漂校准做对整个电流采样链路基本不会出幺蛾子。真正会出问题的往往不是芯片本身而是外围那些看着不起眼的细节采样电阻功率不够、单端采样、滤波参数拍脑袋、零点不校准每隔一段时间就会碰到有人栽在其中一个上面。这篇的经验是我反复踩坑后沉淀下来的按这个流程走一遍至少能避开我在调试时交过学费的那些坑。
返回列表