Engee 文档
Notebook

输送机管理系统

此示例继续开发管道建模项目。 使用Engee函数和图表块,我们模拟了各种重量的负载在皮带和基于可编程逻辑控制器(PLC)的输送机控制系统上的运动。 最后,我们在KPM节奏上用控制算法实时测试物理模型。

导言

在[前面的例子](https://engee.com/community/ru/catalogs/projects/model-konveiera 在该项目中,我们计算并模拟了不同皮带负载条件下的电气和机械输送系统。 现在是时候转移到自动化输送机。 在项目开发的这个阶段,我们将扩展初始模型。:

*增加发动机制动系统,

*我们将开发一个块,用于计算皮带上负载的位置和总负载,

*添加子系统:

*确定货物到达皮带边缘,

*在皮带上放置新货物,

*我们将开发一个输送机管理系统。

示例模型

当前示例的模型最终看起来如下图所示。:

conveyor_control-02.09.25 11_31_14.png

让我们详细考虑下面的模型元素。

物理区块链的变化

动态制动电路已被添加到物理块的系统-通过信号 on_off 交流电源被关闭,并且在仿真的下一步中,从源向电机的两相施加恒定电压。 Uдт.

子系统"输送机上的负载"

子系统"在输送机上加载"的主要元素是[Engee功能]块(https://engee.com/helpcenter/stable/ru/base-lib-user-defined-function/engee-function.html ),其中Julia代码描述了模拟过程中磁带上负载的行为。 本机接收信号:

*"放置新货物"(可变 in1)-一个模拟步骤的持续时间,以及新负载的张力量,

*"磁带移动"(可变 in2)是自模拟开始以来传送带行进的距离,

*"移除进货"(变量 in3)是一个逻辑信号,作为命令从磁带上货物的描述模型中取出被输送到磁带边缘的货物。

在块的输出端,我们收到以下信号:

*"位置"是一个静态大小的向量,它包含与皮带运动相关的负载的当前位置的所有值。 在子系统从该向量的输出处,分配与位置值最大的负载相对应的第一个元素,即从带的开始比其他元素站得更远。

*"loads"是一个静态大小的向量,包含与"位置"向量对应的每个负载的所有负载值。

*"总负荷"-皮带上所有负荷的总负荷量。 子系统的输出用减号传输,形成正确的载荷矢量。

image.png

下面是来自选项卡的代码 Step method Code 带有注释的Engee功能块解释子系统的工作原理.

``'茱莉亚
如果有的话(w->w!=0.0,c.wght)#如果磁带上至少有一个负载
idx=findfirst(w->w==0.0,c.wght)#我们在向量中找到它的索引
c.pos[1:(idx-1)]=c.pos[1:(idx-1)]。+(in2-c.mov[1])#通过皮带运动的增量增加每个负载的运动
结束

c.mov[1]=in2#保存当前磁带移动

如果in3==true#如果你需要删除第一个负载
    对于i in1:length(c.wght)-1#将负载向量中的所有负载移动到idx-1
        c.wght[i]=c.wght[i+1]
    结束
    c.wght[结束]=0.0

for i in1:length(c.pos)-1#将位置向量中的所有权重移动到idx-1
c.pos[i]=c.pos[i+1]
结束
c.pos[结束]=0.0
结束

if(in1>0.0)&&(0.0in c.wght)#如果有新货到达
    idx=findfirst(w->w==0.0,c.wght) 
    c.wght[idx]=in1#我们把他的负荷放在空位上
    c.pos[idx]=0.0#设置位置为"0.0"

结束

return c.pos,c.wght,sum(c.wght)#输出:位置,负载,总负载的向量

变量 c.pos, c.wght, sum(c.wght) 它们在块结构中定义并用零值初始化。

子系统"超声波传感器"

在"输送机上的负载"块中计算的距离皮带开始最远的负载位置的值被传输到"超声波传感器"子系统。 如果负载位置等于传感器L的位置,则产生高电平逻辑信号"负载可被移除"。 传感器L在本例中的位置等于输送滚筒之间的距离。

image.png

子系统"货物放置"

另一个辅助子系统是"货物放置"。 在其中,根据来自可编程逻辑控制器的"放置新负载"信号,产生具有一个仿真步骤的持续时间和先前在原始示例中设置的范围内的随机负载值的信号。

image.png

接收到的"来自新的负载"信号然后被发送到"输送机上的负载"子系统。

子系统"可编程逻辑控制器"

输送机控制算法在可编程逻辑控制器(PLC)子系统中使用[图表]块(https://engee.com/helpcenter/stable/ru/state-machines/chart.html )。

该算法的工作原理是直观的,但另外我们将修复要点。:

*状态图中有2个主要过程:

*磁带移动(条件 mov),

*搬运货物。

*条件 mov 它包括三个变电站:

  • start -仅在模拟开始时执行,启动发动机(motor = 0),之后1秒,以下状态打开:

  • give -产生负载放置信号(put = 1),紧接着,执行到下一个状态的转换:

  • wait -移除负载放置信号(put = 1),我们形成一个3秒的等待放置一个新的负载。

*货物搬运处理如下:

*如果负载传感器被触发(sensor == 1),有一个过渡到状态 stop,

*在 stop 发动机停止(motor = 1),在1秒后,发生到下一个状态的转换:

*在起飞时产生移走进港货物的信号(rem = 1),

*紧接着,负载移除信号被移除(rem = 0),

*1秒后,图表返回状态 mov.

image.png

让我们继续在Engee中建模。

在Engee建模

让我们使用[软件建模控制]运行模型(https://engee.com/helpcenter/stable/ru/modeling/programmatic-modeling.html )和预先准备的功能,以便于使用模型和模拟结果:

In [ ]:
(example_path = @__DIR__) |> cd; # 我们获取包含当前脚本的目录的绝对路径并转到它。
include("useful_functions.jl"); # 我们将Julia脚本与辅助函数连接起来
In [ ]:
simout = get_sim_results("conveyor_control.engee", example_path) # 运行模拟
Out[0]:
SimulationResult(
    "нагрузки" => WorkspaceArray{Vector{Float64}}("conveyor_control/Грузы на конвейере/нагрузки")
,
    "старт/стоп двигаталя" => WorkspaceArray{Float64}("conveyor_control/Программируемый логический контроллер/старт/стоп двигаталя")
,
    "Перемещение ленты" => WorkspaceArray{Float64}("conveyor_control/Перемещение ленты")
,
    "позиции" => WorkspaceArray{Vector{Float64}}("conveyor_control/Грузы на конвейере/позиции")
,
    "Программируемый логический контроллер.rem" => WorkspaceArray{Float64}("conveyor_control/Программируемый логический контроллер/Программируемый логический контроллер.rem")
,
    "Ток статора" => WorkspaceArray{Float64}("conveyor_control/Ток статора")
,
    "разместить новый груз" => WorkspaceArray{Float64}("conveyor_control/Программируемый логический контроллер/разместить новый груз")
,
    "Обороты (у.е)" => WorkspaceArray{Float64}("conveyor_control/Обороты (у.е)")
,
    "Скорость ленты" => WorkspaceArray{Float64}("conveyor_control/Скорость ленты")

)

模拟结果-引擎

我们将接收并减少模型中记录的信号,在发动机上测量:

In [ ]:
t = thin(get_sim_data(simout, "定子电流", 1, "time"), 100);
Is = thin(get_sim_data(simout, "定子电流", 1, "value"), 100);
n = thin(get_sim_data(simout, "转数(单位)", 1, "value"), 100);

让我们绘制这些变量:

In [ ]:
gr(fmt=:png, size = (900,400))
I_graph = plot(t, Is; label = "I(t)", title = "定子电流", ylabel = "I [A]", xlabel = "t[s]")
n_graph = plot(t, n; label = "n(t)", title = "转子转速", ylabel = "n[单位]", xlabel = "t[s]")
plot(I_graph, n_graph)
Out[0]:
No description has been provided for this image

如果我们将这些图表与原始示例中呈现的图表进行比较,可以看出,当发动机上达到一定负载时,大约50秒后,发动机开始停止并定期启动-它停止以去除 在启动发动机后,由于向皮带增加了新的负载,负载继续变化。

模拟结果-管道

我们将接收并减少传送带上模型中记录的信号:

In [ ]:
 = thin(get_sim_data(simout, "磁带速度", 1, "value"), 100);
 = thin(get_sim_data(simout, "移动磁带", 1, "value"), 100);

让我们绘制这些变量:

In [ ]:
V_graph = plot(t, ; label = "V(t)", title = "磁带速度", ylabel = "V[米/秒]", xlabel = "t[s]")
S_graph = plot(t, ; label = "S(t)", title = "移动磁带", ylabel = "S[米]", xlabel = "t[s]")
plot(V_graph, S_graph)
Out[0]:
No description has been provided for this image

输送带的运动学图还显示了运动不改变的停止和时刻,这是从输送带中移除负载所必需的。

仿真结果-PLC

我们将在PLC的输入和输出端接收并减少模型中记录的信号:

In [ ]:
start_stop = thin(get_sim_data(simout, "发动机启动/停止", 1, "value"), 100);
rem = thin(get_sim_data(simout, "可编程逻辑控制器。快速眼动", 1, "value"), 100);
pos = map(p -> p[1], thin(get_sim_data(simout, "职位", 1, "value"), 100)) .>= L;

让我们绘制这些变量:

In [ ]:
plot(t, start_stop; label = "开始/停止", width = 2, linestyle=:dot,
        title = "控制器信号", xlabel = "t[s]", legend = :outerright,
        yticks=([0, 1], ["False", "True"]), st=:steppost)
plot!(t, pos; label = "货物已到位", width = 1)
plot!(t, rem; label = "移走", width = 1)
Out[0]:
No description has been provided for this image

控制器接收货物存在的信号,控制器根据算法使用该信号产生对控制对象有影响的信号。

最后,在使用真实PLC在系统中测试模型之前,我们将实时检查模型的运行情况。

实时仿真

由于集成了Engee和[实时机器节奏],可以进行实时模拟(https://engee.com/community/catalogs/projects/kpm-ritm-bystryi-start )。

在[早期的例子](https://engee.com/community/ru/catalogs/projects/a90fd264-cf08-4c7b-93f5-350bd434fee3 已经展示了如何模拟控制对象,并对其性能进行实时评估。 我们已经进行了模拟我们的设施与控制系统在Engee在KPM节奏,现在我们将评估TET:

In [ ]:
Pkg.add(["StatsBase", "Printf"]) # 安装必要的软件包
In [ ]:
import StatsBase.mean, Printf.@printf # 导入所需的函数和宏

作为实时建模的结果,收集了模型分析数据,随后将其记录在文件中。 个人资料。txt的。 将此数据添加到工作区并将其精简以节省内存。

In [ ]:
tet = TxtToVec("$(@__DIR__)/profile.txt");  # 从文件中获取值的向量
tet = filter(t -> t>0, tet);                    # 移除工件
thintet = thin_vector(tet, 20, 0.2);            # 将矢量减薄95%,偏差高达20%

StepTime = 1e3; # 模型的计算步骤,mks

让我们分析分析数据。

In [ ]:
@printf "分析点数:%d\n" length(tet)
@printf "减薄:%d-->%d(%。2f%%)\n\n" l1 = length(tet) l2 = length(thintet) (l1-l2)/l1*100

@printf "最小TET:%。3f ms\n" tet_min = (minimum(tet)/1e6)
@printf "平均TET:%。3f ms\n" tet_mean = (mean(tet)/1e6)
@printf "最大TET:%。3f ms\n\n" tet_max = (maximum(tet)/1e6)

@printf "TET超出数:%d(%。2f%%)" tet_exc = count(>(StepTime*1e3), tet) tet_exc/l1*100
Количество точек профилирования: 89999
Прореживание: 89999 --> 5330 (94.08 %)

Минимальное TET:   0.021 мс
Среднее TET:       0.029 мс
Максимальное TET:  48.076 мс

Число превышений TET:  14 (0.02 %)

在评估TET时,发现在某些点上,任务执行时间相对于计算步骤最多超过480%。 让我们建立一个TET变化的图表,检查这样的卷出现在哪里。

In [ ]:
gr(format = :png, legend=:bottomright, title="\N模型在KPM节奏上的执行时间",
    xlabel="模型时间,ms", ylabel="交货时间,mks")


plot(thintet./1000;  label="TET", yaxis=:log, ylims=(10,1e5))
plot!([0, length(thintet)], [StepTime,  StepTime];  label="StepTime",   color=:green)
Out[0]:
No description has been provided for this image

从TET图可以看出,在电路中的某些事件时刻会发生显着的浪涌。

对于该示例的模型的"战斗"应用,将需要细化模型以符合实时性。 可以采取以下步骤:

*优化模型,

*调整求解器,

*增加机器的计算能力,

*联系触发事件以升级块的块的开发人员。

结论

在这个例子中,我们研究了使用Engee函数和图表来开发自定义块和控制系统。 我们对带有货物输送系统的输送机进行了模拟,并计算了各种重量的货物的移动,以及一个原型控制系统。 最后,我们进行了实时模拟并估计了任务完成时间。