我想知道我是否可以用状态机/图表编程PLC。
在Sparx EA的帮助下,我们可以组成我们的状态机。有没有机会将此状态机转换为SCL(结构化控制语言,用于PLC编程)?或者我们可以从Sparx EA获取哪些数据,我们可以将其用作PLC编程的输入?
或者你可能更清楚如何实现这个想法。
答案 0 :(得分:2)
不确定。您需要一个能够读取状态机图的代码生成器工具,并生成等效的结构化文本。
代码的形状非常简单。您可以为每个位定义一个ST布尔值(如果您可以在StateCharts中具有实时并行状态)或包含状态编号的ST整数。
每个州的ST代码是:
if (StateXXX) then
<action in this state>
if (somecondition)
StateXXX=false;
StateYYY=true;
endif
endif
您需要为每个州生成此代码。
这就留下了用什么工具来实现这一目标的问题? 可以说任何可以读取UML图的工具,通常可以从UML编辑器导出为XML文档;使用解析后的XML,您可以编写代码来爬过它并吐出上面的代码片段。
如果您编写明确定义的模板片段,这可能会更容易。您可以使用临时模板(只需要包含标记的文本字符串,其中必须填写某些内容),或者您可以使用强制生成代码的结构和组合的工具,例如Program Transformation System (PTS)。
PTS接受语言的语法,将解析该语言的实例,并让您转换该语言,最后吐出修改后的语言实例。一个有用的特殊情况是,如果您愿意,将简单的程序转换为复杂的真实程序。此外,一个好的PTS将允许您根据正式代码模板编写模式和转换规则,这至少强制模板的语法有效。这可确保您使用的部件始终具有一定的最小感觉。 (相比之下,您可以在文本模板中编写任何您喜欢的垃圾)。当你写出很多这样的模式时,这对避免产生垃圾很有帮助。
对于这个特殊的例子,对于(我公司的PTS称为DMS,请参阅bio),您可以为上述片段编写模式:
pattern StateInstance(statenumber: natural, action: statements, exit_condition: expression, exit_state: natural): statement =
" if (StateNumber=\statenumber) then
\action
if (\exit_condition) then
StateNumber=\exit_state
endif
endif
";
DMS提供API来实例化此模式(以及其他人,通常编写许多模式)并将其结果(使用实例化模式作为其他模式的参数进行实例化)以生成最终程序。您还可以添加转换规则以优化生成的代码。 (DMS由语法定义驱动;它已经知道40多种语言,特别是对ST和XML有强大的定义。)
答案 1 :(得分:1)
我从未真正编写过S7,但基本上知道你在寻找什么。 EA没有SCL的生成器,很可能看不到来自Sparx的生成器。所以有两种可能性。
首先(但不是我首选)是深入研究在代码生成过程中使用的Sparx宏语言的内容。如果您只是需要对现有模板进行微调,那很好,但写一个全新的模板并不好玩(对我来说)。
第二种方法是使用API进行代码生成。这很容易(对我来说,因为我在大学学习编译器构建)。你要做的是拿起状态机,遍历它并吐出相应的语言结构。这在很大程度上取决于你的技能,但我会在几天内创建一个粗略的原型。
编辑以下是一个示例Perl(我知道它是一个PITA,如果你不使用它一个星期左右,但你可能会破译它)脚本解析状态机使用EA的API:
package Compiler;
use strict;
use Win32::OLE qw (in);
sub new {
my ($self, $rep) = @_;
$self = {};
$self->{nodes} = {};
$self->{rep} = $rep;
bless $self;
}
sub traverse {
my ($self, $node) = @_;
my $guid = $node->ElementGUID;
return if defined($self->{nodes}->{$guid});
my $nodeInfo = { 'name' => $node->Name, 'type'=> $node->Type, 'out' => ()};
$self->{nodes}->{$guid} = $nodeInfo;
for my $trans (in $node->Connectors) {
my $target = $self->{rep}->GetElementByID($trans->SupplierID);
next if $target->ElementGUID eq $guid;
my @targetInfo = ($trans->TransitionGuard, $target->ElementGUID);
push(@{$nodeInfo->{out}}, \@targetInfo);
$self->traverse($target);
}
}
1;
和这样一个简单的主程序:
use strict;
no strict 'refs';
use compiler;
my $rep = $ENV{'REP'}; # get repository pointer "by magic"
my $node = $rep->GetElementByGUID('{574C5E0C-E032-44c6-A6B0-783D35B9958B}'); # fixed addressing of InitialNode
my $compiler = Compiler->new($rep);
$compiler->traverse($node); # read in all possible transitions/states
my %states = %{$compiler->{nodes}}; # this hash holds all states and their transitions
for my $key (keys %states) {
my $state = $states{$key}; # loop through all found states
print "$state->{type} $state->{name}\n"; # state name
for my $out (@{$state->{out}}) {
my ($guard, $guid) = @{$out};
my $target = $compiler->{nodes}->{$guid};
print "__$guard -> $target->{name}\n";
}
}
现在假设您有一个这样的状态机:
运行上述程序时,将打印
StateNode
StateNode
__no condition - &gt; State1
州州1 __condition - &gt; State2
__exit - &gt;
州州2 其他条件 - &gt; State1
第一个StateNode是未命名的出口,下一个是InitialNode(您也可以从API获取该信息并使用它)。 State1
有两种可能的转换(退出和State2
)。 State2
仅转换为State1
。
现在,通过命名状态列表,您可以为不同的状态创建一些枚举。您还可以使用所有转换的保护,您可以转换为if-cascades或switch-statements。
当然这不是一个完整的代码生成器,但您可以了解如何从这个脚手架中创建一个。
答案 2 :(得分:0)
如果您使用的是西门子PLC-s,那么S7有一个名为s7-graph的可选软件包:http://w3.siemens.com/mcms/simatic-controller-software/en/step7/simatic-s7-graph/Pages/Default.aspx。您可以在那里实现状态机。但是不知道它的任何导入选项。
我将它用于一些被控制为状态机的设备。该软件包不是免费的,我不记得它的价格。我也不知道是否所有S7 PLC系列都支持它。我使用了400系列,并在那里工作。
在任何项目中使用之前,请咨询您当地的西门子经销商,让您稍微玩一下。
答案 3 :(得分:-1)
我已经在EA中编写了一个模板,以实现从类图,状态机到ST / SCL代码(Twincat / Codesys中为IEC61131)的代码生成PLCopen代码。
类图用于描述FB,DUT等程序的结构。 状态机用于描述plc程序的动态过程。 这样,整个oop plc程序(带有Interface,Inherit)将自动从生成的UML模型中获得。
https://www.youtube.com/watch?v=z071cZgMbZ8
这里我创建了一个新的工具箱,专门用于EA中plc程序的建模