AnyMath 文档
Notebook

用于频率范围选择的RC带通滤波器

在本例中,计算并测试了一个无源带通RC滤波器,其范围约为0.75kHz16kHz。 该脚本显示了额定值的计算,预期幅度-频率响应的构建,现成Engee模型的推出以及信号模型与物理电路的比较。

导言

此示例描述解决问题的进度。

2W1。2 - 带宽

从书中

Thomas K.Hayes,Paul Horowitz
电路工程的艺术:理论与实践

通过计算机模拟在Engee。

该任务需要获得一个滤波器,该滤波器衰减太低的频率,跳过工作范围,并再次削弱高频分量。

实际上,这样的滤波器可以由两个简单的RC链路组装而成。 低频边界由高频链路设置,高频边界由低频链路设置。 重要的是要选择电阻,以便下一个级联不会使前一个级联过载。

理论背景

一阶的低频链路使用传递函数

对于一阶高频链路:

如果我们认为级联在负载方面是弱耦合的,带通滤波器描述了产品:

每个RC链路的边界频率估计为

在物理模型中,上频链路的输出电阻具有1mOhm的电阻。 因此,考虑下界的等效电阻是有用的。:

参数的计算

在此单元中,设置级联电阻、目标频率和标准电容。 然后将计算的边界频率与所需范围进行比较。

In [ ]:
R_LP = 10_000.0
C_LP = 1e-9
R_HP = 100_000.0
C_HP = 2e-9
R_load = 1_000_000.0

f_low_target = 750.0
f_high_target = 16_000.0

parallel(R1, R2) = 1 / (1 / R1 + 1 / R2)
R_HP_loaded = parallel(R_HP, R_load)

f_lp = 1 / (2pi * R_LP * C_LP)
f_hp_ideal = 1 / (2pi * R_HP * C_HP)
f_hp_loaded = 1 / (2pi * R_HP_loaded * C_HP)

C_LP_exact = 1 / (2pi * f_high_target * R_LP)
C_HP_exact = 1 / (2pi * f_low_target * R_HP)

calculation_summary = (;
    R_LP,
    C_LP,
    f_lp,
    R_HP,
    C_HP,
    f_hp_ideal,
    R_HP_loaded,
    f_hp_loaded,
    C_LP_exact,
    C_HP_exact,
)

calculation_summary
Out[0]:
(R_LP = 10000.0, C_LP = 1.0e-9, f_lp = 15915.494309189533, R_HP = 100000.0, C_HP = 2.0e-9, f_hp_ideal = 795.7747154594767, R_HP_loaded = 90909.0909090909, f_hp_loaded = 875.3521870054245, C_LP_exact = 9.947183943243459e-10, C_HP_exact = 2.122065907891938e-9)

低频链路的标称值1nF给出了约15.9kHz的上限。 高频链路的标称值2nF给出了无负载时约796Hz和负载时约875Hz的下限1mOhm。 对于教育RC滤波器,这接近所需的频带。

模型描述

两个Engee模型已经准备好进行测试。

  • RCBandPass_2W_1_2_signal.engee -带块的信号模型 Transfer Fcn. 它将理想的级联传递函数和近似值与1mOhm的负载进行比较。
  • RCBandPass_2W_1_2_phys.engee -物理非因果模型。 在其中,电压源馈送RC电路:首先有一个低频链路10kOhm+1nF,然后是一个高频链路2nF+100kohm,并且一个负载1mOhm连接到输出端。

三个正弦曲线的总和应用于输入:低频200Hz,频段内的频率3kHz和高频30kHz。 这样的信号有助于查看滤波器抑制哪些分量以及跳过哪些分量。

image.png
image.png

环境准备

在此单元格中,指定成品模型的路径和结果文件的文件夹。 如果从其他目录运行示例,请更改dir变量。

In [ ]:
using Plots

dir = @__DIR__
output_dir = dir
model_paths = Dict(
    :signal => joinpath(dir, "RCBandPass_2W_1_2_signal.engee"),
    :physical => joinpath(dir, "RCBandPass_2W_1_2_phys.engee"),
)
string("prepared; dir=", dir)
Out[0]:
"准备好;dir=/user/maxim-sidorov/ivaroprl"

环境已准备就绪:模型位于脚本旁边,新图形和表格将保存到同一文件夹中。

