4. 电流检测法实战:采样电阻选型、运放电路设计、ADC采样配置、阈值设定策略

电流检测,说白了就是电机的“听诊器”。堵转时电流会飙升,你如果能准确捕捉到这个信号,保护就成功了一半。我这些年调试无感启动,踩过最多的坑就在电流检测这一块。不是采样电阻烧了,就是运放输出饱和了,再不然就是ADC采了一堆噪声。

今天咱们就把这条链路从头到尾捋一遍。从电阻选型,到运放设计,再到ADC配置和阈值策略,每一步我都会把实际项目里踩过的坑指出来。

核心链路: 采样电阻 → 差分运放 → ADC采样 → 软件阈值判断

任何一个环节出问题,堵转保护都会失效。

电流检测链路总览 采样电阻 mΩ级 / 低感 / 高功率 差分运放 放大倍数 / 共模抑制 ADC采样 分辨率 / 采样率 / 触发 阈值判断 软件滤波 / 保护动作 关键说明: 1. 采样电阻将电流转换为mV级电压信号 2. 差分运放放大差模信号,抑制共模噪声 3. ADC将模拟电压转为数字量,软件做阈值判断

4.1 采样电阻选型:别只看阻值

很多人选采样电阻,上来就问“用多少毫欧”。其实这只是第一步。我见过一个项目,工程师选了5mΩ的电阻,结果电机启动瞬间电流一冲,电阻直接冒烟了。为什么?功率没算够。

选型时我习惯按三个维度来卡:

  • 阻值: 一般1mΩ ~ 10mΩ。阻值太小,信号太弱,运放需要高增益,噪声也跟着放大。阻值太大,发热严重,效率下降。
  • 功率: 按最大堵转电流的1.5倍来算。比如堵转电流30A,电阻5mΩ,功率P = I²R = 30² × 0.005 = 4.5W。选个5W以上的,留余量。
  • 电感: 这个容易被忽略。普通绕线电阻有寄生电感,高频PWM电流通过时会产生尖峰电压,轻则干扰采样,重则击穿运放。我建议用金属膜电阻或锰铜电阻,电感极低。

我的习惯: 低压电机(12V~48V)用2mΩ~5mΩ,高压电机(220V以上)用1mΩ左右。功率留2倍余量,电感控制在10nH以下。

4.2 运放电路设计:差分放大是王道

采样电阻两端的电压是mV级的,而且共模电压很高(母线电压的一半)。你如果用单端放大,共模噪声会直接把信号淹掉。所以必须用差分运放。

我常用的电路结构是这样的:

采样电阻两端 → 差分输入 → 运放(如LMV358、AD8418) → 输出到ADC

设计时注意几个关键点:

  • 放大倍数: 根据ADC参考电压来算。比如ADC是3.3V,采样电阻最大压降50mV,那放大倍数就是3.3 / 0.05 = 66倍。实际取60倍左右,留一点余量。
  • 共模抑制比(CMRR): 选CMRR在80dB以上的运放。我踩过坑,用了一颗CMRR只有60dB的运放,电机一转,采样值跟着母线电压波动,根本没法用。
  • 偏置电压: 如果电机电流是双向的(正转/反转),需要给运放加一个偏置电压,把信号抬到ADC量程中间。比如偏置到1.65V,这样正负电流都能采到。

我曾经踩过的坑: 运放输出直接连ADC,没加RC滤波。结果PWM开关噪声耦合进来,ADC采出来的值跳得像心电图。后来在运放输出和ADC之间加了一阶RC低通滤波(截止频率约10kHz),问题解决。

4.3 ADC采样配置:时机比频率更重要

ADC采样不是越快越好。你想想看,电机电流是正弦波,你如果随机采样,采到的可能是波峰、波谷或者过零点,算出来的有效值偏差很大。

我建议用同步采样的方式:

  1. 触发源: 用PWM定时器触发ADC。每个PWM周期在固定相位点(比如中心对齐的波谷)触发一次采样。
  2. 采样率: 一般每个PWM周期采一次就够了。PWM频率16kHz,采样率就是16kHz,完全够用。
  3. 分辨率: 12位ADC是底线。如果MCU支持16位,尽量用16位。我试过8位ADC,电流变化10%才能分辨出来,堵转保护根本来不及反应。

配置代码示例(基于STM32 HAL库):

// ADC配置:PWM触发,12位分辨率
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;  // 单次转换,由PWM触发
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;  // 定时器1通道1触发
HAL_ADC_Init(&hadc1);

小技巧: 如果MCU支持过采样,可以开16倍过采样,等效分辨率能提升到14位。代价是采样时间变长,但16kHz的PWM周期下完全够用。

4.4 阈值设定策略:动态 vs 静态

阈值设死了,电机在不同负载下容易误触发或者漏保护。我一般用动态阈值策略。

具体做法:

  • 静态阈值: 作为底线保护。比如额定电流的2倍,超过就直接停机。这个阈值不能设得太低,否则启动瞬间的浪涌电流会误触发。
  • 动态阈值: 根据当前运行电流实时调整。比如正常运行时电流是1A,动态阈值设为1.5A。如果电流突然跳到2A,说明堵转了。

我习惯用滑动窗口均值来做动态阈值:

// 动态阈值计算
#define WINDOW_SIZE 10
uint16_t current_buffer[WINDOW_SIZE];
uint8_t index = 0;

uint16_t get_dynamic_threshold(void) {
    uint32_t sum = 0;
    for (int i = 0; i < WINDOW_SIZE; i++) {
        sum += current_buffer[i];
    }
    uint16_t avg = sum / WINDOW_SIZE;
    return avg * 1.5;  // 1.5倍作为动态阈值
}

这个策略的好处是:电机启动时电流大,动态阈值也跟着抬高,不会误触发。堵转时电流持续偏高,动态阈值跟不上,保护就会动作。

阈值设定总结:

阈值类型 设定值 触发条件
静态阈值(硬保护) 额定电流 × 2.5 超过立即停机
动态阈值(软保护) 滑动均值 × 1.5 持续超过100ms
启动阈值(特殊处理) 额定电流 × 3.0 启动后200ms内有效