第8章
数字控制:把控制器放进计算机
学完这一章你应该能
- 画出数字控制回路的结构,说清楚采样、量化、零阶保持各自带来什么问题;
- 理解采样定理和混叠,知道为什么要加抗混叠滤波;
- 用 Z 变换和差分方程描述离散系统,用单位圆判断稳定性;
- 把连续控制器离散化(欧拉法、双线性变换、零阶保持),知道各自的特点;
- 写出位置式和增量式数字 PID;
- 按相位裕度的损失选择采样周期。
为什么要学?今天的控制器几乎都是数字的:单片机、PLC、电脑、无人机飞控、3D 打印机主板……它们每隔一个固定的时间(采样周期 \(T_s\))读一次传感器、算一次、输出一次。前面学的连续理论仍然是基础,但「每隔 \(T_s\) 才动一次」会带来新问题:混叠、延迟、离散化误差。这一章讲清楚这些问题和对应的做法。
8.1 数字控制回路
一个典型的数字控制回路:
- 采样(A/D 转换):每隔 \(T_s\) 把连续的测量信号 \(y(t)\) 变成一个数 \(y(k)=y(kT_s)\);
- 计算:控制程序根据 \(r(k)\)、\(y(k)\) 和以前的数据算出 \(u(k)\);
- 保持(D/A 转换或 PWM):把 \(u(k)\) 输出,并且一直保持到下一个采样时刻(零阶保持器,ZOH),对象看到的是阶梯形的输入。
和连续控制相比,多了三个问题:
- 混叠:采样太慢,高频信号会「伪装」成低频信号(8.2 节);
- 延迟:零阶保持平均延迟 \(T_s/2\),再加上计算时间,会吃掉相位裕度(8.6 节);
- 量化:A/D、编码器的分辨率有限,信号是一格一格的,可能引起小幅振荡(第12章)。
8.2 采样定理与混叠
采样定理:要从采样值中无失真地恢复一个信号,采样频率 \(f_s\) 必须大于信号最高频率的 2 倍。\(f_s/2\) 叫奈奎斯特频率。
频率 \(f>f_s/2\) 的信号被采样后,会和频率为 \(|f-nf_s|\)(\(n\) 取使它最小的整数)的低频信号无法区分,这叫混叠。
工程上的含义:
- 传感器信号里的高频噪声(比如 50 Hz 工频干扰、电机 PWM 的开关噪声)如果超过 \(f_s/2\),采样后会变成低频「假信号」混进控制回路,事后用数字滤波去不掉;
- 所以在 A/D 之前要加抗混叠滤波器(模拟 RC 低通,截止频率低于 \(f_s/2\)),或者先用很高的频率过采样,数字滤波后再降采样;
- 采样定理只是下限。控制要的采样频率比它高得多(8.6 节)。
8.3 Z 变换与差分方程
离散系统用差分方程描述:输出 \(y(k)\) 由过去的输出和输入算出。例如
就是 \(\frac{1}{s+1}\) 在 \(T_s=0.1\) s 时的离散模型(8.4 节会算出来)。在程序里它就是一行代码:y = 0.9048*y + 0.09516*u。
Z 变换对离散序列的作用,就像拉氏变换对连续函数:
| \(x(k)\) | \(X(z)\) |
|---|---|
| 单位脉冲 \(\delta(k)\) | \(1\) |
| 单位阶跃 \(1(k)\) | \(\dfrac{z}{z-1}\) |
| \(a^k\) | \(\dfrac{z}{z-a}\) |
| \(e^{-akT_s}\)(采样后的指数) | \(\dfrac{z}{z-e^{-aT_s}}\) |
| 延迟一步 \(x(k-1)\) | \(z^{-1}X(z)\) |
最重要的一条是最后一行:\(z^{-1}\) 就是「延迟一个采样周期」。对上面的差分方程两边取 Z 变换:\(Y(z)=0.9048z^{-1}Y(z)+0.09516z^{-1}U(z)\),得到脉冲传递函数
终值定理:\(x(\infty)=\lim_{z\to1}(z-1)X(z)\)(序列收敛时)。例如上面这个系统的直流增益 \(G(1)=0.09516/0.0952=1\)。
离散系统的稳定性:单位圆
连续系统的极点 \(s\) 与离散系统的极点 \(z\) 之间的关系是 \(z=e^{sT_s}\)。由此:
- s 平面的左半平面 ↔ z 平面的单位圆内;虚轴 ↔ 单位圆;
- 离散系统稳定 ⟺ 所有极点都在单位圆内(\(|z|<1\));
- 极点越靠近 \(z=1\),响应越慢;越靠近原点,响应越快;
- 负实轴上的极点(比如 \(z=-0.5\))会让输出每一拍改变一次符号,以奈奎斯特频率振荡(「振铃」),这是连续系统里没有的现象。
例:\(\frac{1}{s+1}\) 的极点 \(s=-1\),\(T_s=0.1\) 时离散极点 \(z=e^{-0.1}=0.9048\),正是上面的分母。
8.4 连续控制器的离散化
实际工作中常见的做法是:先按连续理论设计控制器 \(G_c(s)\),再把它「翻译」成差分方程。常用方法:
| 方法 | 做法 | 特点 |
|---|---|---|
| 前向欧拉 | \(s\approx\dfrac{z-1}{T_s}\) | 最简单;\(T_s\) 较大时可能把稳定的系统变成不稳定的 |
| 后向欧拉 | \(s\approx\dfrac{z-1}{zT_s}\) | 总能保持稳定,计算简单;有一点额外的相位滞后 |
| 双线性变换(Tustin) | \(s\approx\dfrac{2}{T_s}\cdot\dfrac{z-1}{z+1}\) | 保持稳定,频率特性最接近原连续系统;控制器离散化最常用 |
| 零阶保持(ZOH) | 输入在每个采样周期内保持不变时的精确离散化 | 被控对象离散化用,因为 D/A 输出本来就是阶梯形的 |
例:一阶低通滤波器 \(\dfrac{1}{\tau s+1}\)(\(\tau\) 为时间常数)
- 后向欧拉:\(y(k)=y(k-1)+\dfrac{T_s}{\tau+T_s}\big[u(k)-y(k-1)\big]\)。这就是程序员熟悉的「指数滑动平均」,系数 \(\alpha=\dfrac{T_s}{\tau+T_s}\);
- 零阶保持:\(y(k)=a\,y(k-1)+(1-a)\,u(k-1)\),\(a=e^{-T_s/\tau}\)(\(\tau=1\)、\(T_s=0.1\) 时就是上一节的 0.9048 和 0.09516);
- Tustin:\(y(k)=\dfrac{2\tau-T_s}{2\tau+T_s}y(k-1)+\dfrac{T_s}{2\tau+T_s}\big[u(k)+u(k-1)\big]\)(\(\tau=1\)、\(T_s=0.1\) 时系数为 0.9048 和 0.04762);
- 前向欧拉:\(y(k)=y(k-1)+\dfrac{T_s}{\tau}\big[u(k-1)-y(k-1)\big]\),极点 \(1-T_s/\tau\)。\(T_s=0.5\tau\) 时为 0.5(正常);\(T_s=1.5\tau\) 时为 −0.5(每拍变号);\(T_s>2\tau\) 时跑出单位圆,原本稳定的滤波器变得不稳定。
import control as ct
G = ct.tf([1], [1, 1])
print(ct.c2d(G, 0.1, method="zoh")) # 0.09516 / (z - 0.9048)
print(ct.c2d(G, 0.1, method="tustin")) # (0.04762 z + 0.04762) / (z - 0.9048)
8.5 数字 PID
把 PID 的积分换成累加、微分换成差分:
位置式(直接算出控制量):
增量式(算出控制量的变化量,再累加):
两种形式在没有限幅时完全等价。增量式的好处:不需要保存累加和,输出限幅时天然不会积分饱和(直接对 \(u\) 限幅即可),手动/自动切换时不会跳变,适合步进电机、阀门这类本身就是「增量」的执行器。
#define TS 0.01f
#define KP 2.0f
#define KI 1.0f
#define KD 0.1f
/* 位置式:直接算出控制量 u(k) */
float pid_position(float e)
{
static float sum = 0.0f, e_prev = 0.0f;
float u;
sum += e * TS;
u = KP * e + KI * sum + KD * (e - e_prev) / TS;
e_prev = e;
return u;
}
/* 增量式:算出控制量的增量 du(k),调用方做 u += du */
float pid_increment(float e)
{
static float e1 = 0.0f, e2 = 0.0f; /* e(k-1)、e(k-2) */
float du = KP * (e - e1) + KI * TS * e + KD * (e - 2.0f * e1 + e2) / TS;
e2 = e1;
e1 = e;
return du;
}
这是最简化的写法,用 static 变量只能有一个实例。项目里应该用结构体保存参数和状态,并加上限幅、抗饱和、微分滤波,见第9章的完整实现。
实现时最容易出的问题
- 采样周期不固定:在主循环里「能跑多快跑多快」,每次的 \(T_s\) 都不一样,积分和微分就全错了。要用定时器中断或者固定周期的任务,并测一下实际周期;
- 参数和 \(T_s\) 绑定:如果把 \(K_iT_s\)、\(K_d/T_s\) 预先乘好当成参数,改了采样周期就要重新调参;
- 微分直接对原始测量做差分:噪声被放大 \(1/T_s\) 倍,采样越快越严重,必须滤波(第9章);
- 浮点和整数:在没有浮点单元的单片机上,要用定点数,注意溢出和精度。
8.6 采样周期怎么选
零阶保持器的输出比原信号平均晚 \(T_s/2\),计算也要时间(读传感器、算、输出,最坏可能晚一整个周期)。延迟在截止频率处造成的相位损失约为
例 第6章超前校正后的系统(连续时 \(\omega_c=1.55\) rad/s、\(\gamma=50.5^\circ\)),对象用零阶保持离散化、控制器用 Tustin 离散化后的相位裕度:
| 采样周期 \(T_s\) | 0.05 s | 0.1 s | 0.2 s | 0.5 s |
|---|---|---|---|---|
| 估算损失 \(\omega_cT_s/2\) | 2.2° | 4.4° | 8.9° | 22.2° |
| 实际相位裕度 | 48.3° | 46.0° | 41.5° | 27.5° |
| 再加一拍计算延迟 | 43.8° | 37.2° | 23.8° | −17.3°(不稳定) |
估算和实际很接近。经验规则:
- 取 \(\omega_cT_s\approx0.1\sim0.3\),相位损失 3°~9°,基本可以忽略;或者说采样频率取闭环带宽的 10~30 倍;
- 「读传感器 → 计算 → 输出」要尽量紧凑,并且每次的时间要固定;
- 常见的量级:电机电流环 10~20 kHz,速度环约 1 kHz,位置环 100 Hz~1 kHz;温度控制 1~10 Hz;多旋翼姿态角速度环 500 Hz 到几 kHz。
采样也不是越快越好:采样太快,相邻两次的测量几乎一样,差分得到的微分基本全是噪声;数值精度问题也会变严重(极点都挤在 \(z=1\) 附近)。
在实验台里试一下:默认对象有 1 s 延迟,PI 参数是按连续系统整定的。把采样周期从 10 ms 拉到 1 s,超调从约 4% 增加到约 23%。
常见错误
- 只按采样定理选采样频率(2 倍远远不够);
- 传感器输入没有抗混叠滤波,高频噪声混叠成低频干扰;
- 用前向欧拉离散化快速的环节,\(T_s\) 稍大就不稳定;
- 采样周期不固定,或者控制参数里隐含了 \(T_s\),改了周期却没改参数。
本章小结
- 数字回路 = 采样 + 计算 + 零阶保持;新问题是混叠、延迟、量化。
- 采样定理 \(f_s>2f_{\max}\) 是下限;A/D 前要抗混叠滤波。
- \(z^{-1}\) 是延迟一拍;差分方程 ↔ 脉冲传递函数;稳定 ⟺ 极点在单位圆内。
- 控制器离散化常用 Tustin,对象离散化用 ZOH;前向欧拉可能破坏稳定性。
- 数字 PID 有位置式和增量式;采样周期要固定。
- 采样和计算延迟损失相位 \(\approx\omega_c(T_s/2+\tau)\);取 \(\omega_cT_s\approx0.1\sim0.3\)。
练习
1. 用 1 kHz 采样一个 900 Hz 的振动信号,采样后看起来是多少 Hz?
\(|900-1000|=100\) Hz。高于奈奎斯特频率 500 Hz 的信号被混叠成了 100 Hz。
2. 差分方程 \(y(k)=0.8y(k-1)+0.2u(k-1)\),求脉冲传递函数、极点和直流增益。它稳定吗?
\(G(z)=\dfrac{0.2}{z-0.8}\),极点 0.8 在单位圆内,稳定;直流增益 \(G(1)=0.2/0.2=1\)。如果采样周期是 0.1 s,它相当于时间常数 \(\tau=-T_s/\ln0.8\approx0.45\) s 的一阶惯性环节。
3. 用后向欧拉离散化 \(\frac{1}{0.05s+1}\),采样周期 10 ms,写出差分方程。
\(\alpha=\dfrac{T_s}{\tau+T_s}=\dfrac{0.01}{0.06}\approx0.167\),\(y(k)=y(k-1)+0.167\,[u(k)-y(k-1)]\)。
4. 一个速度环的截止频率是 100 rad/s,希望采样和计算延迟造成的相位损失不超过 5°,采样周期最大取多少?(假设计算延迟为半个周期)
总延迟 \(T_s/2+T_s/2=T_s\),\(\Delta\varphi=100T_s\le5^\circ=0.0873\) rad,所以 \(T_s\le0.87\) ms,大约用 1 kHz 以上的采样频率。
5. 增量式 PID 为什么不容易积分饱和?
增量式算的是 \(\Delta u\),输出 \(u(k)=u(k-1)+\Delta u(k)\) 本身就是一个累加器。对 \(u\) 限幅之后,累加器存的就是限幅后的值,不会在饱和期间继续「攒」误差。位置式的积分和与输出是分开的,饱和时积分和还会继续增大,所以要专门做抗饱和。