2. 伺服系统时序基础:PWM更新时刻、电流采样时刻、速度/位置计算时刻的典型时序关系

做伺服驱动这些年,我见过不少工程师把算法调得天花乱坠,结果一上电机就抖成筛子。问题出在哪?十有八九是时序没搞对。

说白了,伺服控制就是一个“什么时候该干什么事”的游戏。PWM什么时候更新、电流什么时候采样、速度和位置什么时候算——这几个时间点要是没对齐,你写的控制算法再漂亮也是白搭。

这一节,我就带你把这些时序关系彻底理清楚。

2.1 核心时序事件:三个关键动作

一个伺服控制周期里,有三个动作必须精确安排:

  • PWM更新时刻:把新的占空比写入硬件比较寄存器,决定下一个周期开关管的导通时间。
  • 电流采样时刻:通过ADC读取相电流和母线电流,通常在PWM载波的特定位置触发。
  • 速度/位置计算时刻:根据编码器脉冲或绝对位置数据,解算当前转子的位置和速度。

这三个动作不是随便排的。我刚开始做伺服时,图省事把电流采样放在PWM更新之后立刻做,结果每次采样都抓到开关噪声,电流波形跟心电图似的。后来才明白——时序设计,本质上是在跟噪声和延迟做博弈。

2.2 典型时序关系:单周期 vs 多周期

先看最常见的单周期时序。这里我以中心对齐PWM(三角载波)为例,因为工业伺服90%都用这种模式。

单周期时序(中心对齐PWM)

  • 载波周期 = 控制周期(通常50μs ~ 100μs,对应10kHz ~ 20kHz)
  • 电流采样:在载波顶点(峰值)或谷底触发ADC
  • PWM更新:在载波谷底更新比较值
  • 速度/位置计算:通常在电流环计算完成后进行

为什么电流采样要选在顶点或谷底?因为这两个时刻开关管处于死区或换向瞬间,di/dt最小,采样噪声最低。我有个习惯——采样点一定要避开开关动作沿,至少留出1μs~2μs的“静默窗口”。

再看多周期时序。有些高性能伺服会把电流环跑在更高频率(比如20kHz),而速度环和位置环跑在较低频率(比如4kHz或2kHz)。这时候时序关系就复杂了:

控制环 典型频率 计算时刻 依赖数据
电流环 10kHz ~ 20kHz 每个PWM周期执行一次 当前采样电流、转子角度
速度环 2kHz ~ 5kHz 每N个电流周期执行一次 最近N次位置增量
位置环 1kHz ~ 2kHz 每M个速度周期执行一次 当前目标位置与反馈位置

这里有个坑:速度环计算时,用的位置数据必须是“当前时刻”的,而不是上次速度环留下的旧值。我曾经在一个项目里没注意这个,速度环用的位置数据滞后了半个电流周期,结果电机在低速时出现周期性抖动。排查了两天才找到原因——数据新鲜度问题。

2.3 时序图:一图胜千言

下面这张图是我自己画的一个典型时序关系。它展示了一个PWM周期内,各个事件发生的先后顺序。

伺服控制单周期时序关系图 伺服控制单周期时序关系图 t 0 T/2 T 3T/2 载波 PWM 电流采样 电流采样 电流采样 PWM更新 PWM更新 位置/速度计算 说明: 1. 电流采样在载波顶点和谷底触发,避开开关噪声。 2. PWM更新在谷底进行,保证新占空比从下一个半周期开始生效。

从图上你能看到几个关键点:

  • 电流采样和PWM更新是错开的,不在同一时刻发生
  • 位置/速度计算在电流环计算完成后进行,保证使用最新的电流和角度数据
  • 每个PWM周期有两个电流采样点(顶点和谷底),但实际控制中通常只用一个

2.4 时序偏移带来的问题

时序没对齐会出什么问题?我列几个真实踩过的坑:

常见时序问题及后果

  • 采样滞后:电流采样点离PWM更新太近,采样值包含开关噪声,电流环发散
  • 计算延迟:位置计算用了上一周期的角度,导致速度估算有相位滞后,低速抖动
  • 更新冲突:PWM更新和ADC触发共用同一个定时器中断,优先级没处理好,丢采样
  • 多环不同步:速度环和电流环的更新时刻没有对齐,导致控制输出跳变

我记得有一次调试一个750W的伺服驱动器,电机空载时好好的,一带负载就啸叫。用示波器抓了PWM和电流采样触发信号,发现采样点正好落在开关管导通的瞬间——每次采样都抓到尖峰噪声。后来把采样触发延迟了2μs,问题立刻消失。你看,有时候就是这2微秒的事。

2.5 实际设计中的时序安排建议

基于我这些年的经验,给你几个实用的时序设计原则:

时序设计黄金法则

  1. 采样优先:电流采样必须在PWM更新之前完成,保证采样时开关状态稳定
  2. 计算紧随:采样完成后立即启动电流环计算,减少数据到计算的延迟
  3. 更新靠后:PWM更新放在控制周期末尾,保证所有计算完成后再输出
  4. 预留余量:每个事件之间至少留出1μs~3μs的裕量,应对硬件抖动

具体到代码实现,我一般这样安排中断优先级:

// 伪代码:时序安排示意
// 假设PWM载波频率10kHz,周期100μs

void PWM_ISR(void)          // 载波谷底中断,优先级最高
{
    // 1. 触发ADC采样(硬件自动完成)
    ADC_StartConversion();
    
    // 2. 读取上一周期计算好的PWM占空比并更新
    PWM_UpdateDutyCycle();
}

void ADC_ISR(void)          // ADC转换完成中断,优先级次高
{
    // 3. 读取ADC结果
    current_u = ADC_GetResult(CH_U);
    current_v = ADC_GetResult(CH_V);
    
    // 4. 执行电流环计算
    CurrentLoop_Calculate();
    
    // 5. 如果需要,执行速度/位置计算
    if (speed_loop_counter == 0) {
        SpeedLoop_Calculate();
    }
    
    // 6. 计算新的PWM占空比,存入缓冲区
    PWM_PrepareNextDutyCycle();
}

这个结构我用了很多年,基本没出过时序问题。核心思路就是:采样→计算→更新,三步走,顺序不能乱。

2.6 不同控制模式的时序差异

最后提一句,不同的控制模式对时序的要求也不一样:

控制模式 时序特点 注意事项
电流模式 每个PWM周期执行一次电流环 采样延迟必须小于5μs
速度模式 电流环高频,速度环低频 速度环使用的位置数据必须是最新的
位置模式 三级环级联,频率逐级降低 位置环周期必须是速度环周期的整数倍