您现在所在的是:

PLC论坛

回帖:0个,阅读:795 [上一页] [1] [下一页]
2009
万泉河.
文章数:915
年度积分:-106
历史总积分:2009
注册时间:2009/12/4
发站内信
发表于:2023/3/14 15:31:26
#0楼
0313 【万泉河】万老师手把手带你抄PLC程序

前面写了一篇文章《0304 【万泉河】 我把LBP的功能块解耦了》,讲解了把LBP的一个MOTOR块一分为二解耦成2个单独的块的过程方法和意义。

然后有人就在后面酸溜溜的评论道:情商高的说法把抄说成了解耦。

意思就是瞧不上我这种公然抄和借用别人的现成的库函数方法,并大行其道的宣传。

我简直被这种价值观给惊讶到了。 我这儿还巴拉巴拉地介绍开源,幻想工控行业也会有繁盛开源的那一天呢!哪想到同行之中还有另一派完全公然相反的价值观在运行。

先这么说吧,我们现在的技术观点,讲究的是不自己重新发明轮子。所以,如果你在十几年前从每一个工程项目都从启保停开始写PLC程序,WINCC程序每个人都要从头研究窗口弹出,变量前缀,以实现子窗口功能的话, 还有情可原。 毕竟那个时候自动化行业的发展成熟程度还不够。

而十几年后的今天, 你仍然十几年如一日做着同样的工作,技术已经发展到如此成熟,网络资源如此唾手可得的情况下,还在沿用老的工作方式,那可想而知其中的工作效率有多低,做出来的效果有多土了。

十几年前我们的工资几千块钱, 那么到今天,除却物价增长因素,你的工资也还仍然应该停留在几千元。没有创造更多的效益,凭什么就要拿到更高的收入呢?

所以,这个行业需要达成的一个基本的共识是, 要想效率高,收入高,就要学会如何充分利用已有轮子,免费或者付费,在已有的轮子的基础上,快速实现应用,以充分发挥自己的优势。

这也是隔壁IT行业早就在践行的基础。

也是我为啥明知这个行业的大多数人当下并不理解和接受LBP, 明知道做了也不会产生什么效益,明知道其中的困难难度极大,却仍然要独自前行闯出一条路来把LBP的接口方法移植拓展到更多平台的原因。

同时,有领导批评我做着西门子HMI版区的版主,近来对HMI和WINCC的技术却关心很少,貌似精力全放到PLC去了。 通过本文通过LBP,可以看到,当工控技术发展到一定的层级, PLC和HMI的工作一定是同步的,甚至在PLC中做的大量工作都是在给HMI做数据准备。 离开了PLC工作的标准化,HMI上的标准化根本无从谈起。

在对LBP_MTR解耦并实现移植应用之后,我下一个库函数的目标便盯上了INTLK8函数。先用同样的方法解耦成2个模块,然后再一步步分别移植到SMART 200和KTP 触摸屏以及将来更多的拓展方向。

先解释下INTLK8这个库函数的功能。我在做LBP移植五期讲座的时候,这里只是随口提了一下,就越过去了,相应的功能因为比较复杂,而且用的场合不多,就建议简单删掉算事了。所以这里仔细讲一下, 学员们通过看文章充分了解后,需要的话那部分功能还可以再拾起来。

我在前一本书《PLC标准化编程原理和方法》中P161页提到过,BST库中有一个可视化联锁功能,BST_ILOCK (FB651) 。然而在BST中时有时无,曾经在S7-400的版本中有过,但到了PORTAL版本中给取消了。 所以我们在做PORTAL项目时,需要用到的时候,还是从S7-400中参考移植过来的。

逻辑其实很简单,就是对多个管脚的取与AND或OR逻辑计算,得到的结果可以用于对电机阀门等设备的启动条件连锁等功能。

但通过一个专用的FB,实现了在上位机的可视化管理,操作人员可以在设备故障不能启动时,通过上位界面,详细了解运行条件的满足和缺失情况。 所以可以认为整个FB本质上是为HMI显示服务的。 否则仅仅为了逻辑功能,在PLC中做与(串联)、或(并联)的梯形图逻辑都是一句话的事,不需要什么功能块。

有一些行业,要求触摸屏和上位机有跳转到PLC中查看梯形图逻辑的功能。有极少数的控制系统搭配其自家的触摸屏,通过一些特殊的插件,可以实现。 然而本质上说,客户要的并不是在触摸屏上能翻阅所有控制逻辑,就是希望能可视化的看到重要设备的启动条件而已。 所以这种连锁功能的可视化就可以实现这样的功能。

这个功能在蛰伏了数年之后,在LBP中重新出现了,名字叫做LBP_INTLK8,望文生义,可以最多控制8个输入条件。如果再多,可以多次调用来实现。

