第8章

数字控制:把控制器放进计算机

学完这一章你应该能

  • 画出数字控制回路的结构,说清楚采样、量化、零阶保持各自带来什么问题;
  • 理解采样定理和混叠,知道为什么要加抗混叠滤波;
  • 用 Z 变换和差分方程描述离散系统,用单位圆判断稳定性;
  • 把连续控制器离散化(欧拉法、双线性变换、零阶保持),知道各自的特点;
  • 写出位置式和增量式数字 PID;
  • 按相位裕度的损失选择采样周期。

前置知识:拉氏变换、相位裕度、PID。会一点编程(任何语言)。

为什么要学?今天的控制器几乎都是数字的:单片机、PLC、电脑、无人机飞控、3D 打印机主板……它们每隔一个固定的时间(采样周期 \(T_s\))读一次传感器、算一次、输出一次。前面学的连续理论仍然是基础,但「每隔 \(T_s\) 才动一次」会带来新问题:混叠、延迟、离散化误差。这一章讲清楚这些问题和对应的做法。

8.1 数字控制回路

一个典型的数字控制回路:

  1. 采样(A/D 转换):每隔 \(T_s\) 把连续的测量信号 \(y(t)\) 变成一个数 \(y(k)=y(kT_s)\);
  2. 计算:控制程序根据 \(r(k)\)、\(y(k)\) 和以前的数据算出 \(u(k)\);
  3. 保持(D/A 转换或 PWM):把 \(u(k)\) 输出,并且一直保持到下一个采样时刻(零阶保持器,ZOH),对象看到的是阶梯形的输入。

和连续控制相比,多了三个问题:

8.2 采样定理与混叠

采样定理:要从采样值中无失真地恢复一个信号,采样频率 \(f_s\) 必须大于信号最高频率的 2 倍。\(f_s/2\) 叫奈奎斯特频率。

频率 \(f>f_s/2\) 的信号被采样后,会和频率为 \(|f-nf_s|\)(\(n\) 取使它最小的整数)的低频信号无法区分,这叫混叠。

工程上的含义:

8.3 Z 变换与差分方程

离散系统用差分方程描述:输出 \(y(k)\) 由过去的输出和输入算出。例如

$$y(k)=0.9048\,y(k-1)+0.09516\,u(k-1)$$

就是 \(\frac{1}{s+1}\) 在 \(T_s=0.1\) s 时的离散模型(8.4 节会算出来)。在程序里它就是一行代码:y = 0.9048*y + 0.09516*u。

Z 变换对离散序列的作用,就像拉氏变换对连续函数:

$$X(z)=\mathcal Z[x(k)]=\sum_{k=0}^{\infty}x(k)z^{-k}$$
\(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)\),得到脉冲传递函数

$$G(z)=\frac{Y(z)}{U(z)}=\frac{0.09516z^{-1}}{1-0.9048z^{-1}}=\frac{0.09516}{z-0.9048}$$

终值定理:\(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\) 为时间常数)

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(k)=K_pe(k)+K_iT_s\sum_{j=0}^{k}e(j)+K_d\frac{e(k)-e(k-1)}{T_s}$$

增量式(算出控制量的变化量,再累加):

$$\Delta u(k)=K_p\big[e(k)-e(k-1)\big]+K_iT_se(k)+\frac{K_d}{T_s}\big[e(k)-2e(k-1)+e(k-2)\big],\qquad u(k)=u(k-1)+\Delta u(k)$$

两种形式在没有限幅时完全等价。增量式的好处:不需要保存累加和,输出限幅时天然不会积分饱和(直接对 \(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\),计算也要时间(读传感器、算、输出,最坏可能晚一整个周期)。延迟在截止频率处造成的相位损失约为

$$\Delta\varphi\approx\omega_c\left(\frac{T_s}{2}+\tau_{\text{计算}}\right)\quad(\text{弧度})$$

例 第6章超前校正后的系统(连续时 \(\omega_c=1.55\) rad/s、\(\gamma=50.5^\circ\)),对象用零阶保持离散化、控制器用 Tustin 离散化后的相位裕度:

采样周期 \(T_s\)0.05 s0.1 s0.2 s0.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\) 限幅之后,累加器存的就是限幅后的值,不会在饱和期间继续「攒」误差。位置式的积分和与输出是分开的,饱和时积分和还会继续增大,所以要专门做抗饱和。