3、电流环与速度环调试:电流采样电路与ADC校准、PI参数整定方法(Ziegler-Nichols)、速度环震荡分析与抑制

电流环和速度环,是运动控制的「两条腿」。

很多新手一上来就调位置环,结果电机嗡嗡响、跑飞、甚至炸管。我当年也干过这事——调了半天发现电流环根本没收敛。说白了,电流环是基础,基础不稳,上层全白搭。

3.1 电流采样电路与ADC校准

电流采样,是电流环的「眼睛」。眼睛看不清,后面再怎么调也没用。

3.1.1 采样电阻与差分放大

常用的方案是低侧采样,用毫欧级电阻串在MOS管源极和GND之间。采样信号经过差分运放放大后送ADC。

我个人习惯用INA240这类专用电流检测放大器,共模抑制比高,省心。如果你用普通运放搭差分电路,电阻匹配精度必须做到0.1%以内,否则共模抑制比会掉得很厉害。

注意:采样电阻的功率要留够余量。我曾经在项目里用了1206封装的10mΩ电阻,峰值电流30A,结果电阻直接冒烟——算下来功率9W,1206根本扛不住。后来换了2512封装,才稳住。

3.1.2 ADC校准:零偏与增益

ADC采集回来的值,不能直接用。为什么?因为运放有零偏,电阻有误差,ADC本身也有偏移。

校准分两步:

  1. 零偏校准:电机不转,母线不上电,采集ADC值作为零偏。一般采100次取平均,存下来。
  2. 增益校准:给一个已知电流(比如用恒流源或者精密电阻负载),采集ADC值,算出实际增益系数。

代码实现很简单:

// 电流ADC校准
typedef struct {
    float zero_offset;   // 零偏值(ADC码值)
    float gain;          // 增益系数 (A/LSB)
} CurrentCalib_t;

CurrentCalib_t calib;

void CurrentCalib_Init(void) {
    uint32_t sum = 0;
    for (int i = 0; i < 100; i++) {
        sum += ADC_GetValue();
        delay_ms(1);
    }
    calib.zero_offset = sum / 100.0f;
    
    // 假设已知校准电流为 1.0A,对应ADC码值差为 2048
    calib.gain = 1.0f / (2048.0f - calib.zero_offset);
}

float Current_GetActual(void) {
    float raw = ADC_GetValue();
    return (raw - calib.zero_offset) * calib.gain;
}
小技巧:零偏校准最好在每次上电时做一次。因为温度变化会导致零偏漂移,我见过一个项目,冬天和夏天的零偏差了20多个码值,电流环低速抖动就是这原因。

3.2 PI参数整定方法(Ziegler-Nichols)

PI参数怎么调?很多人靠蒙,调大调小试半天。其实有经典方法——Ziegler-Nichols法。

3.2.1 基本原理

Ziegler-Nichols法分两步:

  1. 先把积分项I设为0,微分项D设为0(我们只用PI,D不用)。
  2. 慢慢增大比例增益Kp,直到系统输出出现等幅振荡。记录此时的Kp为Ku,振荡周期为Tu。

然后按表查参数:

控制器类型 Kp Ki
P 0.5 * Ku -
PI 0.45 * Ku 1.2 * Kp / Tu
PID 0.6 * Ku 2 * Kp / Tu

嗯,这里要注意:这个方法适用于一阶滞后系统。电流环和速度环基本符合,但实际应用时参数要微调。

3.2.2 实操步骤

我建议你这样操作:

  • 先调电流环。电流环带宽高,一般Kp从0.1开始往上加,直到听到电机有轻微啸叫或电流波形出现等幅振荡。
  • 记录Ku和Tu,按表算出PI参数。
  • 然后调速度环。速度环带宽低,Kp从1开始往上加,同样找等幅振荡点。
避坑指南:我曾经在一个伺服项目里,电流环怎么都调不出等幅振荡,后来发现是电流采样有50Hz工频干扰。加了50Hz陷波滤波器后,立马就出来了。所以,调参前先确认采样信号干净。

3.3 速度环震荡分析与抑制

速度环震荡,是调试中最常见的问题。电机要么嗡嗡响,要么转速忽高忽低。

3.3.1 震荡原因分析

震荡的原因主要有三个:

  • PI参数不合适:Kp太大导致超调,Ki太大导致积分饱和。
  • 机械谐振:负载惯量匹配不好,或者联轴器有间隙。
  • 采样噪声:速度反馈信号有毛刺,导致控制器误动作。

怎么区分?我教你一招:用手摸电机轴,如果感觉是高频振动(几百Hz),多半是电流环问题;如果是低频摆动(几Hz到几十Hz),多半是速度环或机械问题。

3.3.2 抑制方法

针对不同原因,方法也不同:

  1. PI参数优化:用Ziegler-Nichols法算出初值后,再微调。一般Kp降10%-20%,Ki适当增加,可以抑制超调。
  2. 低通滤波:在速度反馈通道加一阶低通滤波,截止频率设为速度环带宽的3-5倍。
  3. 陷波滤波器:如果机械谐振频率已知,可以用陷波滤波器定点消除。
  4. 前馈补偿:在速度环输出加加速度前馈,可以改善动态响应。

代码示例:

// 速度环PI控制器(带积分限幅)
typedef struct {
    float Kp;
    float Ki;
    float integral;
    float integral_max;  // 积分限幅
} SpeedPI_t;

float SpeedPI_Update(SpeedPI_t *pi, float error, float dt) {
    float output;
    
    // 比例项
    float p_out = pi->Kp * error;
    
    // 积分项(带限幅)
    pi->integral += pi->Ki * error * dt;
    if (pi->integral > pi->integral_max)
        pi->integral = pi->integral_max;
    else if (pi->integral < -pi->integral_max)
        pi->integral = -pi->integral_max;
    
    output = p_out + pi->integral;
    return output;
}
经验之谈:积分限幅很重要。我见过有人把积分限幅设得很大,结果积分项一直累积,电机突然加速到飞车。一般积分限幅设为额定输出的20%-30%比较安全。

3.4 本章知识体系

下面这张图,把电流环和速度环调试的整个流程串起来了。你调试时按这个顺序走,基本不会乱。

电流环与速度环调试知识体系 硬件基础 采样电阻选型 → 差分放大电路 → ADC采集 → 零偏与增益校准 电流环调试 Ziegler-Nichols法找Ku、Tu → 计算Kp、Ki → 微调 → 验证带宽 速度环调试 Ziegler-Nichols法 → 低通滤波 → 陷波滤波器 → 前馈补偿 震荡分析与抑制:PI优化 → 滤波 → 机械谐振处理 调试流程方向

调试时记住一个原则:从底层往上层调。先确保电流采样准确,再调电流环,最后调速度环。跳过任何一步,后面都会出问题。

最后说一句:调试是个耐心活。我当年调一个电机,光电流环就折腾了两天。后来发现是ADC时钟配置错了,采样率不够。所以,遇到问题先检查基础配置,别一上来就怀疑算法。

公众号:蓝海资料掘金营,微信deep3321