一、概述
不知道大家在做上位机控制电机启停的时候,一般都用什么方法去写数据给PLC。比如:
1、 WINCC写一个位发给PLC,PLC接收到这个位,电机启动,PLC复位这个位。停止也是如此。
2、 WINCC在左键按下动作中写一个位发给PLC,PLC接收到这个位,电机启动,WINCC在左键释放动作中复位这个位。
以上,我比较倾向于第一种,所以在S7-200、300、400、1200、1500中一向如此使用。也就是上位机发1信号,PLC内复位此信号,也一直正常使用。直到最近做了一个项目,用到了1500,在使用过程,WINCC偶尔启动或停止电机时,要给好几次命令。
该来的还是来了,早就知道在400、1500中使用这种方式会有一定的概率会出现写入不成功的情况,此问题,在SIEMENS赵欣老师《PLC通信原理探秘系列》中有专门介绍过。就是上位机跟 PLC通讯是时间片TS和CCP的问题。
- S7-300是基于CCP
- S7-400/1500是基于时间片
如图:

二、发现问题
1. 情况说明
我的问题跟这种情况差不多,做了个电机块,在INOUT接口做了个控制字,主要是用作启动、停止、手动、自动。WINCC做了面板,对应这个控制字。如图:S7-400中的块

在块中定义INOUT接口,把这个控制字赋给临时变量,通过临时变量做一些逻辑处理,再把0写回到控制字,做复位

复位控制字,写入0

在S7-400中一直这么使用,有十几年了,一直没出现过问题,看了下扫描周期,在十几ms左右。直到最近在1500的一个项目上使用,出现了不能每次都能写入到PLC的情况。后来想想,应该跟扫描周期的快慢也有关系。扫描周期快了,出现问题的概率就小。

2.问题点
1、上面的程序,如果上位机写过来的数据,刚好在NW3之后,NW12之前,那么,控制字会通过INOUT接口,直接写回数据0,#ON_CMD就不会置位。
2、如果在NW12之后给数据过来,此数据也不会保留到下一个周期,重头再赋给控制字,因为FB调用结束后,会把现在的值0通过INOUT接口写回到实参。
三、解决问题
既然INOUT接口会在块调用之后写回数据,也就是在一个周期内,数据被改写了。那能不能像CCP方式一样,把数据保持到下个周期,这样就解决问题了。
解决方案:
1、 使用IN接口,这样实参不会被改写
2、 IN 接口使用POINT指针
实际方式就是通过指针,把实参的数据复制给临时变量,判断临时变量的数据是否为0,如果为0,那么就是实际数据没有接收到,不复位实参。如果临时变量不为0 ,说明接收到了数据,复位实参。

数据清零

四、测试
在NW30之前,增加的循环,保证WINCC给过来的数据大概率是在这个位置。扫描周期也增加到了58ms。测试下来正常,问题解决。


五、1500的解决方案
1500也跟 S7-400一样,改成IN接口。但是,S7-400可以通过指针来触决,那么1500没有指针,只有Variant,不太好处理。
这时,又想到了赵老师讲过的《从S7-300_400到S7-1500看变址寻址的改变-连载》系列,其中提到了引用(References)寻址。感觉有戏,经过一翻研究,完善解决问题。
1.在IN接口中定义接口为引用

2.解引用

测试::
在MW13前增加循环,保证大概率上位机写过来的数据会在此

这里说下引用,使用下来,有点像400中的POINT指针。在400中,要对指针进行数据解偶。1500中,直接使用引用,不用管内部结构,比较方便。