使用SCL实现一个算法来实现简单优先级
前言
大家好啊!今天我们一起用SCL语言来实现一个算法——简单优先级;使用场景是在<三层电梯>试验中;这里会结合着西门子的触摸屏来实现,可以看的更加直观一些!
一、场景需求
在我们实现三层电梯的运动控制时,主要有两个问题 :一是怎么才能记录所按下的按钮,然后根据所按下的按钮依次执行上升或下降;二是在上升或下降时怎么实现先执行距离当前位置最近的楼层,例:电梯在一层时,4层先被按下然后3层2层被按下,在进行上升的过程中,我们希望电梯先到达2层再到达3层最后再去4层,从高层下降到低层时也是一样。
这里按钮的优先级是先考虑的电梯内部按钮(主要实现也是内部,外部因为有上和下,先暂时不考虑) ,下面我们来实现一下这两个主要需求。
1.记录所有按下的按钮,然后执行
这里我们可以代入平时坐电梯时的基本运行:在电梯内有很多个按钮被按下,然后电梯按照一定规律进行上升下降,直到走完所有被按下的楼层(或没有按钮被按下了)。
那么问题来了,如何记录被按下的按钮,这里我的方法是:每个按钮被按下都让它有一个数值(代表被按下),再把数值存放起来,然后让电梯一个一个的执行;
具体实现就是:按钮按下给数组传一个值,在使用时我们遍历这个数组,然后再执行;
SCL代码段:
按下按钮传入不同的值到数组中;
//获取按钮上升沿
#PR[0](CLK := #S1);
#PR[1](CLK := #S2);
#PR[2](CLK := #S3);
#PR[3](CLK := #SU1);
#PR[4](CLK := #SU2);
#PR[5](CLK := #SD2);
#PR[6](CLK := #SD3);
//传入数值到数组
IF #PR[0].Q THEN
"数据块_1".#SZ[1] := 1;
ELSIF #PR[1].Q THEN
"数据块_1".#SZ[2] := 1;
ELSIF #PR[2].Q THEN
"数据块_1".#SZ[3] := 1;
ELSIF #PR[3].Q THEN
"数据块_1".#SZ[4] := 1;
ELSIF #PR[4].Q THEN
"数据块_1".#SZ[5] := 1;
ELSIF #PR[5].Q THEN
"数据块_1".#SZ[6] := 1;
ELSIF #PR[6].Q THEN
"数据块_1".#SZ[7] := 1;
END_IF;
在这里进行判断,找到一个不等于0的,然后执行;
//判断条件
IF #I = 0 THEN
FOR "数据块_1".W := 1 TO 7 DO //执行循环
IF "数据块_1".SZ["数据块_1".W] <> 0 THEN //判断哪一个<>0,将当前第几个传给变量,下
// 面变量再执行
"数据块_1".T := "数据块_1".W;
#I := 1; //找到后退出
EXIT;
END_IF;
END_FOR;
END_IF;
触摸屏效果:这样就实现了记录的功能。
二、简单优先级
可以进行按钮记录后,我们要来完成简单优先级设置,上升时要优先去最近的楼层,下降是优先先下降到最近的楼层
1.下降优先
按钮传值和上面相同,这里我们着重看for循环;这里把数组的类型改成了bool型,不是0就是1;
FOR "数据块_1".W := 1 TO 8 DO //执行循环
IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
"数据块_1".T := "数据块_1".W;
END_IF;
END_FOR;
效果:
这里会优先找到最大的楼层,如果按钮1,2,3,4,5被短时按下,将会执行最高的楼层5,到达楼层后再执行楼层4,然后3,2,1;符合我们的下降优先要求!
执行流程:
FOR "数据块_1".W := 1 TO 8 DO //执行循环
IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
"数据块_1".T := "数据块_1".W;
END_IF;END_FOR;
上电后,for循环开始运行,变量W从1到8来遍历整个数组,如果其中一个按钮被按下,就将数组下标(第几个)传给一个变量,然后再执行程序;如果1,2,3被按下,那么2会覆盖掉1,3会覆盖掉2,最后输出结果就是3;如果有比3大的被按下,3就被覆盖掉了,然后执行最大的;最大的执行完成后,就会找到另一个数组里面最大的,再执行;
程序运行原理:
工作流程知道后,下面就是它为什么一直这样执行?大的为什么能够覆盖掉小的?小的为真时为什么无法覆盖掉大的呢?
第一:它为什么能一直这样执行?
这样执行是和PLC的工作过程有关 ,PLC的工作过程是一个不断循环扫描的过程,cpu从第1条指令开始,按顺序逐条的执行用户程序直到程序结束,然后返回第一条指令,开始新的一轮扫描;每次扫描的过程有:输入采样、程序执行、输出刷新。所以,for循环从1到8循环1次后,会再次的进行循环。
第二:大的为什么能覆盖小的?
for 循环从1到8开始遍历数组,我们假设5楼按钮按下,SZ【5】为TRUE,在循环到5的时候,条件成立;在这时按下4,输出结果仍为5,而不是4;因为4的后面还有5,5是最后一个,也就是最后输出的结果,运行后输出的始终是最后一个,因为它是1,2,3,4,5,6,7顺序来循环的。
第三:小的为什么不能覆盖大的?
理解上面的运行原理后,就知道了;因为它最后的输出结果是最后一个,小的在前面不在后面,所以无法覆盖。
2.上升优先
上升优先要实现只需要和下降优先相反就可以啦!
这里让for循环从8开始然后循环到1,就好了。
FOR "数据块_1".W := 8 TO 1 BY -1 DO //执行循环
IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
"数据块_1".T := "数据块_1".W;
END_IF;
END_FOR;
效果:
总结
以上就是今天的所有内容啦!再见!