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周期内,各个事件发生的先后顺序。
从图上你能看到几个关键点:
- 电流采样和PWM更新是错开的,不在同一时刻发生
- 位置/速度计算在电流环计算完成后进行,保证使用最新的电流和角度数据
- 每个PWM周期有两个电流采样点(顶点和谷底),但实际控制中通常只用一个
2.4 时序偏移带来的问题
时序没对齐会出什么问题?我列几个真实踩过的坑:
常见时序问题及后果
- 采样滞后:电流采样点离PWM更新太近,采样值包含开关噪声,电流环发散
- 计算延迟:位置计算用了上一周期的角度,导致速度估算有相位滞后,低速抖动
- 更新冲突:PWM更新和ADC触发共用同一个定时器中断,优先级没处理好,丢采样
- 多环不同步:速度环和电流环的更新时刻没有对齐,导致控制输出跳变
我记得有一次调试一个750W的伺服驱动器,电机空载时好好的,一带负载就啸叫。用示波器抓了PWM和电流采样触发信号,发现采样点正好落在开关管导通的瞬间——每次采样都抓到尖峰噪声。后来把采样触发延迟了2μs,问题立刻消失。你看,有时候就是这2微秒的事。
2.5 实际设计中的时序安排建议
基于我这些年的经验,给你几个实用的时序设计原则:
时序设计黄金法则
- 采样优先:电流采样必须在PWM更新之前完成,保证采样时开关状态稳定
- 计算紧随:采样完成后立即启动电流环计算,减少数据到计算的延迟
- 更新靠后:PWM更新放在控制周期末尾,保证所有计算完成后再输出
- 预留余量:每个事件之间至少留出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 |
| 速度模式 | 电流环高频,速度环低频 | 速度环使用的位置数据必须是最新的 |
| 位置模式 | 三级环级联,频率逐级降低 | 位置环周期必须是速度环周期的整数倍 |