Engee 文档
Notebook

OFDM过采样信号模型

在这个例子中,我们将考虑OFDM过采样信号模型(正交频分复用,一种使用大量紧密间隔的正交子载波的数字调制技术,或多路复用)。 该模型允许您查看多个调制的组合。 本例还使用测量叠加有噪声的OFDM调制信号的RMS单元,按与相对于FFT(快速傅立叶变换)大小的活动副载波数成比例的值缩放,以确认信号功率近似为一。

该模型基于以下原理。

  1. 生成随机整数数据集和导频输入字符。
  2. 16-QAM调制数据和导频符号。
  3. OFDM调制qam调制信号。 一对OFDM调制器和解调器处理导频信号的子载波索引和每个符号的循环前缀长度不同的三个符号。 OFDM信号包含模型以四倍采样率的频率产生的数据和导频。
  4. 接下来,我们将振幅失真应用于每个帧,这显着改变了信号强度。
  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

结论

在这个例子中,我们分析并演示了在通信系统中使用几种类型调制的可能性。 这种方法在这一活动领域非常受欢迎。