分析验证

在运行模型之前,建立计算的幅度-频率响应。 它显示了预期的带宽和负载对下界的影响。

In [ ]:
freqs = exp10.(range(log10(10.0), log10(100_000.0), length = 800))

gain_bp(f, R_hp) = begin
    tau_lp = R_LP * C_LP
    tau_hp = R_hp * C_HP
    omega = 2pi * f
    (omega * tau_hp) / sqrt((1 + (omega * tau_hp)^2) * (1 + (omega * tau_lp)^2))
end

p_response = plot(
    freqs,
    20 .* log10.(gain_bp.(freqs, R_HP));
    xscale = :log10,
    label = "空载",
    xlabel = "频率,赫兹",
    ylabel = "振幅,dB",
    title = "RC带通滤波器的估计频率响应",
)
plot!(p_response, freqs, 20 .* log10.(gain_bp.(freqs, R_HP_loaded)); label = "Rh=1mOhm")
vline!(p_response, [750.0, 16_000.0]; label = "任务边界", linestyle = :dash)
hline!(p_response, [-3.0]; label = "-3分贝", linestyle = :dot)

response_path = joinpath(output_dir, "rc_bandpass_response.png")
savefig(p_response, response_path)
p_response
Out[0]:

该曲线图示出了下边界之后的特征的上升和上边界之后的下降。 负载1mOhm略微向上偏移下限,因为它同时降低了高频级联的输出臂的电阻。

模型的仿真

现在下载信号模型并运行仿真。 该代码使用Engee的软件管理: engee.load, engee.open, engee.runengee.close.

In [ ]:
missing_models = [path for path in values(model_paths) if !isfile(path)]

if isempty(missing_models)
    signal_payload = Core.eval(Main, quote
        model = engee.load($(model_paths[:signal]); force = true)
        engee.open(model)
        results = engee.run(model)
        engee.close(model; force = true)
        (; results, result_text = repr(results))
    end)

    signal_results = signal_payload.results
    string("signal model simulated; results=", signal_payload.result_text)
else
    string("missing_models=", join(missing_models, ";"))
end
Out[0]:
"signal model simulated; results=SimulationResult(\n    run_id => 5,\n    \"bp_load_1M.1\" => WorkspaceArray{Float64}(\"RCBandPass_2W_1_2_signal/bp_load_1M.1\")\n,\n    \"input_sum.1\" => WorkspaceArray{Float64}(\"RCBandPass_2W_1_2_signal/input_sum.1\")\n,\n    \"bp_ideal.1\" => WorkspaceArray{Float64}(\"RCBandPass_2W_1_2_signal/bp_ideal.1\")\n\n)"

信号模型返回输入信号,理想带通滤波器的输出,以及负载为1mOhm的近似值的输出。

检查物理模型

运行物理模型。 它测试与电压源,电阻器,电容器,接地,电压传感器和块的电路相同的想法 Solver Configuration.

In [ ]:
physical_payload = Core.eval(Main, quote
    model = engee.load($(model_paths[:physical]); force = true)
    engee.open(model)
    results = engee.run(model)
    engee.close(model; force = true)
    (; results, result_text = repr(results))
end)

physical_results = physical_payload.results
string("physical model simulated; results=", physical_payload.result_text)
Out[0]:
"physical model simulated; results=SimulationResult(\n    run_id => 7,\n    \"input_sum.1\" => WorkspaceArray{Float64}(\"RCBandPass_2W_1_2_phys/input_sum.1\")\n,\n    \"vout_sensor.V\" => WorkspaceArray{Float64}(\"RCBandPass_2W_1_2_phys/vout_sensor.V\")\n\n)"

物理模型成功完成:输出电压由传感器记录。

仿真结果分析

建信号模型的时间图。 它们显示了如何在信号的三个谐波之和中,主要在带宽中保留一个分量。

In [ ]:
function series_from_result(results, key)
    df = results[key]
    return df.time, df.value
end

time, input_signal = series_from_result(signal_results, "input_sum.1")
_, y_ideal = series_from_result(signal_results, "bp_ideal.1")
_, y_load = series_from_result(signal_results, "bp_load_1M.1")

