Engee 文档
Notebook

主频带调制

本例展示了一种简单的主频带调制方法,通过将调制后的复信号乘以复正弦波来实现频率上变频。最好在复杂基频频段对系统进行建模。不过,在某些情况下,有必要在实际带宽内对系统进行建模。例如,当邻近频段信号经过非线性处理后,会对所需频段产生干扰。本示例也说明了这种干扰的影响,并以两种变体呈现: 1.脚本形式; 2.模型形式。

算法方案的形式如下:

passband.png

使用脚本构建系统

构建系统的第一步:连接所有使用过的系统元素和库。

In [ ]:
Pkg.add(["CSV"])
In [ ]:
using FFTW, Plots
import .EngeeComms
gr()
step = EngeeComms.step;

创建一个结构,其中包含与所连接模块参数相关的所有变量。

In [ ]:
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

创建一个函数来执行系统运行逻辑。

In [ ]:
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
Out[0]:
step1 (generic function with 1 method)

启动系统并获取输出数据。

In [ ]:
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.

绘制发射机输出端的信号频谱图和插入失真频谱图。

In [ ]:
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)
Out[0]:

通过降压转换器后的信号频谱。

In [ ]:
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)
Out[0]:

信号星座图。

In [ ]:
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!("Квадратурная амплитуда")
Out[0]:

模型构建

现在,让我们考虑建立通信系统的第二种方法,即使用 Engee 模型建立数字信号处理模型。

*密码模块

image3.png

非线性干扰

image.png

上转换器

image.png

Downconverter

image.png

计算 EVM 有效值

image.png

*计算误码率

image.png

In [ ]:
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 5%
Progress 10%
Progress 15%
Progress 21%
Progress 26%
Progress 31%
Progress 37%
Progress 42%
Progress 47%
Progress 53%
Progress 59%
Progress 64%
Progress 69%
Progress 74%
Progress 79%
Progress 85%
Progress 91%
Progress 96%
Progress 100%
Progress 100%
In [ ]:
# Подключение библиотек
using CSV, DataFrames
using Plots # Подключение библиотеки для построения графиков
gr() # Подключение бэкенда - метода отображения графики
Out[0]:
Plots.GRBackend()
In [ ]:
## EVM
EVM = Matrix(CSV.read("$(@__DIR__)/EVM.csv", DataFrame)); #загрузка данных
plot(EVM[:,1], EVM[:,2], xlabel="Время", ylabel="EVM", title="EVM") # Построение графика
Out[0]:
In [ ]:
## BER
BER = Matrix(CSV.read("$(@__DIR__)/BER.csv", DataFrame)); #загрузка данных
plot(BER[:,1], BER[:,2], xlabel="Время", ylabel="BER", title="BER") # Построение графика
Out[0]:

结论

我们实现了一个脚本和模型,通过将调制后的复信号与复正弦波相乘来进行频率上变频,从而以简单的方法实现基本的带宽调制。此外,我们还展示了如何在Engee中使用脚本和模型进行数字信号处理。