作者 | 主题 |
---|---|
万泉河 至圣 经验值:28599 发帖数:10824 精华帖:131 |
楼主 2016-02-02 21:34:44
主题:【万泉河】在WINCC中如何单击按钮发出一个脉冲信号? 【万泉河】在WINCC中如何单击按钮发出一个脉冲信号? 这个故事要分成三个部分来讲。 第一部分 大概2个月前, 有网友在论坛中提问, 如何做出点动一个按钮发出一个脉冲?这其实是个老掉牙的问题了,通常的解答, 或者说我们自己的处理方式有两种。 1,在按钮的按下和抬起事件中,分别编程, 按下时给目标变量置1,抬起时清0。这样操作人员的一次鼠标操作,就会产生一个脉冲送到了PLC中。 但是,由于人的操作按钮的时间非常短, 通常会在100ms左右。 熟练人员、游戏玩家,质量好的鼠标,甚至会低于50ms 。 如此短的脉冲, 在电脑的运行时间,网络通讯速度等各种条件影响下,就会经常发生命令丢失的情况。如果下位不是西门子PLC, 而是MODBUS等慢速通讯协议的设备,丢失的可能性就更大。这种指令丢失的结果,就会给操作人员造成的操作性差的印象。 由此, 我们通常在设计时尽量避免要WINCC发脉冲,而是第2种方法: 2,在需要指令操作的场合,尽量避免脉冲方式。 而是上位发出指令,下位收到指令后,由下位来复位这个指令。这样的好处是, 哪怕通讯的运行时间再长都不怕,都可以确保下位收到指令。 第二部分 说实话, 上述的两种方法, 各自都有些缺点, 都不如实实在在的给按照要求, 实现固定宽度的一个脉冲来得靠谱,比如我们能发出大约宽度5S的脉冲,时间精度可能不需要多准确,但只要宽度足够长,又可以自宗复位, 那下位PLC确实可以节省不少工作量。 所以, 那位网友的问题, 我在简单回答后的一段时间里,也进行了思考, 能不能用简单的方法在WINCC中实现呢?何为简单呢,就是不要复杂的编程, 尤其要充分集成,不能画面上做一些, 脚本中再做一些, 那样维护的成本太高,项目中如果几十处要用到,就要反复修改几十个地方,将来复用起来还很麻烦, 就没有什么意思。 最后的解决思路,是利用按钮的填充量的属性,这是一个0-100的数值,我假设代表0-10s好了: 1,在按钮时间中,给属性赋值50,代表5s 2,在填充量属性中, VBS编程如下: Function FillingIndex_Trigger(ByVal Item) If Item.FillingIndex>0 Then HMIRuntime.Tags("P").Write 1,1 Item.FillingIndex=Item.FillingIndex-10 If Item.FillingIndex<=0 Then HMIRuntime.Tags("P").Write 0 End If End If End Function 同时设定属性的触发器为1s。 这样就实现了发出脉冲的功能。 过程是:在按下以后赋值5S, 然后每过1S,属性脚本会触发一次,自动将填充量减10,直到为0,程序中判断如果大于0则置位变量, 如小于0则复位变量。 如果把按钮的动态填充打开, 则可以看到这个动态倒计时的过程。但是实际应用中会让人感到莫名其妙,所以还是不要打开动态填充吧。 项目中如果此类按钮多次用到, 那么只需复制按钮, 然后用替换变量链接的方法, 替换到新的要控制的变量,即可实现一个新的拷贝。 应用起来还是蛮简单吧? 第三部分 上述的实现方法, 其实还是存在一些弊端,或者不足之处: 1,删除的N字。 2,我设置的是5S,但实际运行中, PLC的脉冲有效时间总是4S,有人分析出原因在哪儿了吗? 3,这种把变量嵌入在脚本中的方式还是不太利于使用。如果能像WINCC库中的toggle button一样, 变量绑定到toggle属性,程序脚本中读取获取toggle绑定的变量来进行逻辑操作, 那么脚本就可以更集成化, 不再需要修改。 这样滴: 所以, 我决定跟看懂了的朋友们一起来玩个游戏:举办一次有奖的竞答活动,看谁能按照我的思路, 或者提供更好的思路,最好能修复我所提出的弊端, 做出一个自定义的库对象来,方便以后使用。 规则和流程如下: 1,使用WINCC 6.2 来做,控制的变量和我做的一样,叫做"P",方便我测试比较。 2,每位参赛选手加我微信178616417或加QQ群49122812,向我发10元报名费, 同时把你的投稿结果的PDL文件发给我。 3,我会在一个月后收集整理所有参赛者设计结果,选择其中的1位获胜者, 并把所有参赛者的奖金发给获胜者本人。我自己分文不取。 4,未获胜者的安慰奖便是获胜者的获奖作品。 所以参赛者参赛的同时,即意味着你放弃作品的版权。 春节期间学习充电一下,会是个相当愉快的经历! 祝大家春节快乐! 万泉河 (加我微信或QQ群的时候注明“我是西门子网站的XXX”,不参赛也可以添加,但不要当作答疑热线) 我把我前面做的按钮的画面作为附件传上来, 请大家参考。
微信公众号:PLC标准化编程,ZHO6371995
|
锋言锋语 至圣 经验值:23742 发帖数:3385 精华帖:52 |
2楼 2016-02-03 10:58:28
主题:回复:【万泉河】在WINCC中如何单击按钮发出一个脉冲信号?
全局脚本250ms: #define COUNT 5 #define WIDTH 5 //5s extern BOOL flag[COUNT]; extern time_t timeOri[COUNT]; extern const char* tags[COUNT]; int i =0; time_t ct = time(NULL); //current time (s); for(i = 0; i != COUNT; ++i) { if(flag[i]) { if(ct - timeOri[i] >= WIDTH) // width reached. { flag[i] = FALSE; SetTagBit(tags[i], 0); } } } return 0; } BOOL flag[COUNT]; time_t timeOri[COUNT]; const char* tags[COUNT] = { "tag1", "tag2", "tag3", "tag4", "tag5"}; 按钮脚本: #define TAG "tag1" #define COUNT 5 #define WIDTH 5 //5s extern BOOL flag[COUNT]; extern time_t timeOri[COUNT]; extern const char* tags[COUNT]; int i = FindIndex(TAG); if(-1 == i) else { SetTagBit(TAG, 1); flag[i] = TRUE; timeOri[i] = time(NULL); } 项目函数FindIndex如下: #pragma option(mbcs) int FindIndex(const char* p) { #define COUNT 5 extern const char* tags[COUNT]; int i = 0; for(i = 0; i != COUNT; ++i) { if(!strcmp(p, tags[i])) { return i; } } return -1; } 好了, COUNT,和 Width可以做到头文件里, 就不用没处都声明了, 也可以做成全局变量, 这些工作自己搞吧。 以上的思路, 使用时, 只写一次代码, 然后通过变量连接替换变量即可。
不忘初心
|