3、信号基础:时域与频域概念、采样定理、常见信号类型

各位同学,欢迎来到第三讲。说实话,每次讲到信号基础,我都会想起刚入行时被频谱仪支配的恐惧。那时候看波形就是波形,哪知道背后还有这么多门道。今天咱们就把这些基础概念掰开揉碎了讲清楚。

3.1 时域与频域:一枚硬币的两面

先问大家一个问题:你平时看到的信号长什么样?

大概率是示波器上那种随时间变化的曲线,对吧?这就是时域——横轴是时间,纵轴是幅度。比如一个正弦波,你看到的就是它上下起伏的样子。

但信号还有另一面:频域。横轴变成频率,纵轴变成幅度或相位。说白了,就是告诉你这个信号里包含哪些频率成分,每个成分有多强。

我打个比方你就明白了。时域像是一首交响乐的乐谱随时间展开,你能看到每个音符什么时候响起。频域呢,就像这张乐谱的和声分析——告诉你整首曲子用了哪些音高,每个音高出现了多少次。

核心要点:时域和频域描述的是同一个信号,只是观察角度不同。傅里叶变换就是连接这两座城市的桥梁。

我在项目中遇到过一位同事,死活理解不了频域有什么用。后来我让他看一段电机振动信号,时域上就是乱糟糟的波形,但转到频域后,几个明显的尖峰直接指向了轴承故障频率。他当场就服了。

3.2 采样定理:别让你的信号失真

好,现在问题来了:计算机只能处理离散的数字信号,而现实世界是连续的模拟信号。怎么把连续的变成离散的?采样

采样这事儿看着简单,但坑特别多。我来讲讲著名的奈奎斯特采样定理

采样定理:采样频率必须大于信号最高频率的两倍,才能无失真地恢复原始信号。

用公式表示就是:

fs > 2 * fmax

其中 fs 是采样频率,fmax 是信号中的最高频率成分。

为什么会这样?你想想看,如果采样频率太低,高频信号会被误认为低频信号,这就是混叠现象。我举个例子:

假设有一个 100Hz 的正弦波,你用 150Hz 去采样。结果呢?采样点连起来一看,变成了 50Hz 的波形。100Hz 的信号被「伪装」成了 50Hz,这就是混叠。

避坑指南:我曾经在一个振动监测项目里吃过这个亏。传感器采集的振动信号最高频率是 500Hz,我图省事用了 800Hz 采样率。结果频谱分析时发现 200Hz 附近有个莫名其妙的尖峰,排查了半天才发现是 600Hz 的噪声混叠下来的。从那以后,我采样率至少留 2.5 倍余量。

实际工程中,我建议采样频率取信号最高频率的 3~5 倍。另外,采样前一定要加抗混叠滤波器,把高于 fs/2 的频率成分滤掉。这是标准操作,别偷懒。

3.3 常见信号类型:正弦、方波、噪声

搞信号处理,你得认识几种基本信号。就像学英语要先认识字母一样。

3.3.1 正弦波

正弦波是最基础的信号,没有之一。它的数学表达式是:

x(t) = A * sin(2πft + φ)

其中 A 是幅度,f 是频率,φ 是初相位。

正弦波在频域上只有一个尖峰,干净利落。我经常用它来测试系统的频率响应——给系统输入一个正弦波,看输出变成什么样,就能知道系统对这个频率的增益和相位延迟。

3.3.2 方波

方波就更有意思了。你看它时域上就是高低电平来回跳变,但转到频域一看——好家伙,全是尖峰!

方波其实是由无数个奇次谐波的正弦波叠加而成的。具体来说:

方波 = 基波 + 3次谐波/3 + 5次谐波/5 + 7次谐波/7 + ...

谐波次数越高,幅度越小。所以方波的频谱是一根根逐渐衰减的谱线,间隔正好是基频的奇数倍。

