以 sigma-delta 模数转换器为例的 DSP 任务
该示例实现了一个 Sigma-Delta 模数转换器(Sigma-Delta ADC)模型,它是一种使用Δ-Σ调制方法实现高精度和高分辨率模拟信号测量的类型。它广泛应用于各种要求高测量精度的应用中,如:音频、测量传感器等。(型号 sigma_delta_adc.engee):
下面的案例研究分析了Simulink和Engee中Sigma-Delta ADC的性能,并比较了两种开发环境的结果。
首先需要连接库:
In [ ]:
Pkg.add(["Statistics", "CSV"])
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]:
模型输出的可视化
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)) совпадающих точек")
现在我们可以正确比较 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));
In [ ]:
engee.close( modelName, force=true);
结论
总之,本示例实现了一个 sigma-delta 模数转换器模型。从这个例子中可以得出几个结论:
-
- Engee与Simulink一样精确。
-
- Engee允许使用MOS,由于有一个庞大的模块库,我们有机会实现大量的模块功能。
3.如果Engee的功能不够,我们还可以在Engee中使用MATLAB的功能。
- Engee允许使用MOS,由于有一个庞大的模块库,我们有机会实现大量的模块功能。