模糊调节器的管道压力控制仿真
本例演示了使用模糊调节器的管道压力控制仿真。
模型文件包含两个带控制系统的液压回路。 上层电路由PID控制器控制,其描述可以在社区中找到。:在трубопроводе压力控制的模拟和管路压力控制。 两个电路中的设定点信号由块表示
Chart
下层电路具有物理块的类似参数。
模型图:
模糊控制器使用块描述 Engee Function. 它允许您使用Julia编程语言中的代码。 了解更多关于合作的信息 Engee Function 您可以在相应的文章документации.
要创建模糊控制器,让我们使用名为FuzzyLogic的Julia编程语言库。 要在Engee中安装它,您需要执行以下代码。:
Pkg.add(["FuzzyLogic"])
Pkg.add("FuzzyLogic")
我们正在启动已安装的FuzzyLogic库和Plots图表库。
using FuzzyLogic
using Plots
在下面的代码单元格中,正在使用宏构建Mamdani模糊推理系统 @mamfis. 这种系统的构建包括成员函数的定义。 函数被声明 tipper,这需要一个参数 delta_p. 这个变量将代表来自加法器的输入数据,加法器计算设定压力和测量压力之间的差。
用于压力差范围和阀门横截面积输出的附件功能包括:
*高斯隶属函数 GaussianMF(x, y) -其中x是确定分布中心的平均值,y是标准偏差
*三角隶属函数 TriangularMF(x, y, z) 其中x是三角形的左角,z是右边,y是三角形的峰值
*梯形附件功能 TrapezoidalMF(x, y, z, k),其中x是梯形的左下角,k是右下角,y和z分别是左上角和右上角
在变量中 domain 定义成员函数的范围。
接下来,定义了涉及输入和输出变量的模糊逻辑规则。 例如:
如果 delta_p 很高,那么 control_signal 它将完全开放。
如果 delta_p 高,那么 control_signal 它将部分开放。
等其余条件。
fis = @mamfis function tipper(delta_p)::control_signal
delta_p := begin
domain = -50000.0:50000.0
very_high = GaussianMF(17000.0, 3000.0) # Очень высокое давление
high = GaussianMF(15000.0, 4120.0) # Высокое давление
moderate = GaussianMF(-6000.0, 3000.0) # Нормальное давление
low = GaussianMF(-15000.0, 3000.0) # Низкое давление
very_low = GaussianMF(-30000.0, 3000.0) # Очень низкое давление
end
control_signal := begin
domain = 0.0:0.005
fully_closed = TriangularMF(0.00000000001, 0.00000001, 0.000001) # Полностью закрытая заслонка
partially_closed = TriangularMF(0.0000009, 0.000005, 0.00001) # Частично закрытая заслонка
neutral = TriangularMF(0.00001, 0.00002, 0.0003) # Нейтральное положение (половина открыта)
partially_open = TrapezoidalMF(0.0003, 0.0009, 0.003, 0.0044) # Частично открытая заслонка
fully_open = TriangularMF(0.004, 0.0047, 0.005) # Полностью открытая заслонка
end
# Работающие правила
delta_p == very_high --> control_signal == fully_open
delta_p == high --> control_signal == partially_open
delta_p == moderate --> control_signal == neutral
delta_p == low --> control_signal == partially_closed
delta_p == very_low --> control_signal == fully_closed
end
绘制输入数据的隶属函数:
plot(fis, :delta_p)
绘制数据输出的隶属函数:
plot(fis, :control_signal)
为了将这种模糊推理系统实现为控制系统,有必要从中生成一个不依赖于库的函数,并且仅由Julia语言的基本构造定义。 为此,您可以使用该函数 compilefis(fis),其中fis自变量是先前定义并写入变量的模糊推理系统。 使用此函数生成代码的结果将写入asd变量。:
asd = compilefis(fis)
记录在asd变量中的结果被重写成代码单元。:
function tipper(delta_p)
very_high = exp(-((delta_p - 17000.0) ^ 2) / 1.8e7)
high = exp(-((delta_p - 15000.0) ^ 2) / 3.39488e7)
moderate = exp(-((delta_p - -6000.0) ^ 2) / 1.8e7)
low = exp(-((delta_p - -15000.0) ^ 2) / 1.8e7)
very_low = exp(-((delta_p - -30000.0) ^ 2) / 1.8e7)
ant1 = very_high
ant2 = high
ant3 = moderate
ant4 = low
ant5 = very_low
control_signal_agg = collect(LinRange{Float64}(0.0, 0.005, 101))
@inbounds for (i, x) = enumerate(control_signal_agg)
fully_closed = max(min((x - 1.0e-11) / 9.99e-9, (1.0e-6 - x) / 9.9e-7), 0)
partially_closed = max(min((x - 9.0e-7) / 4.1000000000000006e-6, (1.0e-5 - x) / 5.0e-6), 0)
neutral = max(min((x - 1.0e-5) / 1.0e-5, (0.0003 - x) / 0.00028), 0)
partially_open = max(min((x - 0.0003) / 0.0006000000000000001, 1, (0.0044 - x) / 0.0014000000000000002), 0)
fully_open = max(min((x - 0.004) / 0.0007000000000000001, (0.005 - x) / 0.0002999999999999999), 0)
control_signal_agg[i] = max(max(max(max(min(ant1, fully_open), min(ant2, partially_open)), min(ant3, neutral)), min(ant4, partially_closed)), min(ant5, fully_closed))
end
control_signal = ((2 * sum((mfi * xi for (mfi, xi) = zip(control_signal_agg, LinRange{Float64}(0.0, 0.005, 101)))) - first(control_signal_agg) * 0.0) - last(control_signal_agg) * 0.005) / ((2 * sum(control_signal_agg) - first(control_signal_agg)) - last(control_signal_agg))
return control_signal
end
通过定义函数 tipper() 描述模糊输出系统,我们可以绘制输出数据对输入数据的依赖性。 为此,我们确定从-50000到50,000Pa的压力值向量,如之前在变量中所写的那样 domain 我们通过函数传递它:
x = collect(range(-50000.0,50000.0,10001));
绘制结果函数的响应曲线:
plot(x, tipper.(x), linewidth=3)
有阀门打开面积对设定点和来自传感器的信号之间的压力差的依赖性的曲线图。
代码生成得到的函数可以写入文件。 为此,Expr格式的asd变量将转换为字符串格式以供进一步写入。:
text_function = string(asd)
将字符串格式的函数写入文件:
f = open("/user/start/examples/controls/liquid_pressure_regulator_fuzzy/liquid_pressure_regulator_fuzzy.jl","w") # создание файла
write(f, text_function) # запись в файл
close(f) # закрытие файла
生成的文件,在**。jl**格式,具有功能 tipper(),我们把它放在街区 Engee Function 我们使用函数来执行 include(). 要做到这一点,转到块参数,单击"查找掩码下"按钮,选择"主"选项卡并单击"编辑源代码",在打开的窗口中输入:
struct Block<:AbstractCausalComponent;end
函数(c::块)(t::Real,delta_p)
include("liquid_pressure_regulator_fuzzy.jl")
返回控制_signal
结束
接下来,启动模型并在图形上显示数据。
定义加载和运行模型的函数:
function start_model_engee()
try
engee.close("liquid_pressure_regulator_fuzzy", force=true) # закрытие модели
catch err # в случае, если нет модели, которую нужно закрыть и engee.close() не выполняется, то будет выполнена её загрузка после catch
m = engee.load("$(@__DIR__)/liquid_pressure_regulator_fuzzy.engee") # загрузка модели
end;
try
engee.run(m) # запуск модели
catch err # в случае, если модель не загружена и engee.run() не выполняется, то будут выполнены две нижние строки после catch
m = engee.load("$(@__DIR__)/liquid_pressure_regulator_fuzzy.engee") # загрузка модели
engee.run(m) # запуск модели
end
end
运行模拟
try
start_model_engee() # запуск симуляции с помощью специальной функции, реализованной выше
catch err
end;
从simout变量中提取数据并将其写入变量:
sleep(5)
result = simout;
res = collect(result)
将两个电路的设定点传感器和压力传感器的信号记录到变量中:
PID_регулятор = collect(res[1])
Нечёткий_регулятор = collect(res[3])
Сигнал_задатчика = collect(res[4]);
模拟结果的可视化
plot(PID_регулятор[:,1], PID_регулятор[:,2], linewidth=3, label="PID-регулятор")
plot!(Нечёткий_регулятор[:,1], Нечёткий_регулятор[:,2], linewidth=3, label="Нечёткий регулятор")
plot!(Сигнал_задатчика[:,1], Сигнал_задатчика[:,2], linewidth=3, label="Сигнал задатчика")
分析该图,可以看到,与PID控制器不同,模糊控制器具有显着更少的超调,以及瞬态过程的持续时间更短。 但模糊控制器也有一个缺点,它的信号往往可以从设定点信号偏移一定量,但这可以通过更精确的隶属函数和判决规则的调整来修正。
结论:
在这个例子中,我们演示了两个物理对象的仿真与自动控制系统的不同变体,特别是PID控制器和模糊控制器。 建立了模糊推理系统,然后将其转化为适合嵌入Engee功能块中的函数。 结果是模糊控制器,其特性不逊色于PID控制器。