第4章 数字信号处理基础:离散时间信号与系统、Z变换基础、数字滤波器设计(FIR/IIR)、定点与浮点运算
各位同学,欢迎来到第4章。说实话,这一章是OBC数字控制的“内功心法”。你想想看,我们天天跟ADC采样、PWM更新、电流环调节打交道,这些本质上都是在处理离散时间信号。如果这块基础不牢,后面写控制算法代码时,很容易掉坑里。
我个人习惯,在讲具体算法之前,先把这些数学工具理清楚。别怕,咱们不搞纯理论推导,我尽量用工程师的视角来讲。
4.1 离散时间信号与系统
什么叫离散时间信号?说白了,就是一连串的数字序列。比如你每隔10微秒采一次电流值,得到的就是离散信号。连续信号是x(t),离散信号我们写成x[n],n是整数索引。
我在项目中遇到过一个问题:采样率选低了,结果高频谐波混叠到低频,电流环怎么调都抖。后来才意识到,这是违反了奈奎斯特定理——采样频率必须大于信号最高频率的两倍。
核心要点:
- 离散时间系统:输入x[n],输出y[n],系统对输入做某种运算
- 线性时不变系统(LTI):最常用,叠加性和时不变性
- 单位脉冲响应h[n]:输入为δ[n]时的输出,决定了系统全部特性
判断一个系统是不是LTI,有个简单方法:看它有没有“记忆”。比如y[n] = 2x[n] + 3x[n-1],这就是LTI。但y[n] = x[n]²,就不是线性系统。嗯,这里要注意,实际DSP算法里,我们几乎都在跟LTI系统打交道。
4.2 Z变换基础
Z变换,你可以把它理解成离散时间领域的拉普拉斯变换。为什么要学它?因为有了Z变换,差分方程就变成了代数方程,解起来方便多了。
定义式:X(z) = Σ x[n] z^{-n},从n=0到∞。注意,我们通常用单边Z变换,因为实际信号都是因果的。
我记得刚入行时,总觉得Z变换很抽象。后来做数字滤波器设计,发现Z平面上的极点位置直接决定了系统稳定性——极点必须在单位圆内。这个结论太重要了,我建议你记牢。
实用技巧:
做OBC控制时,我们经常用双线性变换法把s域的传递函数映射到z域。公式是:s = (2/T) * (1-z^{-1})/(1+z^{-1})。T是采样周期。这个变换能保证频率响应特性基本不变,但要注意预畸变处理。
常见Z变换对,我列个表,你写代码时直接查:
| 时域序列 x[n] | Z变换 X(z) | 收敛域 |
|---|---|---|
| δ[n] | 1 | 全平面 |
| u[n](单位阶跃) | 1/(1-z^{-1}) | |z| > 1 |
| a^n u[n] | 1/(1-az^{-1}) | |z| > |a| |
| n a^n u[n] | az^{-1}/(1-az^{-1})² | |z| > |a| |
4.3 数字滤波器设计(FIR/IIR)
做OBC,滤波器无处不在。电流采样要滤波,电压反馈要滤波,PLL也要滤波。滤波器分两大类:FIR和IIR。
FIR滤波器:有限脉冲响应,没有反馈。特点是绝对稳定,线性相位。但同样的指标,FIR需要的阶数比IIR高很多。
IIR滤波器:无限脉冲响应,有反馈。效率高,但可能不稳定,相位非线性。
我个人习惯,在电流环里用IIR,因为延迟小。在需要线性相位的场合(比如某些保护逻辑),用FIR。
避坑指南:
我曾经在调试一个OBC项目时,IIR滤波器系数算错了,导致系统在轻载时自激振荡。后来查了三天,才发现是极点跑到了单位圆外。所以,IIR设计完后,一定要检查极点位置!
设计方法上,我常用的是:
- FIR:窗函数法(汉明窗、凯泽窗),简单实用
- IIR:双线性变换法,从模拟滤波器(巴特沃斯、切比雪夫)转换过来
举个例子,设计一个50Hz陷波器,用于滤除电网工频干扰:
// 双线性变换法设计50Hz陷波器,采样率10kHz
// 模拟原型:s^2 + ω0^2
// 预畸变频率 ωd = tan(π*50/10000)
// 这里给出直接型IIR系数
float b0 = 0.9902f;
float b1 = -1.9604f;
float b2 = 0.9902f;
float a1 = -1.9604f;
float a2 = 0.9805f;
// 差分方程实现
y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2];
你看,代码就这么几行。但实际调试时,系数精度很关键。这就引出了下一个话题。
4.4 定点与浮点运算
DSP芯片分两类:定点DSP和浮点DSP。OBC里,成本敏感的项目用定点,比如TI的TMS320F28035;高性能项目用浮点,比如F28379D。
定点数,说白了就是用整数来模拟小数。比如Q15格式,16位有符号数,最高位符号位,剩下15位小数位。表示范围-1到1-2^{-15}。
浮点数就简单了,IEEE754标准,直接写小数。但运算慢,功耗高。
我的经验:
定点运算最怕溢出和精度丢失。我曾经在定点DSP上实现PI控制器,积分项累加时没做饱和处理,结果积分饱和导致系统失控。后来加了抗饱和逻辑才解决。
定点运算的几个关键点:
- 乘法后要左移或右移,恢复Q格式
- 加法要考虑溢出,用饱和指令
- 除法尽量用查表或近似算法
浮点运算虽然方便,但也不是万能的。我记得有一次,浮点DSP上跑滤波器,发现结果有微小抖动。查了半天,原来是浮点精度导致的条件数恶化。所以,浮点也不是银弹。
实用建议:
如果你用定点DSP,我建议把所有系数都归一化到[-1,1)区间,用Q15或Q31格式。这样乘法结果不会溢出。如果系数大于1,就拆成整数部分和小数部分分别处理。
最后,说个实战技巧:在定点DSP上调试时,先把算法在浮点环境下跑通,然后定点化。定点化后,用同样的输入数据对比输出,误差控制在1%以内就算合格。
好了,这一章的内容就这些。离散信号、Z变换、滤波器设计、定点浮点,这些是数字控制的四大基石。下一章我们开始讲PID控制的数字化实现,到时候你会用上今天学的所有东西。