而LBP_INTLK8比BST_ILOCK先进的地方在于,原本BST中的逻辑条件只能集体统一选择AND 或者OR, 每个管脚之间并不能单独选择。而INTLK8实现了每个管脚都可以分配不同的逻辑,包括:
1=OR,2=AND , 3= OR NOT, 4=AND NOT。
以及0=无效。
由此,通过一个标准化的模块可以实现更丰富的逻辑条件,及其可视化。

有了这样的功能,一个系统中,最重要的主机部分的启动条件前面都可以通过这样的可视化条件接入。然后在触摸屏上就可以实现可视化监控管理了。比起设计的程序只能让设备运转起来,运转不起来时则需要用户翻说明书,或者打服务电话咨询,都要友好和便捷的多了。那么同比之下,这样的设备就更容易被客户接受,也更容易卖上高价值。


在S7-1200和TP900触摸屏中的实现毫无难度,与普通的LBP模块基本相同。 解耦方法也相同。

然而在TP触摸屏中,动画的实现方法是通过脚本程序实现的。 通过PLC送来的一个2S脉冲变量,变量的变化事件中执行脚本,将FB的状态字解码后经过逻辑计算,来设置画面中逻辑结果的显示和颜色切换。
Function LBP_Intlk8()
'Activation only when the screen Intlk8 is opened

If HmiRuntime.BaseScreenName <> "LBP_Intlk8_Startscreen" Then
   Exit Function
End If

LBP_Intlk8 = 0
Dim status, overwrite, n, wMask, sName, arrLogic(7), plcName(7), nameText(7)
status = SmartTags("LBP_Intlk8.statusHMI.status")
overwrite = SmartTags("LBP_Intlk8.settingsHMI.overwrite")

Dim ObjItem
Set ObjItem = HmiRuntime.Screens(HmiRuntime.BaseScreenName).ScreenItems


' read and show logic types
wMask = 2^8
For n = 0 To 6
If (overwrite And wMask) <> 0 Then
sName = SmartTags("LBP_Intlk8.settingsHMI.logics")(n)
Else
sName = SmartTags("LBP_Intlk8.settingsPLC.logics")(n)
End If
arrLogic(n) = sName
wMask = wMask * 2
Next

' Change visibility of HMI and PLC names
nameText(0) = SmartTags("LBP_Intlk8.settingsHMI.texts[0]")
nameText(1) = SmartTags("LBP_Intlk8.settingsHMI.texts[1]")
nameText(2) = SmartTags("LBP_Intlk8.settingsHMI.texts[2]")
nameText(3) = SmartTags("LBP_Intlk8.settingsHMI.texts[3]")
nameText(4) = SmartTags("LBP_Intlk8.settingsHMI.texts[4]")
nameText(5) = SmartTags("LBP_Intlk8.settingsHMI.texts[5]")
nameText(6) = SmartTags("LBP_Intlk8.settingsHMI.texts[6]")
nameText(7) = SmartTags("LBP_Intlk8.settingsHMI.texts[7]")
For n = 0 To 7
If nameText(n) ="" Then
plcName(n) = True
Else
plcName(n) = False
End If
Next
'
 
'read signal colors
Dim colorInput(1)
colorInput(1) = SmartTags("LBP_Intlk8.settingsHMI.colors.signalColorOn")
colorInput(0) = SmartTags("LBP_Intlk8.settingsHMI.colors.signalColorOff")

If (colorInput(0) = 0) And (colorInput(1) = 0) Then
colorInput(0) = &hF8E4B6
colorInput(0) = &h8A6513
End If


' visible inputs
ObjItem("lineInpOn_1").Color = colorInput((CInt(CBool(status And 2^0)))*(-1))
ObjItem("lineInpOn_2").Color = colorInput((CInt(CBool(status And 2^1)))*(-1))
ObjItem("lineInpOn_3").Color = colorInput((CInt(CBool(status And 2^2)))*(-1))
ObjItem("lineInpOn_4").Color = colorInput((CInt(CBool(status And 2^3)))*(-1))
ObjItem("lineInpOn_5").Color = colorInput((CInt(CBool(status And 2^4)))*(-1))
ObjItem("lineInpOn_6").Color = colorInput((CInt(CBool(status And 2^5)))*(-1))
ObjItem("lineInpOn_7").Color = colorInput((CInt(CBool(status And 2^6)))*(-1))
ObjItem("lineInpOn_8").Color = colorInput((CInt(CBool(status And 2^7)))*(-1))



