CoDeSys常规编程技巧
IEC 61131-3
IEC 61131-3定义了5种编程语言,在绝大多数情况下,我们只推荐使用结构化文本(ST)语言作为编程首选语言。
在您刚开始学习PLC编程或由硬PLC转为软PLC时,我强烈建议您阅读这本书:
开放式控制系统编程技术 基于IEC 61131-3国际标准–马立新,陆国君 京东链接
虽然我不是很认可TwinCAT3的架构,但毫无疑问TC3比CoDeSys更广为人知,所以也推荐:
TwinCAT3.1从入门到精通 陈利君著 BECKHOFF倍福公司推荐 京东链接
此外,我推荐读者申请一个Codesys Store账号,下载一些官方的Example实例。
最后,我推荐读者了解一下OSCAT库,尝试阅读并理解库的内容。
使用Struct结构体替代GVL,规范名称
较多的变量归为结构体,例如Out.Sensor1、Servo[0].xExecute等
一般变量命名带前缀,例如BOOL型前缀为x xExecute,INT型前缀为i iState,DWORD型前缀为dw dwActPos 等。参考CoDeSys Identifiers
变量后加备注,鼠标停留在任何引用处都会显示,例如dwActPos//当前位置
使用:=、S=、R=、SEL替代IF…END_IF
IF…END_IF及其嵌套会导致代码量过于庞大,不易阅读和调试。
例1:若只有一个变量,可直接用:=:
IF In.Sensor1 THEN
Out.Cylinder1:=TRUE;
ELSE
Out.Cylinder1:=FALSE;
END_IF;
可简写为
Out.Cylinder1:=In.Sensor1;
例2:若有两个变量切换,可用S= R=:
IF In.Sensor1 THEN
Out.Cylinder1:=TRUE;
END_IF;
IF In.Sensor2 THEN
Out.Cylinder1:=FALSE;
END_IF;
可简写为
Out.Cylinder1 S= In.Sensor1;
Out.Cylinder1 R= In.Sensor2;
例3:切换变量值,使用SEL:
IF xEnable THEN
rSet:=5;
ELSE
rSet:=0;
END_IF
可简写为
rSet:=SEL(xEnable,0,5);
灵活使用TON
例1:闪烁指示灯BLINK,我们可以使用UTIL库里的BLINK功能块(UTIL库可以看作Standard库的扩充),也可以直接用TON来做,例如:
ton_Blink(IN:=TRUE,PT:=T#800MS);
IF ton_Blink.Q THEN
ton_Blink(IN:=FALSE);
xBlink:=NOT xBlink;
END_IF
xBlink会以1.6秒为周期规律闪烁
例2:信号延迟启动,条件满足后延迟200ms启动:
ton_Delay(IN:=In.Sensor1,PT:=T#200ms);
Out.Cylider1 S= ton_Delay.Q;
Sensor1触发200MS后,Cylider1会被ton_Delay.Q置位
使用CASE将任务分步
某个自动化设备,带有多个气缸和传感器,主体结构如下:
传送带运行->传感器 1检测到物体,传送带停止->气缸 1动作,500MS后松开->等待传感器 2->传送带运行
代码如下:
CASE iState OF
0:
Out.Trans:=TRUE;//传送带运行
IF In.Sensor1 THEN//检测到Sensor1,跳转到第10步
iState:=10;
END_IF
10:
Out.Cylinder:=TRUE;//气缸打开
ton_Delay(IN:=TRUE,PT:=T#500MS);//计时器500MS
IF ton_Delay.Q THEN
ton_Delay(IN:=FALSE);//复位计时器
Out.Cylinder:=FALSE;//关闭气缸
iState:=20;//跳转到第20步
END_IF
20:
IF In.Sensor2 THEN//检测到Sensor2,跳转到0步
iState:=0;
END_IF
END_CASE
调试时使用Debug下的Flow Control Mode(流控制)可以很方便的看到执行到了哪里。
将自己的源代码加密
很多情况下我们需要将Project共享给同事或者第三者。一般而言,Codesys支持两级加密,第一级在Project->Settings->Security里,可以设置自己的密码,如下:
第二级加密在Project->Settings->Users and Groups里,创建一个带密码的Admin用户并删除原先的Owner用户,给与全部权限。登陆后将要加密内容的Properties->Access control里都设为denied即可。操作如下:
设置visu指示灯
默认Visu支持的指示灯一般只有开关两种状态,我们可能会遇到显示灰/绿/黄/红的指示灯,最简单的方法是用ColorVaribale,我们先在Visu里创建一个Rectangle矩形块,然后把Element Look的Line Style设为Hollow(禁用外轮廓),之后在Color Variables->Normal State->Fill color关联到一个DWORD变量即可。要修改颜色时使用如下格式:
IF xRed THEN
dwColor:=16#FFFF0000;//16#为固定前缀,FF为透明度,FF0000为十六进制颜色(红色)
ELSE
dwColor:=16#FFD4D0C8;//灰色
END_IF
灵活使用循环
一般我们是不推荐使用For…和While…语句的,因为比较容易造成死循环。但某些时候它们可以带来很好的效果。
例1:多个输入添加10ms上升沿防抖
FOR i:=1 TO 8 DO
TON_Delay[i](IN:=IN[i],PT:=T#10MS);
OUT[i]:=TON_Delay[i].Q;
END_FOR
例2:一个不停记录轴在负方向运动时坐标的数组,取它当前值加5MM位置所对应的数组编号(跟随效果):
WHILE (arPosTemp[iFollowNum]-arPosTemp[iActNum] > 5) AND (iFollowNum < iActNum) DO
iFollowNum:=iFollowNum+1;
END_WHILE
在标准化设备上使用POU页
某些设备多数PLC内容是相同的,但有部分不一样,总线拓扑结构也不同。这种情况下,我们把程序放在POU页里(View->POUS),它可以放置一些FB、POU、Visualization等。之后我们再Device页多配置一些设备,每个设备存在不同的GVL用作配置。用的时候把对应的Application设为Active即可。
灵活使用TRACE辅助诊断
TRACE可以提供比示波器更佳的诊断效果,它在PLC循环结束后记录每个变量的数据并显示,非常适合对信号和变量的持续跟踪。
Comments: 2
例2如果是要实现RS触发器功能,那用ELSIF是错误的
感谢您的指正,ELSIF确实会在两个输入都为TRUE的时候与RS触发器产生歧义,已更正为双IF。谢谢。