4、ADC采样与信号调理:ADC模块配置、电流/电压采样、过采样与滤波

ADC采样,说白了就是电机控制的眼睛。眼睛不好使,算法再牛也白搭。我见过不少工程师,花大把时间调PI参数,结果问题出在ADC采样上——噪声大、精度差、时序不对。嗯,今天咱们就把这块彻底聊透。

4.1 ADC模块配置——别小看这几步

英飞凌的ADC模块,我个人觉得设计得挺灵活的。但灵活也意味着坑多。配置时,有几个关键点你必须盯死。

核心配置项:

  • 分辨率选择:12位是标配,但有些场景用10位反而更好(比如高速采样时)。我习惯在低速电机上用12位,高速电机切到10位。
  • 采样时间:这个参数很多人忽略。采样时间太短,电容充不满,精度直接崩。太长呢?又影响吞吐率。
  • 触发源:PWM同步触发是电机控制的标配。千万别用软件触发,那玩意儿抖动大,电流环会抖得你怀疑人生。

举个例子,我配置一个典型的双电阻电流采样:

// 伪代码:ADC模块初始化
void ADC_Init(void)
{
    // 1. 使能ADC时钟
    ADC_ClockEnable(ADC_MODULE_0);
    
    // 2. 设置分辨率12位,采样时间100ns
    ADC_SetResolution(ADC_MODULE_0, ADC_RES_12BIT);
    ADC_SetSampleTime(ADC_MODULE_0, ADC_CH_V, 100);  // 单位ns
    
    // 3. 配置触发源为PWM同步信号
    ADC_SetTriggerSource(ADC_MODULE_0, ADC_TRIGGER_PWM_SYNC);
    
    // 4. 配置结果对齐方式(右对齐)
    ADC_SetResultAlignment(ADC_MODULE_0, ADC_ALIGN_RIGHT);
}

我的小技巧:采样时间别死磕手册上的最小值。我一般留20%余量。比如手册说80ns够,我就设100ns。多出来的20ns,换来的是稳定的精度,值不值?你自己算。

4.2 电流/电压采样——实战中的那些坑

电流采样,电机控制的命门。我做过一个项目,电流采样一直有直流偏置,查了三天,最后发现是PCB布局问题——采样电阻离大功率管太近,热噪声耦合进去了。

常见的采样方式有三种:

采样方式 优点 缺点 适用场景
单电阻采样 成本低,电路简单 重构算法复杂,低速性能差 低成本风机、水泵
双电阻采样 两相电流直接测量,算法简单 需要两个运放,成本略高 通用伺服、工业驱动
三电阻采样 三相独立测量,精度最高 成本高,PCB面积大 高端伺服、机器人关节

电压采样相对简单,但要注意母线电压的纹波。我曾经遇到过母线电压采样不准,导致过压保护误触发。后来加了RC滤波,问题解决。

避坑指南:我曾经在双电阻采样中,忽略了死区时间对采样窗口的影响。PWM死区期间,电流采样结果完全是垃圾数据。一定要确保采样窗口避开死区。怎么避?用PWM定时器的比较值来精确控制采样触发点。

4.3 过采样——用时间换精度

过采样,说白了就是用多个采样点取平均,来提升有效分辨率。你想想看,12位ADC不够用怎么办?换16位的?成本高啊。过采样就是个经济实惠的方案。

原理很简单:每提高1位有效分辨率,需要4倍的过采样率。比如从12位提到14位,需要16倍过采样。

// 过采样实现示例
uint16_t Oversample_Current(uint16_t *raw_data, uint8_t oversample_ratio)
{
    uint32_t sum = 0;
    uint8_t i;
    
    // 累加过采样数据
    for(i = 0; i < oversample_ratio; i++)
    {
        sum += raw_data[i];
    }
    
    // 右移得到最终结果(oversample_ratio = 4^n)
    // 比如16倍过采样,右移2位得到14位结果
    return (uint16_t)(sum >> 2);  // 假设oversample_ratio=16
}

注意:过采样不是万能的。它只能降低白噪声,对周期性噪声效果有限。而且会降低采样率。我一般只在低速或稳态工况下用过采样,高速时关掉。

4.4 滤波——别让噪声毁了你的控制

滤波这块,我踩过的坑最多。很多人上来就上低通滤波,结果相位滞后一大截,电流环带宽直接砍半。

常用的滤波方法:

  • 硬件RC滤波:简单粗暴,但会引入相位滞后。截止频率一般设在开关频率的1/10左右。
  • 软件均值滤波:适合过采样场景,计算量小。但会平滑掉真实变化。
  • 一阶低通滤波:代码简单,但要注意截止频率的选择。我习惯用截止频率=电流环带宽的5倍。
  • 卡尔曼滤波:效果好,但计算量大。我一般只在高端伺服上用。
// 一阶低通滤波实现
typedef struct {
    float output;       // 滤波输出
    float alpha;        // 滤波系数 (0~1)
} LowPassFilter_t;

float LowPassFilter_Update(LowPassFilter_t *filter, float input)
{
    // 一阶低通:output = alpha * input + (1-alpha) * output_prev
    filter->output = filter->alpha * input + (1.0f - filter->alpha) * filter->output;
    return filter->output;
}

// 初始化:alpha = Ts / (Ts + Tau)
// Ts: 采样周期, Tau: 时间常数
void LowPassFilter_Init(LowPassFilter_t *filter, float Ts, float cutoff_freq)
{
    float Tau = 1.0f / (2.0f * 3.14159f * cutoff_freq);
    filter->alpha = Ts / (Ts + Tau);
    filter->output = 0.0f;
}

我的经验:滤波不是越强越好。我见过有人把电流信号滤得干干净净,结果电流环响应慢得像蜗牛。记住一个原则:滤波器的截止频率,至少要比电流环带宽高3-5倍。这样既能滤掉开关噪声,又不影响控制性能。

4.5 实战总结——ADC采样的黄金法则

做了这么多年电机控制,我总结了几条ADC采样的黄金法则:

  1. 采样时序必须与PWM同步:这是底线。不同步?电流环抖给你看。
  2. 采样窗口避开死区:死区期间的采样数据,直接丢弃或标记无效。
  3. 滤波要适度:能硬件滤波就别用软件,能简单滤波就别上复杂算法。
  4. 校准不能省:每次上电做一次ADC偏移校准和增益校准。我见过有人省了这一步,结果电流误差5%以上。
  5. 留足裕量:采样时间、滤波截止频率、过采样率,都留20%的裕量。别卡着极限值设计。

嗯,ADC采样这块就聊这么多。说白了,它就是个信号链的问题——从物理量到数字量,每一步都有坑。但只要把原理搞透,配置做对,滤波选好,你的电机控制就成功了一半。下一章咱们聊聊电流环的PI参数整定,那才是真正见功夫的地方。