' show results inputs 1/2
Dim logic1, logic2, signalInputs
logic1 = arrLogic(0) > 0
logic2 = arrLogic(1) > 0
signalInputs = (CInt(CBool(status And 2^8)))*(-1)
ObjItem("poly0To2On").Color = colorInput(signalInputs)
ObjItem("poly01To02On").Color = colorInput(signalInputs)
ObjItem("poly1To2On").Color = colorInput(signalInputs)
ObjItem("poly1To0On").Color = colorInput(signalInputs)
ObjItem("poly0To2On").Visible = Not logic1 And logic2
ObjItem("poly01To02On").Visible = Not logic1 And Not logic2
ObjItem("poly1To2On").Visible = logic1 And logic2
ObjItem("poly1To0On").Visible = logic1 And Not logic2
ObjItem("lineInpOn_1").Visible = True
ObjItem("ioTxtHMI1").Visible = Not plcName(0)
ObjItem("ioTxtPLC1").Visible = plcName(0)
ObjItem("lineInpOn_2").Visible = logic1
ObjItem("ioTxtHMI2").Visible = logic1 And Not plcName(1)
ObjItem("ioTxtPLC2").Visible = logic1 And plcName(1)


' show results inputs 2/3
logic1 = arrLogic(1) > 0
logic2 = arrLogic(2) > 0
signalInputs = (CInt(CBool(status And 2^9)))*(-1)
ObjItem("poly0To3On").Color = colorInput(signalInputs)
ObjItem("poly02To03On").Color = colorInput(signalInputs)
ObjItem("poly2To3On").Color = colorInput(signalInputs)
ObjItem("poly2To0On").Color = colorInput(signalInputs)
ObjItem("poly0To3On").Visible = Not logic1 And logic2
ObjItem("poly02To03On").Visible = Not logic1 And Not logic2
ObjItem("poly2To3On").Visible = logic1 And logic2
ObjItem("poly2To0On").Visible = logic1 And Not logic2
ObjItem("lineInpOn_3").Visible = logic1
ObjItem("ioTxtHMI3").Visible = logic1 And Not plcName(2)
ObjItem("ioTxtPLC3").Visible = logic1 And plcName(2)

' show results inputs 3/4
logic1 = arrLogic(2) > 0
logic2 = arrLogic(3) > 0
signalInputs = (CInt(CBool(status And 2^10)))*(-1)
ObjItem("poly0To4On").Color = colorInput(signalInputs)
ObjItem("poly03To04On").Color = colorInput(signalInputs)
ObjItem("poly3To4On").Color = colorInput(signalInputs)
ObjItem("poly3To0On").Color = colorInput(signalInputs)
ObjItem("poly0To4On").Visible = Not logic1 And logic2
ObjItem("poly03To04On").Visible = Not logic1 And Not logic2
ObjItem("poly3To4On").Visible = logic1 And logic2
ObjItem("poly3To0On").Visible = logic1 And Not logic2
ObjItem("lineInpOn_4").Visible = logic1
ObjItem("ioTxtHMI4").Visible = logic1 And Not plcName(3)
ObjItem("ioTxtPLC4").Visible = logic1 And plcName(3)

' show results inputs 4/5
logic1 = arrLogic(3) > 0
logic2 = arrLogic(4) > 0
signalInputs = (CInt(CBool(status And 2^11)))*(-1)
ObjItem("poly0To5On").Color = colorInput(signalInputs)
ObjItem("poly04To05On").Color = colorInput(signalInputs)
ObjItem("poly4To5On").Color = colorInput(signalInputs)
ObjItem("poly4To0On").Color = colorInput(signalInputs)
ObjItem("poly0To5On").Visible = Not logic1 And logic2
ObjItem("poly04To05On").Visible = Not logic1 And Not logic2
ObjItem("poly4To5On").Visible = logic1 And logic2
ObjItem("poly4To0On").Visible = logic1 And Not logic2
ObjItem("lineInpOn_5").Visible = logic1
ObjItem("ioTxtHMI5").Visible = logic1 And Not plcName(4)
ObjItem("ioTxtPLC5").Visible = logic1 And plcName(4)

' show results inputs 5/6
logic1 = arrLogic(4) > 0
logic2 = arrLogic(5) > 0
signalInputs = (CInt(CBool(status And 2^12)))*(-1)
ObjItem("poly0To6On").Color = colorInput(signalInputs)
ObjItem("poly05To06On").Color = colorInput(signalInputs)
ObjItem("poly5To6On").Color = colorInput(signalInputs)
ObjItem("poly5To0On").Color = colorInput(signalInputs)
ObjItem("poly0To6On").Visible = Not logic1 And logic2
ObjItem("poly05To06On").Visible = Not logic1 And Not logic2
ObjItem("poly5To6On").Visible = logic1 And logic2
ObjItem("poly5To0On").Visible = logic1 And Not logic2
ObjItem("lineInpOn_6").Visible = logic1
ObjItem("ioTxtHMI6").Visible = logic1 And Not plcName(5)
ObjItem("ioTxtPLC6").Visible = logic1 And plcName(5)

