Engee 文档
Notebook

以sigma-delta模数转换器模型为例的DSP任务

本示例实现了Sigma-Delta模数转换器(Sigma-Delta ADC)模型,该模型使用delta-sigma调制方法在测量模拟信号中实现了高精度和分辨率。 广泛应用于各种需要高测量精度的应用场合,如音频、测量传感器等。 (模型sigma_delta_adc。工程师):

sdadc.PNG

接下来,在这个例子中,分析了Sigma-Delta ADCSimulinkEngee中的工作,并比较了两个开发环境的工作结果。

首先,您需要连接库:

In [ ]:
Pkg.add(["Statistics", "CSV"])
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
In [ ]:
# 连接图书馆
using Plots
using CSV
using DataFrames
using Statistics
plotlyjs();

启动在Engee开发环境中实现的模型。

In [ ]:
modelName = "sigma_delta_adc"
SDC_model = modelName in [m.name for m in engee.get_all_models()] ? engee.open( modelName ) : engee.load( "$(@__DIR__)/$(modelName).engee");

results = engee.run( modelName )
Out[0]:
SimulationResult(
    "analog" => WorkspaceArray{Float64}("sigma_delta_adc/analog")
,
    "SD_ADC" => WorkspaceArray{Float64}("sigma_delta_adc/SD_ADC")
,
    "diff" => WorkspaceArray{Float64}("sigma_delta_adc/diff")

)

模型输出的可视化

In [ ]:
SD_ADC_res_t = results["SD_ADC"].time;
SD_ADC_res_d = results["SD_ADC"].value;
p_adc_da_sl = plot(SD_ADC_res_t, SD_ADC_res_d, legend = false) # 绘制图形
plot!(title = "Engee中的仿真结果", ylabel = "数字信号", xlabel="时间,c") # 轴的签名和图形的标题
Out[0]:

Simulink中的仿真结果:

In [ ]:
using MATLAB # 连接MATLAB内核
mat"cd /user/start/examples/dsp/sigma_delta_adc"
mat"""
    out = sim('sigma_delta_adc');
    sig = getElement(out.yout,1);
    $DA_times = sig.Values.Time;
    $DA_values = sig.Values.Data;
    """; # Запуск Simulink
In [ ]:
p_adc_da_sl = plot(DA_times, DA_values, legend = false) 
plot!(title = "Simulink中的仿真结果", ylabel = "数字信号", xlabel="时间,c")
Out[0]:

模型使用可变间距求解器。 有必要"同步"信号。 首先,让我们把图表放在彼此的顶部。:

In [ ]:
plot(SD_ADC_res_t ,SD_ADC_res_d, label = "Engee")
plot!(title = "模拟结果比较")
plot!(DA_times, DA_values, label = "Simulink")
# plot!(label = ["Engee" "Simulink"])
plot!(legend = :outertopright,ylabel = "数字信号", xlabel="时间,c")
Out[0]:

我们找到两个向量与模拟时间的交集:

In [ ]:
# 1. 检查数组长度是否一致
if length(SD_ADC_res_t) != length(SD_ADC_res_d)
    error("SD_ADC_res_t和SD_ADC_res_d的大小不匹配!")
end

# 2. 将DA_times/DA_values修剪为SD_ADC_res_t的长度(如有必要)
new_length = min(length(DA_times), length(SD_ADC_res_t))
DA_times = DA_times[1:new_length]
DA_values = DA_values[1:new_length];

# 3. 我们找到时间戳的交集
common_times = intersect(DA_times, SD_ADC_res_t)

if isempty(common_times)
    error("DA_times和SD_ADC_res_t之间没有匹配的时间戳!")
end

然后,您需要获取公共点中的值。

In [ ]:
# 4. 我们找到匹配元素的索引(使用整数索引)
SD_ADC_d = collect(SD_ADC_res_d).value
SD_ADC_t = collect(SD_ADC_res_t).time

da_idx = findall(t -> t in common_times, DA_times)
sd_idx = findall(t -> t in common_times, SD_ADC_t)

# 5. 确保索引在时间上彼此对应。
if !all(DA_times[da_idx] .== SD_ADC_t[sd_idx])
    error("索引后时间戳不匹配!")
end

# 6. 提取数据
sd_comp_t = DA_times[da_idx]
sd_comp_sl = DA_values[da_idx]
sd_comp_en = SD_ADC_d[sd_idx]

# 7. 检查结果
@assert length(sd_comp_t) == length(sd_comp_sl) == length(sd_comp_en) "输出数组的大小不匹配!"
println("成功处理$(length(sd_comp_t))匹配点")
Успешно обработано 45 совпадающих точек

现在我们可以正确比较Simulink和Engee的结果。:

In [ ]:
adc_abs_tol = sd_comp_sl - sd_comp_en;
mean_adc_tol = abs(mean(adc_abs_tol));
adc_rel_tol = (sd_comp_sl - sd_comp_en)./sd_comp_sl;
mean_adc_tol_rel = abs(mean(filter(!isnan,adc_rel_tol)));
println("计算的平均绝对误差:", mean_adc_tol);
println("计算的平均相对误差, %:", abs(mean_adc_tol_rel*100)); 
Средняя абсолютная погрешность вычислений:7.2617452174918e-18
Средняя относительная погрешность вычислений, %:9.655960186035709e-15
In [ ]:
engee.close( modelName, force=true);

结论

总之,本示例实现了sigma-delta模数转换器模型。 基于这个例子,我们可以得出几个结论:

  1. Engee在精度上并不逊色于Simulink
  2. Engee允许您使用MOS,并且由于大量的块库,我们有机会实现大量的块功能。
  3. 而且,如果Engee的功能不足,我们可以在Engee内部使用MATLAB的功能