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

Генерация КИХ-фильтра при помощи командного управления

Открыть пример в Engee

В этой демонстрации покажем вам, как применять командное управления для реализации однатипных действий, а также поделимся методами упрощения процесса построения моделей.

Начнём с подключения библиотек, которые нам понадобятся для реализации проекта.

In [ ]:
using Plots, DSP; # Подключение библиотек PLots и DSP

Теперь, используя библиотеку DSP, сгенерируем коэффициенты для нашего фильтра.

In [ ]:
st = 0.0001;
fc = [500 1200]'; # Частоты сигнала
fs = 6000; # Частота дискретизации сигнала
t = [0:1/fs:0.001;]; # Диапазон времени сигнала
x = cos.(2*pi*fc[1]*t) + cos.(2*pi*fc[2]*t); # Пример сигнала для фильтрации
responsetype = Lowpass(2000; fs); # Определение полосы пропускания
print("Размер окна фильтрации:")
N = parse(Int,readline())
designmethod = FIRWindow(hanning(N)); # Определение размеров окна
x_filt =filt(digitalfilter(responsetype, designmethod), x); # Фильтрация сигнала
c=digitalfilter(responsetype, designmethod); # FIR-фильтр
coef=length(c); # Количество коэффициентов фильтра
Размер окна фильтрации:stdin>  5
Out[0]:
5

Построим графики спектральной плотности мощности – исходного сигнала и сигнала после фильтрации.

In [ ]:
p1 = periodogram(x); 
plot(freq(p1), power(p1), xlabel="частота, Гц", ylabel="спектральная плотность мощности", label="исходный сигнал")
p2 = periodogram(x_filt);
plot!(freq(p2), power(p2), label="отфильтрованный сигнал")
Out[0]:

Теперь создадим модель, в которой сгенерируем сам фильтр.

In [ ]:
print("Напишите название вашей модели:")
name_model = readline()
Path = (@__DIR__) * "/" * name_model * ".engee"
if isdir(Path)
	rm(Path;force = true, recursive = true)	
end
engee.create(name_model) # Создать модель
Напишите название вашей модели:stdin>  fir_filter
Out[0]:
Model(
	name: fir_filter
	id: 7a06b003-8e53-4e8c-8ae9-811e511419a6
)

Для начала зададим входные и выходные порты модели.

In [ ]:
engee.add_block("/Basic/Ports & Subsystems/In1", name_model*"/"); # Создание входного порта для подсистемы
engee.add_block("/Basic/Ports & Subsystems/Out1", name_model*"/"); # Создание выходного порта для подсистемы

Теперь объявим цикл для создания модели FIR-фильтра.

In [ ]:
for n in 1:coef-1 
    name_gain="Gain-"*string(n); # Задаем имя блока для Gain 
    engee.add_block("/Basic/Math Operations/Gain", name_model*"/"*name_gain); # Добавим в модель Gain
    engee.set_param!(name_model*"/"*name_gain, "Gain" => c[n]); # Установим значения коэффициентов фильтра
    name_delay="Delay-"*string(n); # Задаем имя блока для Delay
    engee.add_block("/Basic/Discrete/Delay", name_model*"/"*name_delay); # Добавим в модель Delay
    engee.set_param!(name_model*"/"*name_delay, "DelayLength" => 1); # Установим длину задержки равной 1
    engee.set_param!(name_model*"/"*name_delay, "SampleTime" => st); # SampleTime для Delay
    name_add="Add-"*string(n); # Задаем имя блока для Add
    engee.add_block("/Basic/Math Operations/Add", name_model*"/"*name_add); # Добавим в модель Add
    if n==1
        engee.add_line(name_gain*"/1", name_add*"/1"); # Соединим Gain и Add 1 вход
    end
    if n>1
        name_delay_1="Delay-"*string(n-1); # Задаем имя блока для предыдущего Delay
        engee.add_line(name_delay_1*"/1", name_delay*"/1"); # Соединим Delay n-1 и Delay n
        engee.add_line(name_delay_1*"/1", name_gain*"/1"); # Соединим Delay n-1 и Gain n
        name_add_1="Add-"*string(n-1); # Задаем имя блока для предыдущего Add
        engee.add_line(name_add_1*"/1", name_add*"/1");  # Соединим Add n-1 и Add 1 вход
        engee.add_line(name_gain*"/1", name_add_1*"/2"); # Соединим Gain n-1 и Add 2 вход
    end
    if n==coef-1
        name_gain="Gain-"*string(n+1); # Задаем имя блока для Gain
        engee.add_block("/Basic/Math Operations/Gain", name_model*"/"*name_gain); # Добавим в модель Gain
        engee.set_param!(name_model*"/"*name_gain, "Gain" => c[n+1]); # Установим значения коэффициентов фильтра
        engee.add_line(name_delay*"/1", name_gain*"/1"); # Соединим Delay и Gain
        engee.add_line(name_gain*"/1", name_add*"/2"); # Соединим Gain и Add 2 вход
        engee.add_line(name_add*"/1", "Out1/1");  # Соединим Add и Out1
    end
end
engee.add_line("In1/1", "Gain-1/1"); # Соединим In1 и Gain-1
engee.add_line("In1/1", "Delay-1/1"); # Соединим In1 и Delay-1

Сохраним результат в модель и изменим параметры моделирования.

In [ ]:
engee.save(Path)
model = engee.load(Path, force=true ) # Загрузить модель
engee.set_param!(model, "StopTime" => 5, "FixedStep" => 0.1) # меняем фиксированный размер шага и время окончания симуляции
param = engee.get_param(model) # Получение параметров текущей модели
Out[0]:
ModelParameters(
  :EnableMultiTasking => false
  :GenerateComments => true

  #Параметры интегратора:
  :StartTime => 0.0
  :StopTime => 5.0
  :SolverType => fixed-step
  :SolverName => Euler
  :FixedStep => 0.1
)

Вывод

В данном примере мы разобрали пример использования командного управления для автоматической генерации моделей.

Блоки, использованные в примере