Документация Engee
Notebook

Системные объекты EngeeDSP

Системный объект — это специализированная программная конструкция в среде технических расчётов Engee. Объекты используются для реализации и моделирования динамических систем с входами, изменяющимися во времени. Они упрощают построение систем потоковой обработки в скриптах Engee.

В качестве примера динамической системы можно рассмотреть чтение "кадра" из нескольких отсчётов сигнала, записанного в длинный файл, последующей обработки этого кадра цифровым фильтром, или же спектрального анализа методом БПФ или банка фильтров. Все звенья этой цепи можно представить последовательностью соответствующих системных объектов.

so.png

В этом примере мы рассмотрим возможность реализации схемы потоковой обработки и визуализации, аналогичной эталонной модели Engee, которую собрали из параметризуемых блоков. Модель reference_FFT.engee является вариацией рассмотренной ранее модели из данного примера.

Модифицированная модель обрабатывает действительный сигнал с линейной частотной модуляцией (ЛЧМ) фильтром нижних частот (ФНЧ) с конечной импльсной характеристикой (КИХ), а затем буферизует кадр данных и вычисляет результат оконного быстрого преобразования Фурье (БПФ) с последующей визуализацией действительной части спектра.reference_fft--1773861203257.png

Ожидаемое поведение алгоритмов ЦОС можно наблюдать при запуске модели в окне "Визуализация сигналов". Данную цепь обработки мы реализуем в скрипте формата *.ngscript на основе системных объектов библиотеки EngeeDSP.

Укажем используемые библиотеки системных объектов и функций ЦОС:

In [ ]:
using EngeeDSP
using EngeeDSP.Functions

Зададим основные параметры цифровой системы, такие как частота дискретизации и размер обрабатываемого кадра:

In [ ]:
fs = 8000;
framesize = 512;

Источник потокового сигнала

В качестве источника сигнала с линейно изменяющейся частотой дискретизации будем использовать системный объект SineWaveDSP. Он генерирует синусоидальное колебание, частоту которого мы можем изменять в цикле, тем самым аппроксимируя поведение источника ЛЧМ-сигнала. Передадим ему параметры частоты дискретизации и размера кадра:

In [ ]:
source = SineWaveDSP();
source.SampleTime = 1//fs;
source.SamplesPerFrame = framesize;
source
Out[0]:
SineWaveDSP:
    Amplitude=1
    Frequency=100
    PhaseOffset=0
    SampleMode=Discrete
    OutputComplexity=Real
    ComputationMethod=Trigonometric fcn
    SampleTime=1//8000
    SamplesPerFrame=512
    ResettingStatesWhenReEnabled=Restart at time zero

Рассмотрим поведение объекта при его вызове и сбросе состояний:

In [ ]:
release!(source)
In [ ]:
x = source();
plot(x, leg=false)
Out[0]:

Фильтр нижних частот

Начнём с создания прототипа подходящего фильтра нижних частот. Для этого используем функции синтеза и анализа из библиотеки EngeeDSP.Functions:

In [ ]:
n = 15;
firwin = window("hamming", n+1)
b = fir1(n, 2000/(fs/2), firwin, "low");
freqz(b, 1, 512, fs, out=:plot)
Out[0]:

Коэффициенты числителя передаточной функции прототипа фильтра передадим системному объекту DiscreteFIRFilter. О влиянии состояний фильтра на форму обрабатываемого сигнала более подробно рассказывается в этом примере сообщества:

In [ ]:
FIR = DiscreteFIRFilter();
FIR.Coefficients = b;
setup!(FIR, zeros(framesize));
plot(b, l=:stem, m=:c)
Out[0]:

Оконная функция

Для оконной функции необязательно использовать системный объект, так как её математика не меняется в зависимости от предыдущих значений сигнала и состояний. Достаточно просто сформировать вектор значений окна Хэмминга размером с кадр данных во временной области:

In [ ]:
hamwin = window("hamming", framesize);
plot(hamwin,l=:stem,label="Hamming window")
Out[0]:

БПФ

Системный объект EngeeFFT будет наследовать размер входного кадра, но численные значения комплексных отсчётов мы будем делить на длину БПФ:

In [ ]:
FFT = EngeeFFT();
FFT.DivideOutputFFTLength = true;
FFT
Out[0]:
EngeeFFT:
    FFTImplementation=Radix-2
    OutputInBitReversedOrder=false
    DivideOutputFFTLength=true
    InheritFFTLength=true
    FFTLength=64
    WrapInputData=true

Преобразование в дБм

Объект dbConverion позволяет устанавливать параметры входного и выходного сигналов. В нашем случае мы преобразуем амплитуду в дБм:

In [ ]:
dbconv = dBConversion()
dbconv.ConvertTo = "dBm";
dbconv
Out[0]:
dBConversion:
    ConvertTo=dBm
    InputSignal=Amplitude
    LoadResistance=1
    AddEpsToInputToProtectAgainst=false

Основной цикл обращения к системным объектам

Зададим численные вектора изменяющегося значения частоты повторений источника синусоидального сигнала freq_range. Частота будет изменяться в пределах от 50 Гц до 4000 Гц с шагом 50 Гц.

Также инициализируем вектор частотной сетки freqvec для последующего отображения спектра.

Количество итераций основного цикла будет соответствовать длине вектора нарастающих значений частоты синусоиды. Результат обработки будем помещать покадрово в матрицу spectrum:

In [ ]:
freq_range = 50:50:Int(fs/2);
freqvec = LinRange(0.0,fs/2,Int(framesize/2));
count = length(freq_range);
spectrum = zeros(Int(framesize/2),count);

На каждом шаге цикла происходит изменение параметра частоты системного объекта генератора синусоиды, запись отрезка синуса в переменную sine_chunk, обработка этого кадра КИХ-фильтром, применение оконной функции, вычисление комплексного вектора БПФ, обрезка его до "середины", вычисление модуля и перевод из амплитуды в дБм:

In [ ]:
for k = 1:count
    source.Frequency = freq_range[k];
    sine_chunk = source();
    LPF = FIR(sine_chunk);
    complexFFT = FFT(LPF .* hamwin);
    absFFT = abs(complexFFT[1:Int(framesize/2)]);
    spectrum[:,k] = dbconv(absFFT);
end

Визуализация

Отобразим изменение спектра в динамике за всё время "динамической симуляции" при помощи трёхмерной поверхности:

In [ ]:
surface(1:count, freqvec, spectrum)
Out[0]:

А также визуализируем анимацию изменения спектра:

In [ ]:
anim = @animate for i = 1:count
    plot(freqvec, spectrum[:,i], 
                    lw=2, 
                    ylim = (-120,30), 
                    leg = false, 
                    title = "Спектр ЛЧМ-сигнала",
                    yguide = "dBm",
                    xguide = "Частота (Гц)",
                    size = (800,200))
end
gif(anim, "dynamic_spectrum.gif", fps = 10)
Out[0]:
No description has been provided for this image

Заключение

Мы рассмотрели возможность построения полноценной динамической модели потоковой обработки и визуализации сигналов на базе системных объектов EngeeDSP. Модель включает в себя функциональные узлы:

  • источника синусоиды с изменяющейся частотой повторений
  • КИХ-фильтра нижних частот
  • оконной функции
  • быстрого преобразования Фурье
  • вычисления спектра сигнала в дБм
  • визуализации