p_time = plot(
    time .* 1000,
    input_signal;
    label = "入口处",
    xlabel = "时间,ms",
    ylabel = "电压,相对单位",
    title = "过滤三个音调的总和",
)
plot!(p_time, time .* 1000, y_ideal; label = "完美的级联模型")
plot!(p_time, time .* 1000, y_load; label = "负载为1mOhm")

time_plot_path = joinpath(output_dir, "rc_bandpass_time_signals.png")
savefig(p_time, time_plot_path)
p_time
Out[0]:

输出受慢分量200Hz和高频分量30kHz的影响较小。 3kHz范围内的信号比其他信号传递得更好,因此形状变得更接近中音谐波。

与物理电路的比较

建物理模型的输入和输出。 需要此图以确保物理电路的行为与计算的带通滤波器类似。

In [ ]:
time_phys, input_phys = series_from_result(physical_results, "input_sum.1")
_, vout_phys = series_from_result(physical_results, "vout_sensor.V")

p_phys = plot(
    time_phys .* 1000,
    input_phys;
    label = "物理模型输入",
    xlabel = "时间,ms",
    ylabel = "电压,V",
    title = "检查物理RC电路",
)
plot!(p_phys, time_phys .* 1000, vout_phys; label = "物理模型的输出")

physical_plot_path = joinpath(output_dir, "rc_bandpass_physical_time.png")
savefig(p_phys, physical_plot_path)
p_phys
Out[0]:

物理电路还抑制低和高分量。 与理想传递函数略有不同:实际级联通过阻抗相互作用,输出附加负载电阻为1mOhm

总表

将计算的指标放在一个表格中。 它记录测试频率下的频带边界和传输系数。

In [ ]:
case_rows = [
    (case = "ideal", R_hp = R_HP),
    (case = "load_1M", R_hp = R_HP_loaded),
]

summary_rows = [
    (;
        case = row.case,
        f_hp_Hz = 1 / (2pi * row.R_hp * C_HP),
        f_lp_Hz = f_lp,
        gain_200Hz = gain_bp(200.0, row.R_hp),
        gain_750Hz = gain_bp(750.0, row.R_hp),
        gain_3kHz = gain_bp(3_000.0, row.R_hp),
        gain_16kHz = gain_bp(16_000.0, row.R_hp),
        gain_30kHz = gain_bp(30_000.0, row.R_hp),
    )
    for row in case_rows
]

summary_csv = joinpath(output_dir, "rc_bandpass_summary.csv")
open(summary_csv, "w") do io
    println(io, "case,f_hp_Hz,f_lp_Hz,gain_200Hz,gain_750Hz,gain_3kHz,gain_16kHz,gain_30kHz")
    for row in summary_rows
        println(io, join((row.case, row.f_hp_Hz, row.f_lp_Hz, row.gain_200Hz, row.gain_750Hz, row.gain_3kHz, row.gain_16kHz, row.gain_30kHz), ","))
    end
end

summary_rows
Out[0]:
2-element Vector{@NamedTuple{case::String, f_hp_Hz::Float64, f_lp_Hz::Float64, gain_200Hz::Float64, gain_750Hz::Float64, gain_3kHz::Float64, gain_16kHz::Float64, gain_30kHz::Float64}}:
 (case = "ideal", f_hp_Hz = 795.7747154594767, f_lp_Hz = 15915.494309189533, gain_200Hz = 0.2437278406404212, gain_750Hz = 0.6851064392173065, gain_3kHz = 0.9498460237713993, gain_16kHz = 0.704361397337135, gain_30kHz = 0.4684850032871685)
 (case = "load_1M", f_hp_Hz = 875.3521870054245, f_lp_Hz = 15915.494309189533, gain_200Hz = 0.22272201468675978, gain_750Hz = 0.6499191682006742, gain_3kHz = 0.9433569704186011, gain_16kHz = 0.7041789727228396, gain_30kHz = 0.46845041976732643)

该表确认了工程目标:约3kHz的传输系数是所选测试频率中最高的,频率200Hz30kHz明显减弱。

结论

我们计算并测试了RC带通滤波器的范围约为0.75kHz16kHz。 额定值10kOhm+1nF2nF+100kohm给出了接近的带边界,负载1mOhm适度地移动了下边界。 Engee信号和物理模型一致地显示在中端信号通过期间低和高分量的抑制。

文献列表