' show results inputs 6/7
logic1 = arrLogic(5) > 0
logic2 = arrLogic(6) > 0
signalInputs = (CInt(CBool(status And 2^13)))*(-1)
ObjItem("poly0To7On").Color = colorInput(signalInputs)
ObjItem("poly06To07On").Color = colorInput(signalInputs)
ObjItem("poly6To7On").Color = colorInput(signalInputs)
ObjItem("poly6To0On").Color = colorInput(signalInputs)
ObjItem("poly0To7On").Visible = Not logic1 And logic2
ObjItem("poly06To07On").Visible = Not logic1 And Not logic2
ObjItem("poly6To7On").Visible = logic1 And logic2
ObjItem("poly6To0On").Visible = logic1 And Not logic2
ObjItem("lineInpOn_7").Visible = logic1
ObjItem("ioTxtHMI7").Visible = logic1 And Not plcName(6)
ObjItem("ioTxtPLC7").Visible = logic1 And plcName(6)

' show results inputs 7/8
logic1 = arrLogic(6) > 0
signalInputs = (CInt(CBool(status And 2^14)))*(-1)
ObjItem("lineOutOn_1").Color = colorInput(signalInputs)
ObjItem("lineOutOn_2").Color = colorInput(signalInputs)
ObjItem("lineOutOn_1").Visible = logic1
ObjItem("lineOutOn_2").Visible = True
ObjItem("lineInpOn_8").Visible = logic1
ObjItem("ioTxtHMI8").Visible = logic1 And Not plcName(7)
ObjItem("ioTxtPLC8").Visible = logic1 And plcName(7)

End Function

然而,我们的最终目标是没有脚本功能的如KTP这样的触摸屏,那么这些逻辑只能先在PLC中计算完成,得到画面元素各自的状态位数据,然后触摸屏方仅用于显示。

所以对库函数块做了改造,增加了2个DWORD , VIS1和VIS2 , 不超过64个Bit可以完整表达。

