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

Модуляция основной полосы частот

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

  1. В виде скрипта;

  2. В виде модели.

Схема алгоритма имеет следующий вид:

passband.png

Построение системы при помощи скрипта

Первый шаг построения системы: подключаем все используемые системные элементы и библиотеки.

using FFTW, Plots
import .EngeeComms
gr()
step = EngeeComms.step;

Создадим структуру, в которой содержатся все переменные, связанные с параметрами подключенных блоков.

mutable struct passband_modulator
    # Transmitter
    obj_random_integer
    obj_QPSK_modulator
    obj_raised_cosine_transmit
        # Upconverter
        obj_sine_upc
        obj_prod_upc
        obj_re_upc
    # Channel
    obj_sum
    obj_AWGN
        #interference
        obj_sine_inter
        obj_re_inter
        obj_const_inter
        obj_math_inter
        obj_gain_inter
    # Receiver
    #   downconverter
        obj_sine_wave_dc
        obj_conj_dc
        obj_prod_dc
    obj_raised_cosine_receive
    obj_QPSK_demodulator
    # Metrics
    obj_int_to_bit
    obj_BER
    obj_delay
    obj_EVM

    function passband_modulator()
        new(EngeeComms.random_integer(4, 37, 1e-6, 100, "Int"), EngeeComms.QPSK(pi/4), EngeeComms.rcostrans(0.2, 8, 8, 1.0),
        EngeeComms.sine_wave(1.0, 2500000.0, 0.0, "Discrete", "Complex", "Trigonometric fcn", 1e-6/8, 800, "Restart at time zero"), EngeeComms.product(2, "Element-wise"), EngeeComms.complex_to_real_imag("Real"),
        EngeeComms.Sum("+"), EngeeComms.AWGN(67, "mode", 8.0, 2, 1/(2*8), 1e-6, 1e-4), EngeeComms.sine_wave(1.0 ,8.833333333333334e+05, 0.0, "Discrete", "Complex", "Trigonometric fcn", 1e-6/8, 800, "Restart at time zero"), EngeeComms.complex_to_real_imag("Real"), 3, EngeeComms.math("pow"), EngeeComms.Gain(.25),
        EngeeComms.sine_wave(1.0 ,2500000.0, 0.0, "Discrete", "Complex", "Trigonometric fcn", 1e-6/8, 800, "Restart at time zero"), EngeeComms.math("conj"), EngeeComms.product(2, "Element-wise"), EngeeComms.rcosreciev(0.2, 8, 8, 2.0, 8, 0), EngeeComms.deQPSK(pi/4),
        EngeeComms.IntToBit(2, "Unsigned", "MSB first", "Boolean"), EngeeComms.error_rate(16, 0, "Entire frame", "Port", false, false), EngeeComms.delay(8,1), EngeeComms.EVM("Average reference signal power", "Input port", "Input length", 1))
    end
end

Создадим функцию для выполнения логики работы системы.

function step1(obj::passband_modulator)
    out_upconv1 =[];
    out_downcov =[];
    out_rec_filt =[];
    out_interfer =[];
    out_BER =zeros(3);
    EngeeComms.setup(obj.obj_random_integer);
    EngeeComms.setup(obj.obj_AWGN, [1]);
    EVM_out = 0;
    for i =1:201
        # Передатчик
        ri = step(obj.obj_random_integer);
        QPSK_tr = step(obj.obj_QPSK_modulator, ri);
        raised_cos_tr = step(obj.obj_raised_cosine_transmit, QPSK_tr)
        test_rcos = raised_cos_tr;
            # Повышающий преобразователь
            sine_wave_upc = step(obj.obj_sine_upc);
            prod_upc = step(obj.obj_prod_upc, sine_wave_upc,raised_cos_tr);
            out_upconv = step(obj.obj_re_upc, prod_upc);

        # Канал
            # Интерференция с нелинейными искажениями
            sine_wave_nonl = step(obj.obj_sine_inter);
            re_nonl = step(obj.obj_re_inter, sine_wave_nonl);
            inter_pow = step(obj.obj_math_inter, re_nonl, obj.obj_const_inter);
            inter_gain = step(obj.obj_gain_inter, inter_pow);

        AWGN_in = step(obj.obj_sum, out_upconv, inter_gain);
        Channel_out = step(obj.obj_AWGN, AWGN_in);

        # Приемник
            # Понижающий преобразователь
            sine_dc = step(obj.obj_sine_wave_dc);
            conj_dc = step(obj.obj_conj_dc, sine_dc);
            out_dc = step(obj.obj_prod_dc, conj_dc, Channel_out);
        raised_cos_reciev = step(obj.obj_raised_cosine_receive, out_dc[:,1]);
        out_reciever = step(obj.obj_QPSK_demodulator, raised_cos_reciev);


        # Расчет побитовой ошибки (BER)
        out_bits = step(obj.obj_int_to_bit, out_reciever);
        rand_int_bits = step(obj.obj_int_to_bit, ri);

        BER = step(obj.obj_BER, rand_int_bits, out_bits);
        # Расчет EVM_rms
        ref_sig = step(obj.obj_delay, QPSK_tr)
        EVM_out = step(obj.obj_EVM, ref_sig, raised_cos_reciev)

        # Выходы
        out_BER = BER;
        out_upconv1 = vcat(out_upconv1, out_upconv);
        out_downcov = vcat(out_downcov, out_dc);
        out_rec_filt = vcat(out_rec_filt, raised_cos_reciev);
        out_interfer = vcat(out_interfer, inter_gain);
    end
    return out_BER, out_upconv1, out_downcov, out_rec_filt, out_interfer, EVM_out;
