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

Канал цифровой связи

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

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

  • 2.5 Гц – частота на “прикладном уровне” модели (генератор порождает числа от 0 до 10)
  • 10 Гц – частота потока битов после цифровой модуляции (4-битные пакеты)
  • 80 Гц – частота на физическом уровне (биполярный цифровой сигнал и манчестерское кодирование 1 к 8)

На принимающей стороне производится подсчет ошибок, как на уровне чисел, так и на уровне битов.

Структура модели

image.png

В модель входят:

  • Генератор чисел от 0 до 10
  • Модулятор, который переводит их в 4-битные последовательности
  • Преобразователь униполярного сигнала в биполярный
  • Цифровой фильтр для применения к сигналу кода Манчестера
  • Канал с добавлением гауссовского шума

И набор обратных операций:

  • Сопряженный принимающий фильтр для кода Манчестера
  • Преобразователь из биполярного сигнала в униполярный
  • Блок подсчета битовых ошибок между отправленным и принятым сигналом
  • Демодулятор, который из каждой группы по 4 бита делает числа от 0 до 10

Общий вид модели

image.png

Такая модель позволяет заглянуть в каждую линию связи и посмотреть, что из себя представляет сигнал на каждом этапе передачи.

Запуск модели из скрипта

Для автоматизации анализа нужно закрыть модель (если она открыта на холсте) и запустить эту модель под программным управлением.

In [ ]:
# Запуск модели
if "simple_digital_channel" in [m.name for m in engee.get_all_models()]
    model = engee.open( "simple_digital_channel" );
else
    model = engee.load( "$(@__DIR__)/simple_digital_channel.engee" );
end

results = engee.run( model )
Out[0]:
Dict{String, DataFrames.DataFrame} with 9 entries:
  "Кол-во ошибок передачи"    => 101×2 DataFrame…
  "Приемный фильтр"           => 801×2 DataFrame…
  "Выходной бинарный вектор"  => 26×2 DataFrame…
  "Входной сигнал и задержка" => 26×2 DataFrame…
  "Бинарный вектор"           => 26×2 DataFrame…
  "Входной сигнал"            => 26×2 DataFrame…
  "Сигнал в канале"           => 801×2 DataFrame…
  "Формирующий фильтр"        => 801×2 DataFrame…
  "Реконструкция сигнала"     => 26×2 DataFrame
In [ ]:
#engee.close( "simple_digital_channel", force=true );

Вывод графиков

Подключение библиотек

In [ ]:
# Подключение библиотек
using DataFrames, Plots, Measures
gr(); # Подключение бэкенда - метода отображения графики

Анализ информации на входе и выходе (ряд чисел)

In [ ]:
# Загрузка данных
Sin = results["Входной сигнал и задержка"];
Sout = results["Реконструкция сигнала"];

# Построение графиков
plot(
    plot( Sin.time, Sin.value, st=:step, xlabel="Время", ylabel="Числа", title="Числа на входе", leg=false ),
    plot( Sout.time, Sout.value, st=:step, xlabel="Время", ylabel="Числа", title="Числа на выходе", leg=false ),
    layout=grid(1, 2, widths=(4/8,4/8)), size=(900,300), margin=5mm, guidefont = font( 7 )
)
Out[0]:

Анализ битовых массивов на входе и выходе

In [ ]:
# Загрузка данных
Bin = results["Бинарный вектор"]
Bout = results["Выходной бинарный вектор"]

Bin_a = [v[1] for v in Bin.value]
Bin_b = [v[2] for v in Bin.value]
Bin_c = [v[3] for v in Bin.value]
Bin_d = [v[4] for v in Bin.value]

Bout_a = [v[1] for v in Bout.value]
Bout_b = [v[2] for v in Bout.value]
Bout_c = [v[3] for v in Bout.value]
Bout_d = [v[4] for v in Bout.value]

# Построение графиков
plot( 
    plot( Bin.time, [Bin_a Bin_b.+1.1 Bin_c.+2.2 Bin_d.+3.3], st=:step,
      xlabel="Время", ylabel="Биты", title="Входной массив", leg=false ),
    plot( Bout.time, [Bout_a Bout_b.+1.1 Bout_c.+2.2 Bout_d.+3.3], st=:step,
      xlabel="Время", ylabel="Биты", title="Выходной массив", leg=false ),
    layout=grid(1, 2, widths=(4/8,4/8)), size=(900,300), margin=5mm, guidefont = font( 7 )
)
Out[0]:

Отобразим количество ошибочно принятых битов

In [ ]:
# Загрузка данных
ERC = results["Кол-во ошибок передачи"]

# Построение графиков
plot( 
    plot( ERC.time, ERC.value, st=:step, xlabel="Время", ylabel="Сигнал", title="Количество ошибок приема", leg=false ),
    size=(900,400), margin=5mm, guidefont = font( 7 )
)
Out[0]:

Изучим шум в канале

In [ ]:
# Загрузка данных
Fin = results["Формирующий фильтр"];
AWGN_out = results["Сигнал в канале"];
Fout = results["Приемный фильтр"];

# Построение графиков
plot( 
    plot( Fin.time, Fin.value, st=:step, xlabel="Время", ylabel="Сигнал", title="Сигнал из формирующиего фильтра (идеальный)", leg=false ),
    plot( AWGN_out.time, AWGN_out.value, st=:step, xlabel="Время", ylabel="Сигнал", title="Сигнал в канале (с белым шумом)", leg=false ),
    plot( Fout.time, Fout.value, st=:step, xlabel="Время", ylabel="Сигнал", title="Сигнал после принимающего фильтра", leg=false ),
    layout=grid(3, 1),
    size=(900,600), margin=5mm, guidefont = font( 7 )
)
Out[0]:

Вывод

На основе этого примера можно рассчитывать параметры избыточности кодирования, проверять коды коррекции ошибок или проверять работу канала связи на физическом уровне с другим кодированием сигнала: частотным, фазовым, сделать канал частью виртуального стенда и многое другое.

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