在S7-1200的程序中增加的逻辑:
REGION 增加的触摸屏显示的逻辑图
   REGION ' show results inputs 1/2_
       // Statement section REGION
           
   // #logic1 = arrLogic(0) > 0
   // logic2 = arrLogic(1) > 0
   // signalInputs = (CInt(CBool(status AND 2^8)))*(-1)
   // ObjItem("poly0To2On").Color = colorInput(signalInputs)
   // ObjItem("poly01To02On").Color = colorInput(signalInputs)
   // ObjItem("poly1To2On").Color = colorInput(signalInputs)
   // ObjItem("poly1To0On").Color = colorInput(signalInputs)

   #logic1 :=( #tempLogics[0] > 0);
   #logic2 :=( #tempLogics[1] > 0);
   #plcName[0]:=(#statDataIntlk8.settingsHMI.texts[0]='');
   #plcName[1] := (#statDataIntlk8.settingsHMI.texts[1] = '');
   #plcName[2] := (#statDataIntlk8.settingsHMI.texts[2] = '');
   #plcName[3] := (#statDataIntlk8.settingsHMI.texts[3] = '');
   #plcName[4] := (#statDataIntlk8.settingsHMI.texts[4] = '');
   #plcName[5] := (#statDataIntlk8.settingsHMI.texts[5] = '');
   #plcName[6] := (#statDataIntlk8.settingsHMI.texts[6] = '');
   #plcName[7] := (#statDataIntlk8.settingsHMI.texts[7] = '');
   
   // ObjItem("poly0To2On").Visible = NOT #logic1 AND logic2
   #tempPanel.VIS1.%X0 := NOT #logic1 AND #logic2;
   // ObjItem("poly01To02On").Visible = NOT logic1 AND NOT logic2
   #tempPanel.VIS1.%X1 := NOT #logic1 AND NOT #logic2;
   // ObjItem("poly1To2On").Visible = logic1 AND logic2
   #tempPanel.VIS1.%X2 := #logic1 AND #logic2;
   // ObjItem("poly1To0On").Visible = logic1 AND NOT logic2
   #tempPanel.VIS1.%X3 := #logic1 AND NOT #logic2;
   
   // ObjItem("lineInpOn_1").Visible = True
   //
   #tempPanel.VIS1.%X4 :=1;
   // ObjItem("ioTxtHMI1").Visible = NOT plcName(0)
   //
   #tempPanel.VIS1.%X5 := NOT #plcName[0];
   
   // ObjItem("ioTxtPLC1").Visible = plcName(0)
   //
   #tempPanel.VIS1.%X6 :=   #plcName[0];
   // ObjItem("lineInpOn_2").Visible = logic1
   //
   #tempPanel.VIS1.%X7 :=#logic1;
   // ObjItem("ioTxtHMI2").Visible = logic1 AND NOT plcName(1)
   //
   #tempPanel.VIS1.%X8 := #logic1 AND NOT #plcName[1]    ;
   
   // ObjItem("ioTxtPLC2").Visible = logic1 AND plcName(1)
   //
   #tempPanel.VIS1.%X9 :=#logic1 AND #plcName[1];
   
   END_REGION
   REGION ' show results inputs 2/3
       // #logic1 = arrLogic(1) > 0
       // logic2 = arrLogic(2) > 0
       // signalInputs = (CInt(CBool(status AND 2^9)))*(-1)
       // ObjItem("poly0To3On").Color = colorInput(signalInputs)
       // ObjItem("poly02To03On").Color = colorInput(signalInputs)
       // ObjItem("poly2To3On").Color = colorInput(signalInputs)
       // ObjItem("poly2To0On").Color = colorInput(signalInputs)
       // ObjItem("poly0To3On").Visible = NOT logic1 AND logic2
       // ObjItem("poly02To03On").Visible = NOT logic1 AND NOT logic2
       // ObjItem("poly2To3On").Visible = logic1 AND logic2
       // ObjItem("poly2To0On").Visible = logic1 AND NOT logic2
       // ObjItem("lineInpOn_3").Visible = logic1
       // ObjItem("ioTxtHMI3").Visible = logic1 AND NOT plcName(2)
       // ObjItem("ioTxtPLC3").Visible = logic1 AND plcName(2)
       
       #logic1 := (#tempLogics[1] > 0);
       #logic2 := (#tempLogics[2] > 0);
       // ObjItem("poly0To3On").Visible = NOT logic1 AND logic2
       //
       #tempPanel.VIS1.%X10 := NOT #logic1 AND #logic2;
       // ObjItem("poly02To03On").Visible = NOT logic1 AND NOT logic2
       //
       #tempPanel.VIS1.%X11 := NOT #logic1 AND NOT #logic2;
       // ObjItem("poly2To3On").Visible = logic1 AND logic2
       //
       #tempPanel.VIS1.%X12 := #logic1 AND #logic2;
       // ObjItem("poly2To0On").Visible = logic1 AND NOT logic2
       //
       #tempPanel.VIS1.%X13 := #logic1 AND NOT #logic2;
       
       // ObjItem("lineInpOn_3").Visible = logic1
       //
       #tempPanel.VIS1.%X14 := #logic1;
       
       // ObjItem("ioTxtHMI3").Visible = logic1 AND NOT plcName(2)
       //
       #tempPanel.VIS1.%X15 := #logic1 AND NOT #plcName[2];
       
       // ObjItem("ioTxtPLC3").Visible = logic1 AND plcName(2)      
       #tempPanel.VIS1.%X16 := #logic1 AND #plcName[2];
       
       
   END_REGION

   REGION ' show results inputs 3/4
   // Statement section REGION
   
   // ' show results inputs 3/4
   // logic1 = arrLogic(2) > 0
   // logic2 = arrLogic(3) > 0
   // signalInputs = (CInt(CBool(status AND 2^10)))*(-1)
   // ObjItem("poly0To4On").Color = colorInput(signalInputs)
   // ObjItem("poly03To04On").Color = colorInput(signalInputs)
   // ObjItem("poly3To4On").Color = colorInput(signalInputs)
   // ObjItem("poly3To0On").Color = colorInput(signalInputs)
   // ObjItem("poly0To4On").Visible = NOT logic1 AND logic2
   // ObjItem("poly03To04On").Visible = NOT logic1 AND NOT logic2
   // ObjItem("poly3To4On").Visible = logic1 AND logic2
   // ObjItem("poly3To0On").Visible = logic1 AND NOT logic2
   // ObjItem("lineInpOn_4").Visible = logic1
   // ObjItem("ioTxtHMI4").Visible = logic1 AND NOT plcName(3)
   // ObjItem("ioTxtPLC4").Visible = logic1 AND plcName(3)
   
       #logic1 := (#tempLogics[2] > 0);
       #logic2 := (#tempLogics[3] > 0);
       

       // ObjItem("poly0To4On").Visible = NOT logic1 AND logic2
       //
       #tempPanel.VIS1.%X17 := NOT #logic1 AND #logic2;
       // ObjItem("poly03To04On").Visible = NOT logic1 AND NOT logic2
       //
       #tempPanel.VIS1.%X18 := NOT #logic1 AND NOT #logic2;
       // ObjItem("poly3To4On").Visible = logic1 AND logic2
       //
       #tempPanel.VIS1.%X19 :=   #logic1 AND #logic2;
       // ObjItem("poly3To0On").Visible = logic1 AND NOT logic2
       //
       #tempPanel.VIS1.%X20 :=  #logic1 AND NOT #logic2;
       // ObjItem("lineInpOn_4").Visible = logic1
       //
       #tempPanel.VIS1.%X21 :=#logic1 ;
       // ObjItem("ioTxtHMI4").Visible = logic1 AND NOT plcName(3)
       //
       #tempPanel.VIS1.%X22 := #logic1 AND NOT #plcName[3];
       // ObjItem("ioTxtPLC4").Visible = logic1 AND plcName(3)
       //
       #tempPanel.VIS1.%X23 :=#logic1 AND #plcName[3];
       
       //
