Engee 文档
Notebook

OFDM 过采样信号模型

在本例中,我们将研究一个过采样 OFDM(正交频分复用,一种使用大量紧密间隔的正交子载波或复用的数字调制技术)信号模型。通过该模型,您可以看到多种调制的耦合。另一个例子是使用 RMS 单元来测量叠加了噪声的 OFDM 调制信号,其缩放值与 FFT(快速傅立叶变换)大小中的有效子载波数成正比,以确认信号功率近似等于 1。

该模型根据以下原则构建。 1.生成随机整数数据集和先导输入符号。 2.2. 16-QAM 对数据和先导符号进行调制。 3. OFDM 对 QAM 调制信号进行调制。一对 OFDM 调制器和解调器处理三个符号,每个符号的先导信号子载波索引和循环前缀长度各不相同。OFDM 信号包含数据和先导信号,由模型以四倍采样率生成。 4.4. 接下来,我们对每个帧进行振幅失真,从而显著改变信号功率。 5.5. 然后,OFDM 对数据和先导信号分别进行解调和输出。 6.16-QAM 对数据和先导符号进行解调。 7.然后找出输入和输出之间的差值。

下图显示了实现的模型。

image.png

让我们初始化模型参数。

In [ ]:
M = 16;              # Порядок модуляции
nfft = 64;           # Длина FFT
NumSymbols=3;        # Количество символов OFDM
osf=4;               # Фактор передискретизации
ngbc = [9;8];        # Число носителей защитного диапазона
insertdcnull = true;  # Наличие DC-нулевой поднесущей
addpilotport = true;  # Присутствие пилота
Noise_power = 10; # Мощность шума
In [ ]:
# Индексы пилотных поднесущих
pscindx = [[12;26;40;54] [14;28;38;52] [12;26;40;54]]; 
cplen = [16; 32; 16];  # CyclicPrefixLength
# Выборки на кадр для данных
spf_data = NumSymbols * (nfft-sum(ngbc)-size(pscindx,1)-insertdcnull)
# Выборки на кадр для пилота    
spf_pilot = NumSymbols * size(pscindx,1)
# Число активных поднесущих
nasc = nfft-sum(ngbc)+insertdcnull;

声明模型参数后,让我们初始化模型启动函数并启动模型本身。

In [ ]:
# Подключение вспомогательной функции запуска модели.
function run_model( name_model)
    
    Path = (@__DIR__) * "/" * 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
    sleep(5)
    return model_output
end

run_model("OFDM_Signal_and_QAM") # Запуск модели.
Building...
Progress 0%
Progress 0%
Progress 0%
Progress 3%
Progress 8%
Progress 13%
Progress 18%
Progress 23%
Progress 28%
Progress 33%
Progress 38%
Progress 43%
Progress 48%
Progress 54%
Progress 59%
Progress 64%
Progress 69%
Progress 74%
Progress 79%
Progress 84%
Progress 89%
Progress 94%
Progress 99%
Progress 100%
Progress 100%
Out[0]:
Dict{String, DataFrame} with 4 entries:
  "ErrorPilot" => 121×2 DataFrame…
  "RMSout"     => 10241×2 DataFrame…
  "ErrorData"  => 1261×2 DataFrame…
  "RMSinp"     => 10241×2 DataFrame

现在我们来分析记录的数据。

In [ ]:
ErrorData = collect(ErrorData);
ErrorPilot = collect(ErrorPilot);
RMSinp = collect(RMSinp);
RMSout = collect(RMSout);

ErrorData = ErrorData.value;
ErrorPilot = ErrorPilot.value;
RMSinp = RMSinp.value;
RMSout = RMSout.value;
In [ ]:
plot([real(RMSinp),real(RMSout)], title="RMS", label=["До наложения шума" "После наложения шума"])
Out[0]:

我们可以看到,每一帧的信号功率都有所不同。现在我们来看看输入和输出数据之间的差异。

In [ ]:
plot([ErrorData,ErrorPilot], title="Разница между входами и выходами", label=["Данные" "Пилоты"])
Out[0]:

从图中可以看出,误差为零,但为了确保万无一失,我们还是要找出总误差。

In [ ]:
println("Суммарная разница между входными и выходными данными: " * string(sum(ErrorData)))
println("Суммарная разница между входными и выходными пилотами: " * string(sum(ErrorPilot)))
Суммарная разница между входными и выходными данными: 0.0
Суммарная разница между входными и выходными пилотами: 0.0

结论

在本例中,我们分解并演示了在通信系统中使用几种调制方式的可能性。这种方法在这一领域的应用非常广泛。