end
step1 (generic function with 1 method)

Запуск системы и получение выходных данных.

passband = passband_modulator() # Вызов структуры
BER,Upconverter,Downconverter,receive_filter,Interference, EVM_out = step1(passband); # Вызов функции
println(BER[1]," BER;") # Вывод данных в командной строке
println(BER[2], " Bit errors;")
println(BER[3], " Bits;")
println()
println(EVM_out, " EVM_rms.") # Построение графика
0.001493131594664543 BER;
60.0 Bit errors;
40184.0 Bits;

35.140576755325306 EVM_rms.

Построим спектр сигнала на выходе передатчика и спектр вносимых искажений.

b = Float64.(Upconverter);
spec_b = fftshift(fft(b))[80400:160800];
plot([0:4e6/80400:4e6...],(20log10.(abs.((spec_b)./[4e6/80400,4e6/80400:4e6/80400:4e6...]))), label ="Сигнал на выходе передатчика")

e = Float64.(Interference);
spec_e = fftshift(fft(e))[80400:160800];
plot!([0:4e6/80400:4e6...],20log10.(abs.((spec_e))), label ="Искажения")

ylabel!("Мощность дБВт")
xlabel!("Частота Гц")
plot!(legend=:outerbottom)
ylims!(-240, -60)
xlims!(0.2e6,4e6)

interactive-scripts/images/communication_passband_mod/ac5a69653d26dd0fca392e1e82ce55d796648e62

Спектр сигнала после прохождения понижающего преобразователя.

d = ComplexF64.(Downconverter);
spec_d = fftshift(fft(d));
plot([-4e6:8e6/160800:4e6-1...],10log10.(abs.((spec_d/3e6))), label ="Сигнал на выходе понижающего преобразователя")
ylabel!("Мощность дБВт")
xlabel!("Частота МГц")
plot!(legend=:outerbottom)

interactive-scripts/images/communication_passband_mod/c7c0edabbd36f2bc3f530b25ebd3fd8aff2eae5d

Схема сигнального созвездия.

f = ComplexF64.(receive_filter);
plot(f[end-200:end], seriestype=:scatter)
plot!([0.75+0.75im, 0.75-0.75im, -0.75+0.75im, -0.75-0.75im], seriestype=:scatter, lc=:red, lw=:5, ls =:dot)
plot!(legend=:none)
xlabel!("Синхфазная амплитуда")
ylabel!("Квадратурная амплитуда")

interactive-scripts/images/communication_passband_mod/e7b5e11a491a5b2e2504350a2a093df7b937661b

Построение модели

Теперь рассмотрим второй способ построения систем связи, это моделирование процессов цифровой обработки сигналов при помощи моделей Engee.

Passbanmod

image3.png

Interference with Nonlinearity

image.png

Upconverter

image.png

Downconverter

image.png

Calculate RMS EVM

image.png

Compute BER

image.png

function run_model( name_model, path_to_folder )

    Path = path_to_folder * "/" * name_model * ".engee"

    if name_model in [m.name for m in engee.get_all_models()] # Проверка условия загрузки модели в ядро
        model = engee.open( name_model ) # Открыть модель
        model_output = engee.run( model, verbose=true ); # Запустить модель
    else
        model = engee.load( Path, force=true ) # Загрузить модель
        model_output = engee.run( model, verbose=true ); # Запустить модель
        engee.close( name_model, force=true ); # Закрыть модель
    end

    return model_output
end
# Запуск модели
run_model( "passbandmod", @__DIR__ )
Building...
Progress 0%
Progress 0%
Progress 5%
Progress 10%
Progress 15%
Progress 20%
Progress 25%
Progress 30%
Progress 35%
Progress 40%
Progress 45%
Progress 50%
Progress 55%
Progress 60%
Progress 65%
Progress 70%
Progress 75%
Progress 80%
Progress 85%
Progress 90%
Progress 95%
Progress 100%
# Подключение библиотек
using CSV, DataFrames
using Plots # Подключение библиотеки для построения графиков
gr() # Подключение бэкенда - метода отображения графики
Plots.GRBackend()
## EVM
EVM = Matrix(CSV.read("$(@__DIR__)/EVM.csv", DataFrame)); #загрузка данных
plot(EVM[:,1], EVM[:,2], xlabel="Время", ylabel="EVM", title="EVM") # Построение графика

interactive-scripts/images/communication_passband_mod/43d0368aec1014ea608dee607a8c07b5122ac1ab

## BER
BER = Matrix(CSV.read("$(@__DIR__)/BER.csv", DataFrame)); #загрузка данных
plot(BER[:,1], BER[:,2], xlabel="Время", ylabel="BER", title="BER") # Построение графика

interactive-scripts/images/communication_passband_mod/e73fd49530a059239ee8a4879b326d89ca83db2c

Вывод

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