END_REGION

REGION   show results inputs 4/5
   // Statement section REGION
   // ' show results inputs 4/5
   // logic1 = arrLogic(3) > 0
   // logic2 = arrLogic(4) > 0
   // signalInputs = (CInt(CBool(status AND 2^11)))*(-1)
   // ObjItem("poly0To5On").Color = colorInput(signalInputs)
   // ObjItem("poly04To05On").Color = colorInput(signalInputs)
   // ObjItem("poly4To5On").Color = colorInput(signalInputs)
   // ObjItem("poly4To0On").Color = colorInput(signalInputs)
   // ObjItem("poly0To5On").Visible = NOT logic1 AND logic2
   // ObjItem("poly04To05On").Visible = NOT logic1 AND NOT logic2
   // ObjItem("poly4To5On").Visible = logic1 AND logic2
   // ObjItem("poly4To0On").Visible = logic1 AND NOT logic2
   // ObjItem("lineInpOn_5").Visible = logic1
   // ObjItem("ioTxtHMI5").Visible = logic1 AND NOT plcName(4)
   // ObjItem("ioTxtPLC5").Visible = logic1 AND plcName(4)
   #logic1 := (#tempLogics[3] > 0);
   #logic2 := (#tempLogics[4] > 0);
   // ObjItem("poly0To5On").Visible = NOT logic1 AND logic2
   //
   #tempPanel.VIS1.%X24 := NOT #logic1 AND #logic2;
   // ObjItem("poly04To05On").Visible = NOT logic1 AND NOT logic2
   //
   #tempPanel.VIS1.%X25 := NOT #logic1 AND NOT #logic2;
   // ObjItem("poly4To5On").Visible = logic1 AND logic2
   //
   #tempPanel.VIS1.%X26 := #logic1 AND #logic2;
   // ObjItem("poly4To0On").Visible = logic1 AND NOT logic2
   //
   #tempPanel.VIS1.%X27 := #logic1 AND NOT #logic2;
   // ObjItem("lineInpOn_5").Visible = logic1
   //
   #tempPanel.VIS1.%X28 :=#logic1;
   // ObjItem("ioTxtHMI5").Visible = logic1 AND NOT plcName(4)
   //
   #tempPanel.VIS1.%X29 := #logic1 AND NOT #plcName[4];
   // ObjItem("ioTxtPLC5").Visible = logic1 AND plcName(4)
   //
   #tempPanel.VIS1.%X30 :=#logic1 AND #plcName[4];
   

   
END_REGION

REGION ' show results inputs 5/6
   //
   // logic1 = arrLogic(4) > 0
   // logic2 = arrLogic(5) > 0
   // signalInputs = (CInt(CBool(status AND 2^12)))*(-1)
   // ObjItem("poly0To6On").Color = colorInput(signalInputs)
   // ObjItem("poly05To06On").Color = colorInput(signalInputs)
   // ObjItem("poly5To6On").Color = colorInput(signalInputs)
   // ObjItem("poly5To0On").Color = colorInput(signalInputs)
   // ObjItem("poly0To6On").Visible = NOT logic1 AND logic2
   // ObjItem("poly05To06On").Visible = NOT logic1 AND NOT logic2
   // ObjItem("poly5To6On").Visible = logic1 AND logic2
   // ObjItem("poly5To0On").Visible = logic1 AND NOT logic2
   // ObjItem("lineInpOn_6").Visible = logic1
   // ObjItem("ioTxtHMI6").Visible = logic1 AND NOT plcName(5)
   // ObjItem("ioTxtPLC6").Visible = logic1 AND plcName(5)
   #logic1 := (#tempLogics[4] > 0);
   #logic2 := (#tempLogics[5] > 0);
   
   // ObjItem("poly0To6On").Visible = NOT logic1 AND logic2
   //
   #tempPanel.VIS2.%X0 := NOT #logic1 AND #logic2;
   // ObjItem("poly05To06On").Visible = NOT logic1 AND NOT logic2
   //
   #tempPanel.VIS2.%X1 :=  NOT #logic1 AND NOT #logic2;
   // ObjItem("poly5To6On").Visible = logic1 AND logic2
   //
   #tempPanel.VIS2.%X2 := #logic1 AND #logic2;
   // ObjItem("poly5To0On").Visible = logic1 AND NOT logic2
   //
   #tempPanel.VIS2.%X3 := #logic1 AND NOT #logic2;
   // ObjItem("lineInpOn_6").Visible = logic1
   //
   #tempPanel.VIS2.%X4 :=#logic1;
   // ObjItem("ioTxtHMI6").Visible = logic1 AND NOT plcName(5)
   //
   #tempPanel.VIS2.%X5 :=#logic1 AND NOT #plcName[5];
   // ObjItem("ioTxtPLC6").Visible = logic1 AND plcName(5)  
   //
   #tempPanel.VIS2.%X6 := #logic1 AND #plcName[5];
   
