你觉得这篇文章怎么样? 帮助我们为您提供更好的内容。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
你觉得这篇文章怎么样?
一个简单的结构式文本 (PLC) 程序,可在 RevPi Core 3 上运行以控制交通灯。
将 RevPi Core 3 和 DIO 安装在 DIN 导轨上并成功运行后(详见上一个帖子,我准备用它们来做一些有意义的事情。作为“概念验证”,我想试着模拟一个简单的交通灯装置。
结构式文本 (ST)
创建 PLC 控制程序的主要标准语言分为 3 种 - 结构式文本语言 Structured Text Language (ST)、梯形逻辑和功能块图 (FBD)。顾名思义,后两者是更为图形化的界面,然而它们的灵活性不如结构式文本语言,加上 RevPi 随附的免费版 logi.CAD 3 仅支持结构式文本语言,因此我选择使用它。
尽管结构式文本是一种行业标准 IEC 61131-3 管理范围内的标准化语言,且语言核心保持不变,但是每个 PLC 供应商都做出特定的修改和增加。我在网上找到了一篇实用的入门教程,在它的指导下我开始着手搭建。对于熟悉计算机语言的人来说,结构式文本由 PASCAL 发展而来,它让我想起许多年前,我在 ZX80 上用来进行乒乓球游戏编程的 BASIC 语言。
logi.CAD 3
除了使用新的语言以外,我还使用了以前从未用过的软件。我发现,通过浏览 logi.CAD 3 术语表了解一些使用的术语,然后在必要时再次查阅,对我的工作有很大的帮助。我特别记录了以下几点:
- 对象 - logi.CAD 3 项目资源管理器中的对象位于文件夹内,是该文件夹的子文件夹。对象相当于文件系统中的文件。
- 项目 - 项目是 logi.CAD 3 项目资源管理器中的一种特殊类型的文件夹。默认情况下,项目是项目资源管理器中的根目录。
完整的内容总称为应用程序,它不仅有包含已编写代码的 STL 文件,还包括配置文件、全局变量和专用于 PLC 的库。
这时,我发现了一个有效的办法,那就是通过单击“Project Menu(项目菜单)”下的“Clean(清理)”选项来“清理”项目,然后等待 Logi.CAD 3 运行完毕,之后应用程序创建并加载成功。
闪烁的灯光
我已经创建了一个简单的应用程序,可用于控制一盏灯闪烁。这基于我在上一篇博客中使用的 RevPi 快速入门指南 示例。
PROGRAM RevolutionPiCounterProgram
VAR
value : BOOL;
END_VAR
VAR_EXTERNAL
Red_1 : BOOL;
Amber_2 : BOOL;
Green_3 : BOOL;
END_VAR
IF value THEN
Red_1 := False;
value := False;
ELSE
Red_1 := True;
value := True;
END_IF;
END_PROGRAM
本例中,LED 持续闪烁。这是因为 PLC 应用程序会自动重复。“End_Program”实际上表示返回到起始行然后重新开始。
教程中解释如下“当 PLC 运行到 END_PROGRAM 时,PLC 扫描周期将重新开始,程序将重新运行”:
交通信号灯
现在,我需要研究出如何使 LED 以标准交通灯亮顺序闪烁 - 红、红和黄、绿、黄,然后再回到红。
更改信号灯的闪烁速度时,只需在配置文件中编辑一个数值即可,但是这会改变整个扫描循环的速度,因此这种方法较为粗糙,只会使应用程序整体减慢。此外,我还想要能单独改变不同灯的闪烁速度。事实证明,这比最初预期的难度更大。
TON 函数(计时器延迟)提供了所需的延迟,但我无法通过代码获得所需的效果。我能够使 LED 亮起一定时间后熄灭,但是却无法再次亮起,或者能够使 LED 闪烁并熄灭,但是却无法指定熄灭时间。我反复碰壁,一度觉得这项任务可能超出了我的处理能力。就在这时,我在网络上寻求帮助,在 Codesys 论坛上找到了一篇实用的博客文章,其中提到了 CASE 语句。Codesys 的功能与 logi.CAD 类似,而我发现它们所用的结构化文本语法存在一些差异,但是我成功地根据我的需要对示例进行了调整。
我曾经在网络教程中学习过 CASE 语句,但是直到我看到这个示例时,才突然认识到如何能够将它用于实际应用中。
最终代码如下:
PROGRAM RevolutionPiProgram
VAR
wait : TON;
count : INT;
END_VAR
VAR_EXTERNAL
Red_1 : BOOL;
Amber_2 : BOOL;
Green_3 : BOOL;
END_VAR
CASE count OF
0: //init
count := count + 1;
1: // Red
Red_1 := True;
Amber_2 := False;
Green_3 := False;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
2: // Red and Amber
Red_1 := True;
Amber_2 := True;
Green_3 := False;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
3: // Green
Red_1 := False;
Amber_2 := False;
Green_3 := True;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
4: // Amber
Red_1 := False;
Amber_2 := True;
Green_3 := False;
wait(IN:=TRUE, PT:=T#5s);
IF wait.Q THEN
wait(IN:=FALSE);
count := count + 1;
END_IF;
ELSE
count := 0;
END_CASE;
END_PROGRAM
CASE 用于在出现特定整数值时执行语句。本例中创建了一个名为“count”的整数变量,此变量在每次 PLC 扫描时增加 1,直到最终条件运行以及 ELSE 将它重新设置为零。而 TON 将每个语句运行 5 秒。更改该数值时,只需编辑以下行中的 5s 值即可:
wait(IN:=TRUE, PT:=T#5s);
如有需要,可以为每次灯亮指定不同的时间(在以下视频中,我将它们全部更改为了 2 秒)。如需增加灯的数量,也可通过扩展代码轻松实现。
结论
在学习使用新的(就我而言)计算机语言和不熟悉的软件时,总会面临各种挑战,但是我对最终得到的优秀解决方案感到非常满意。虽然我最终搭建出的交通灯可能不完全“适合道路应用”,但是可以看到,只需适当的调整,它们可在农业展览等类似的一次性活动中用于简单的交通控制。
评论