Engee 文档
Notebook

DSP 基础知识:信号生成

复习生成周期、脉冲和噪声信号的基本技术,以测试数字信号处理(DSP)算法、通信系统建模、雷达和无线电系统。示例的主要内容包括

  • 周期信号分配
  • 离散信号的时间网格
  • 生成典型的周期信号(正弦波、蜿蜒波、锯齿波)
  • 离散噪音的产生
  • 脉冲序列
  • 频率调制信号

示例中使用的图书馆:

In [ ]:
let
    intalled_packages = collect(x.name for (_, x) in Pkg.dependencies() if x.is_direct_dep)
    list_packages = ["DSP","ChirpSignal","Waveforms"]
    for pack in list_packages
        pack in intalled_packages || Pkg.add(pack)
    end
end
In [ ]:
using DSP, ChirpSignal, Waveforms

周期信号的生成

周期信号是一个重复序列。让我们创建一个周期的信号值,然后使用函数repeat 将其重复五次。用阶梯线将其时间可视化:

In [ ]:
one_period = [1; 4; 6; 8; 7; 5; 0; 0; 0; 0];
five_period = repeat(one_period, 5);
plot(five_period, 
    linewidth = 2,
    marker = "circle", 
    markersize = 3, 
    linetype=:steppost,
    title = "Простой периодический сигнал")
Out[0]:

现在,让我们尝试使用数学函数生成周期信号。例如,函数sin 可以计算以弧度为单位的输入角度值的正弦值。为了以所需的重复率生成正弦波,我们应该使用时间矢量--一串均匀递增的时间采样,并具有指定的采样周期。让我们为采样率为 1000 Hz 的信号设置时间矢量:

In [ ]:
fs = 1000;              # частота дискретизации сигнала
dt = 1/fs;              # период дискретизации
stoptime = 0.5;         # время окончания сигнала
t = 0:dt:stoptime-dt    # вектор отсчётов времени
Out[0]:
0.0:0.001:0.499

现在我们来创建一个基本频率为 10 Hz 的周期性正弦信号(正弦波的形状每 0.1 秒重复一次)。变量sine_wave 是一个包含 500 个采样点的向量。使用函数plot 可视化信号:

In [ ]:
sine_wave = sin.(2*pi*t*10);
plot(t, sine_wave, title = "Синусоида частотой 10 Гц")
Out[0]:

我们可以用一行代码生成多个具有不同振幅、频率和初始相位的正弦波。为此,我们将这些参数设置为向量。生成的变量three_sines 将是一个 500x3 的矩阵。我们可以将其传递给函数plot ,以便在同一坐标轴上同时显示三个图形:

In [ ]:
three_sines = [1.4 0.6 1] .* sin.(2*pi*t.*[10 15 30] .+ [pi/4 0 pi/6]);
plot(t, three_sines, title = "Три синусоиды 10 Гц, 15 Гц и 30 Гц")
Out[0]:

如果我们想观察三个正弦波之和的形状,可以使用函数sum 将矩阵的列相加:

In [ ]:
sum_sines = sum(three_sines, dims = 2);
plot(t, sum_sines, title = "Сумма трёх синусоид")
Out[0]:

信号生成附加函数

我们经常需要矩形、锯齿形和三角形周期信号以及随机序列来进行噪声建模。

Waveforms.jl 函数库包含生成上述周期信号的函数,但从 0 到 2pi 变化的均匀递增锯齿信号被用作决定基频的 "设置 "信号。让我们从时间矢量中创建锯齿信号,并通过mod 除以 2pi 的操作对其进行循环:

In [ ]:
base_signal = mod.(2*pi*t*10, 2*pi);
plot(t, base_signal, title = "Задающий сигнал для функций")
Out[0]:

无线电工程中常用的信号是蜿蜒信号。它是一个频率为 2(或填充因子为 50%)的矩形周期信号。我们可以用函数squarewave 生成它。该函数还可以接受一个额外的输入参数--0 至 1 范围内的填充因子。让我们生成第二个填充因子为 20% 的矩形信号:

In [ ]:
sqw = squarewave.(base_signal);
sqw02 = squarewave.(base_signal, 0.2);
plot(t, sqw)
plot!(t, sqw02, title = "Прямоугольный сигнал")
Out[0]:

通过函数sawtoothwave 可以得到从 -1 到 +1 变化的锯齿信号:

In [ ]:
st = sawtoothwave.(base_signal);
plot(t, st, title = "Пилообразный сигнал")
Out[0]:

还可以考虑使用函数trianglewave 生成三角信号:

In [ ]:
trw = trianglewave.(base_signal);
plot(t, trw, title = "Треугольный сигнал")
Out[0]:

Engee 提供生成不同分布随机数的函数。让我们使用函数rand 生成均匀分布的噪声信号:

In [ ]:
noise = rand.(length(t));
noise = noise .- 0.5;
plot(t, noise, title = "Шум с равномерным распределением")
Out[0]:

现在,让我们尝试将噪声和锯齿信号结合起来,但要使噪声电平随信号电平的增加而增加。使用参考信号,我们将产生一个在 0 和 +1 之间变化的锯齿信号。然后将噪声乘以产生的锯齿信号,再将增加的锯齿信号与增加的噪声相加:

In [ ]:
clean_sawtooth = mod.(t*10,1);                          # "чистый" пилообразный сигнал
amp_noise = noise .* clean_sawtooth;                    # нарастающий шумовой сигнал
noisy_sawtooth = clean_sawtooth .+ (0.25 .* amp_noise); # их сумма
plot(t, noisy_sawtooth, title = "Усиление сигнал и шума")
Out[0]:

生成非周期信号和分组脉冲

作为非周期信号的一个例子,让我们来看看常见的sinc 脉冲。我们使用三角函数和以弧度为单位的角度值输入向量来获得它。在示例中,我们生成的脉冲范围为 -2pi 至 +2pi(步长为 pi/16)。

In [ ]:
rads = -2*pi:pi/16:2*pi;
rads = rads[1:end-1];
one_sinc = sinc.(rads);
plot(rads, one_sinc, title = "sinc-импульс")
Out[0]:

现在,让我们创建一个具有一定周期的sinc 脉冲包。为此,请在一个脉冲的矢量末尾添加一定数量的零,并将结果与函数repeat 相乘。我们还将为脉冲群添加阻尼--函数LinRange 将帮助我们实现这一点:

In [ ]:
zero_padding = [one_sinc; zeros(2*length(one_sinc))];   # sinc-импульс с нулями
four_sinc = repeat(zero_padding, 4);                    # пачка импульсов без затухания
decay = LinRange(1, 0.4, length(four_sinc));            # сигнал затухания
pulse_train = four_sinc .* decay;                       # пачка импульсов с затуханием
plot(pulse_train, title = "Пачка sinc-импульсов с затуханием")
Out[0]:

频率调制信号

最后,让我们来看看典型的频率调制信号,如线性频率调制(LFM)信号和正交频率调制信号。要创建这类信号,我们将使用函数chirp

In [ ]:
LFM = chirp(10, fs, 0, 500; method = "linear");
sg1 = DSP.spectrogram(LFM, 511, 256; fs = fs);
heatmap(sg1.time, sg1.freq, pow2db.(sg1.power), 
        xlabel = "Время, сек", 
        ylabel = "Частота, Гц",
        title = "Спектрограмма ЛЧМ-сигнала")
Out[0]:

为了显示信号,我们将调用函数DSP.spectrogram ,该函数可显示信号频谱随时间的变化(功率与频率的关系)。我们可以观察到 LFM 信号的线性频率增长和method = "quadratic" 选项的二次频率增长:

In [ ]:
QFM = chirp(10, fs, 0, 500; method = "quadratic");
sg2 = DSP.spectrogram(QFM, 511, 256; fs = fs);
heatmap(sg2.time, sg2.freq, pow2db.(sg2.power), 
        xlabel = "Время, сек", 
        ylabel = "Частота, Гц",
        title = "Спектрограмма КЧМ-сигнала")
Out[0]:

结论

我们回顾了产生周期信号、非周期信号和噪声信号的基本技术,以帮助我们开发信号处理算法和无线电系统模型。