Модуляция основной полосы частот¶
Этот пример показывает простой способ выполнения модуляции основной полосы частот путем умножения модулированного комплексного сигнала на сложную синусоидальную волну для выполнения преобразования частоты с повышением. Предпочтительнее моделировать систему в сложной основной полосе частот. Однако существуют некоторые обстоятельства, при которых необходимо моделировать систему в реальной полосе пропускания. Примером этого является случай, когда сигнал соседней полосы частот обрабатывается с нелинейностью и вызывает помехи в желаемой полосе частот. Этот пример также иллюстрирует эффект такого вмешательства и представлен в двух вариантах:
- В виде скрипта;
- В виде модели.
Схема алгоритма имеет следующий вид:
Построение системы при помощи скрипта¶
Первый шаг построения системы: подключаем все используемые системные элементы и библиотеки.
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
Запуск системы и получение выходных данных.
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.") # Построение графика
Построим спектр сигнала на выходе передатчика и спектр вносимых искажений.
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)
Спектр сигнала после прохождения понижающего преобразователя.
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)
Схема сигнального созвездия.
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!("Квадратурная амплитуда")
Построение модели¶
Теперь рассмотрим второй способ построения систем связи, это моделирование процессов цифровой обработки сигналов при помощи моделей Engee.
Passbanmod
Interference with Nonlinearity
Upconverter
Downconverter
Calculate RMS EVM
Compute BER
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__ )
# Подключение библиотек
using CSV, DataFrames
using Plots # Подключение библиотеки для построения графиков
gr() # Подключение бэкенда - метода отображения графики
## EVM
EVM = Matrix(CSV.read("$(@__DIR__)/EVM.csv", DataFrame)); #загрузка данных
plot(EVM[:,1], EVM[:,2], xlabel="Время", ylabel="EVM", title="EVM") # Построение графика
## BER
BER = Matrix(CSV.read("$(@__DIR__)/BER.csv", DataFrame)); #загрузка данных
plot(BER[:,1], BER[:,2], xlabel="Время", ylabel="BER", title="BER") # Построение графика
Вывод¶
Мы реализовали скрипт и модель простого способа выполнения модуляции основной полосы частот путем умножения модулированного комплексного сигнала на сложную синусоидальную волну для выполнения преобразования частоты с повышением. А также показали как использовать скрипты и модели для цифровой обработки сигналов в Engee.