个人经验:我在做数字电路信号完整性分析时,经常用方波来模拟时钟信号。方波的上升沿越陡,高频分量就越多,对 PCB 布线的要求也越高。你想想看,一个 1MHz 的方波,如果上升沿只有 1ns,那它的有效频率成分可能高达几百 MHz。这就是为什么高速数字设计那么讲究。

3.3.3 噪声

噪声这东西,做信号处理的人天天打交道。常见的噪声类型有:

噪声类型 特点 频谱特征
白噪声 所有频率能量均匀分布 平坦的功率谱
粉红噪声 低频能量高,高频能量低 功率谱按 1/f 衰减
脉冲噪声 突然出现的尖峰 宽频带,能量分散

白噪声是最常见的,比如热噪声就是白噪声。它的功率谱密度是常数,意味着每个频率上的能量都一样多。

粉红噪声在自然界中很常见,比如瀑布声、风声。它的能量主要集中在低频段,所以听起来更「柔和」。

脉冲噪声嘛,我印象最深的是有一次在工厂现场采集数据,信号里时不时出现一个巨大的尖峰。排查了半天,发现是旁边一台电焊机工作时产生的电磁干扰。这种噪声在时域上很明显,但在频域上因为能量分散,反而不容易识别。

3.4 用 Python 看看这些信号

光说不练假把式。咱们用 Python 生成几种信号,看看它们在时域和频域上长什么样。

import numpy as np
import matplotlib.pyplot as plt

# 参数设置
fs = 1000  # 采样频率 1000Hz
t = np.arange(0, 1, 1/fs)  # 时间向量,1秒

# 1. 正弦波
f1 = 5  # 频率 5Hz
sin_wave = np.sin(2 * np.pi * f1 * t)

# 2. 方波
square_wave = np.sign(np.sin(2 * np.pi * f1 * t))

# 3. 白噪声
noise = np.random.randn(len(t))

# 计算频谱
def plot_spectrum(signal, fs, title):
    n = len(signal)
    freq = np.fft.fftfreq(n, 1/fs)[:n//2]
    spectrum = np.abs(np.fft.fft(signal))[:n//2] / n * 2
    plt.figure(figsize=(10, 4))
    plt.subplot(1, 2, 1)
    plt.plot(t[:200], signal[:200])
    plt.title(f'{title} - 时域')
    plt.xlabel('时间 (s)')
    plt.subplot(1, 2, 2)
    plt.plot(freq, spectrum)
    plt.title(f'{title} - 频域')
    plt.xlabel('频率 (Hz)')
    plt.tight_layout()
    plt.show()

plot_spectrum(sin_wave, fs, '正弦波')
plot_spectrum(square_wave, fs, '方波')
plot_spectrum(noise, fs, '白噪声')

运行这段代码,你会看到:

  • 正弦波的频谱只有一根线,干净利落
  • 方波的频谱是一根根逐渐衰减的谱线,间隔 5Hz
  • 白噪声的频谱几乎是平的,所有频率能量差不多

小技巧:用 np.fft.fft 计算频谱时,记得只取前一半(正频率部分),并且要归一化。我刚开始用的时候经常忘记归一化,结果频谱的幅度怎么都对不上,折腾了半天才发现是这个问题。

3.5 小结

这一讲咱们聊了三个核心概念:

  • 时域和频域是观察信号的两种视角,傅里叶变换是桥梁
  • 采样定理告诉我们采样频率必须大于信号最高频率的两倍,否则会混叠
  • 正弦波、方波、噪声是三种基础信号,各有各的频谱特征

这些概念看着简单,但往后做 CNN 分类时,你会发现它们无处不在。比如你采集到的振动信号,到底是正弦波还是方波?噪声水平高不高?这些都会直接影响你设计网络结构和预处理流程。

下一讲咱们开始讲傅里叶变换的数学原理,以及怎么用 Python 实现 FFT。到时候你会发现,今天这些基础概念全都用得上。

好了,今天就到这儿。有问题随时问我。