主频带调制¶
本例展示了一种简单的主频带调制方法,通过将调制后的复信号乘以复正弦波来实现频率上变频。最好在复杂基频频段对系统进行建模。不过,在某些情况下,有必要在实际带宽内对系统进行建模。例如,当邻近频段信号经过非线性处理后,会对所需频段产生干扰。本示例也说明了这种干扰的影响,并以两种变体呈现: 1.脚本形式; 2.模型形式。
算法方案的形式如下:
使用脚本构建系统¶
构建系统的第一步:连接所有使用过的系统元素和库。
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]:
启动系统并获取输出数据。
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.") # Построение графика
绘制发射机输出端的信号频谱图和插入失真频谱图。
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 模型建立数字信号处理模型。
*密码模块
非线性干扰
上转换器
Downconverter
计算 EVM 有效值
*计算误码率
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__ )
In [ ]:
# Подключение библиотек
using CSV, DataFrames
using Plots # Подключение библиотеки для построения графиков
gr() # Подключение бэкенда - метода отображения графики
Out[0]:
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中使用脚本和模型进行数字信号处理。