END_REGION

REGION  ' show results inputs 6/7
       //
       // logic1 = arrLogic(5) > 0
       // logic2 = arrLogic(6) > 0
       // signalInputs = (CInt(CBool(status AND 2^13)))*(-1)
       // ObjItem("poly0To7On").Color = colorInput(signalInputs)
       // ObjItem("poly06To07On").Color = colorInput(signalInputs)
       // ObjItem("poly6To7On").Color = colorInput(signalInputs)
       // ObjItem("poly6To0On").Color = colorInput(signalInputs)
       // ObjItem("poly0To7On").Visible = NOT logic1 AND logic2
       // ObjItem("poly06To07On").Visible = NOT logic1 AND NOT logic2
       // ObjItem("poly6To7On").Visible = logic1 AND logic2
       // ObjItem("poly6To0On").Visible = logic1 AND NOT logic2
       // ObjItem("lineInpOn_7").Visible = logic1
       // ObjItem("ioTxtHMI7").Visible = logic1 AND NOT plcName(6)
       // ObjItem("ioTxtPLC7").Visible = logic1 AND plcName(6)
   #logic1 := (#tempLogics[5] > 0);
   #logic2 := (#tempLogics[6] > 0);
   // ObjItem("poly0To7On").Visible = NOT logic1 AND logic2
   //
   #tempPanel.VIS2.%X7 := NOT #logic1 AND #logic2;
   // ObjItem("poly06To07On").Visible = NOT logic1 AND NOT logic2
   //
   #tempPanel.VIS2.%X8 := NOT #logic1 AND NOT #logic2;
   // ObjItem("poly6To7On").Visible = logic1 AND logic2
   //
   #tempPanel.VIS2.%X9 :=  #logic1 AND #logic2;
   // ObjItem("poly6To0On").Visible = logic1 AND NOT logic2
   //
   #tempPanel.VIS2.%X10 := #logic1 AND NOT #logic2;
   // ObjItem("lineInpOn_7").Visible = logic1
   //
   #tempPanel.VIS2.%X11 := #logic1;
   // ObjItem("ioTxtHMI7").Visible = logic1 AND NOT plcName(6)
   //
   #tempPanel.VIS2.%X12 := #logic1 AND NOT #plcName[6];
   // ObjItem("ioTxtPLC7").Visible = logic1 AND plcName(6)
   //
   #tempPanel.VIS2.%X13 := #logic1 AND #plcName[6];
   
   END_REGION
   
   REGION ' show results inputs 7/8
   // ' show results inputs 7/8
   // logic1 = arrLogic(6) > 0
   // signalInputs = (CInt(CBool(status AND 2^14)))*(-1)
   // ObjItem("lineOutOn_1").Color = colorInput(signalInputs)
   // ObjItem("lineOutOn_2").Color = colorInput(signalInputs)
   // ObjItem("lineOutOn_1").Visible = logic1
   // ObjItem("lineOutOn_2").Visible = True
   // ObjItem("lineInpOn_8").Visible = logic1
   // ObjItem("ioTxtHMI8").Visible = logic1 AND NOT plcName(7)
   // ObjItem("ioTxtPLC8").Visible = logic1 AND plcName(7)
     
       #logic1 := (#tempLogics[6] > 0);
       // ObjItem("lineOutOn_1").Visible = logic1
       //
       #tempPanel.VIS2.%X14 := #logic1  ;
       // ObjItem("lineOutOn_2").Visible = True
       //
       #tempPanel.VIS2.%X15 :=  True;
       // ObjItem("lineInpOn_8").Visible = logic1
       //
       #tempPanel.VIS2.%X16 := #logic1 ;
       // ObjItem("ioTxtHMI8").Visible = logic1 AND NOT plcName(7)
       //
       #tempPanel.VIS2.%X17 := #logic1 AND NOT #plcName[7];
       // ObjItem("ioTxtPLC8").Visible = logic1 AND plcName(7)
       //
       #tempPanel.VIS2.%X18 :=#logic1 AND #plcName[7];
       
END_REGION

   
   REGION _name_
       #statDataIntlk8.VIS1 := #tempPanel.VIS1;
       #statDataIntlk8.VIS2 := #tempPanel.VIS2;
       
   END_REGION
   
   
END_REGION
程序中注释的部分是原本的触摸屏中的脚本,为了对照移植,我把源程序复制过来了!
然后,触摸屏画面中,每一根线条和画面元素,都增加了颜色切换和动态显示的动画功能,绑定增加的VIS变量的位。实现了同样的功能。

得益于LBP原作者的细心,每一根线条都有精心起的名字, 如poly0To7On,poly2To0On等,尽管我并没有完全读懂其名称含义,但在对照上面的程序基础上,还是很顺利实现了画面的改进。只要自己不粗心的错误,功能总可以完整复制的。 这就是移植,也同样是抄。

在完整实现功能后,把触摸屏降格为KTP,仍旧连接S7-1200,然后发现,KTP的画面中除了不支持脚本,不支持模板对象之外,还不支持多线!所以画面中的所有线条, 又重新用单线绘制。 原本的多线的显示条件,复制到多个线段。工作量之大,导致我都暗自抱怨,如果早发现其不支持单线,就不做这个块的移植了。但路走都走了,也还好没有项目工期压力,顶多多花点时间而已。

同样的在PLC程序中,也先在SMART 200中实现同样的逻辑,包括INTLK8完整的逻辑,解耦之后分为801和802。

也还好做了解耦,用2个块来实现,否则SMART 200的子程序块的管脚数量和内部TEMP变量全都不够用。 这样靠2个块,共同协作,才算完成了所有需要的功能。当然,前者801主要处理逻辑和状态位显示的计算。而802则是处理与多触摸屏的数据交换管理。
摘录一段801中的程序逻辑:

注释中我把从触摸屏到PORTAL的程序,又当作注释全部搬过来了,只为了方便抄和查错验证。

LBP原本的身份识别是在触摸屏上拼接字符完成的,比如对MTR-0001的连锁,则拼接成MTR-0001LockOn,PLC程序中相应的连锁对应这样的标识,由此实现了ID身份识别。而同样因为KTP不支持脚本功能,所以我又增加了EXT管脚,用于单独识别触摸屏数据管理。所以,即便是抄,也不是把脑子关上不动脑子就能抄成的。

INTLK块的名称虽然是为LOCK功能的,其实也还可以用于允许启动的功能。 即在LOCK的结果为1的时候,设备禁止启动,而倒过来当用于允许启动条件的时候,结果为1时,设备才允许启动,对应了MTR块的RELEASE管脚。我现在才明白这个管脚的功能含义。其实相当于我们国内行业常对应的备妥或者以前称作READY的管脚。

即,符合了我在标准化书和讲座中所要求的,设备的耦合逻辑要追求极致的简化,允许启动和互锁,需要分到不同的管脚中。 而不要因为取反的逻辑很简单,就混淆在一起。 烟台方法的学员们对这一点会理解更深刻。

在可视化界面上, LOCK和RELEASE需要的显示颜色是不同的。比如LOCK时颜色需要为黄色或者红色,而允许启动的颜色会是绿色。所以其库功能还包含了对颜色的选择设定。主要是由HMI脚本实现的。而这些如果同样增加到PLC程序中,导致PLC中变量数量激增,逻辑也更为复杂,所以暂时就做了功能简化。未来,需要的时候再另外想办法实现。 比如黄和绿两套颜色机制可以分在2套不同的画面中实现。

另外,库函数原始功能还包含了操作员的动态编程功能,可以在运行中修改逻辑和描述文本。也是出于PLC中资源限制的原因,做了删减。 我还是认为,显示的意义比操作要大多了。
 
由此,总结下移植(手抄)这个INTLK8块的实现路线:
1, S7-1200 + TP900
2, S7-1200 (加逻辑)   +  TP900(去逻辑)
3, S7-1200    +  TP900 单线条
4, S7-1200 + KTP900
5, SMART 200 + TP900
6, SMART 200 + KTP900
通过逐步实现, 逐步对照比较,发现其中的错误和疏忽,逐步修订,最终实现了想要的功能。 在移植过程中, 我甚至用两台电脑分别运行触摸屏仿真,分别监控S7-1200和SMART200, PLC之间的输入信号为了同步一致,还做了通讯,最终调试成功。

这个过程证明了,在未完全读懂原始逻辑的情况下通过渐进的每次仅一小步的移植,最终也可以实现功能移植。

虽然麻烦,总比自己从头规划设计一套完整的功能,要省力方便的多。

所以,哪怕迫不得已需要自己造轮子,也尽量参考已有的轮子。

这才是科技进步,这才是工业化。

附件:
[本地下载]
PLC标准化编程

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 非法和不良信息举报

工控网客服热线:0755-86369299
版权所有 工控网 Copyright©2024 Gkong.com, All Rights Reserved

78.0005