【SCL】for循环指令的应用&三层电梯模拟控制

使用scl编写三层电梯模拟控制,并学习for循环指令的应用。

文章目录

目录

文章目录

前言

1.指令学习

 2.循环传值

3.嵌套调用

4.冒泡排序

1.排序

 2.优化

二、三层电梯模拟控制

1.控制要求

2.编写思路

3.功能块部分编程

1.开门关门块

 2.去1层2层3层的块

 3.主程序部分

4.for循环部分(优先级) 

1.上升优先 

 2.下降优先

 3.等于楼层时

5. 完善程序

 1.上升下降互锁

 2.楼层限位判断

 3.启动停止

6.主程序(完整)

总结





前言

本章我们一起来完成12个小项目试验中的最后一个——三层电梯模拟控制;并通过本章来学习一下for循环指令的应用,其中包括:循环传值,嵌套调用,冒泡排序,和编写电梯的思路和方法。好的,下面我们进入今天的内容!


一、for循环指令

在前面的指令篇中,我们有提到过,但具体的使用没有说,这里我们来学习一下。 

1.指令学习

 关于for循环,它需要有明确的循环次数,下面第一个参数是一个变量的起始值,第2个是结束值,第3个是步宽(不使用默认是1,一次走一个,如果是2就是一次走两个),for循环中是执行内容。

【SCL】for循环指令的应用&三层电梯模拟控制

 下面是博图中关于for循环的说明:

【SCL】for循环指令的应用&三层电梯模拟控制

【SCL】for循环指令的应用&三层电梯模拟控制

【SCL】for循环指令的应用&三层电梯模拟控制

【SCL】for循环指令的应用&三层电梯模拟控制


 2.循环传值

 这里简单使用for通过一个数组来对另一个数组进行传值:

建立两个数组和整型变量,在for循环中先确定变量的初始值,这里从0开始到5结束和数组的个数相同(如果变量超过数组个数,会导致溢出报错);by是1,一次一个(这里不用by也可以,默认是1);内容执行程序就是获取两个数组的下标然后进行传值。 

【SCL】for循环指令的应用&三层电梯模拟控制

 效果:

【SCL】for循环指令的应用&三层电梯模拟控制


3.嵌套调用

 for循环也可以嵌套调用,简单示范的话,这里我们可以给一个二维数组进行传值;二维数组有两个参数或者叫坐标,可以看下图:

【SCL】for循环指令的应用&三层电梯模拟控制

这里我们给二维数组传参数,就建立两个二维数组 ,中间用,号隔开;建立两个整型变量。

【SCL】for循环指令的应用&三层电梯模拟控制

 这里循环内部就是将变量w和t放在数组中,让他们不断变化,例:第一次的w为0,进入第2个for循环中,t从0循环到5,然后跳出,再走到第1个循环w为2,然后再次进入第2个循环;这样就将二维数组0到5,1到5,2到5,3到5等,全部走一遍。【SCL】for循环指令的应用&三层电梯模拟控制

 
效果:

【SCL】for循环指令的应用&三层电梯模拟控制


4.冒泡排序

1.排序

知道for循环如何使用后,这里我们可以来看一下冒泡排序;它是一个排序方法,可以看下360百科中的解释:

【SCL】for循环指令的应用&三层电梯模拟控制

 算法原理:

【SCL】for循环指令的应用&三层电梯模拟控制

【SCL】for循环指令的应用&三层电梯模拟控制


知道原理后,我们来用SCL中for循环来实现一下: 

 我们建立1个数组,来存放排序过的排序值;再建立一些变量;这里我们初始变量为0;

len是我们的总个数(像0..5,就有6个数),总个数-1就是下标的值;进入循环后,将第1个数据和第2个数据进行比较,如果第1个数据大于第2个数据,就将它们两个交换一下,然后一直循环直到结束,那么排序就完成了。

【SCL】for循环指令的应用&三层电梯模拟控制

这里我们提前写好数组里面的起始值,然后再执行; 

【SCL】for循环指令的应用&三层电梯模拟控制

 效果:

【SCL】for循环指令的应用&三层电梯模拟控制

 2.优化

上面我们是提前写好起始值,然后进行排序的,我们这里也可以做两个数组,一个在运行时让我们输入初始值,另一个在运行时输出排序值;另外第2个循环也可以优化一下,每次让它-j,因为排序是有重复比较的,我们每次-j可以优化掉这一点;

在这个前面使用了一个peek指令,读取存储地址,然后放入到排序数组进行排序;注意:使用peek要取消块的优化,下面的np_temp是获取偏移地址的。

【SCL】for循环指令的应用&三层电梯模拟控制

 效果:

【SCL】for循环指令的应用&三层电梯模拟控制









二、三层电梯模拟控制

前面简单学习回顾一下for循环指令,接下来我们一起来看三层电梯的控制。

1.控制要求

 控制要求可以简单看一下,主要就是三个楼层来回切换上升或下降;

【SCL】for循环指令的应用&三层电梯模拟控制

 电梯参考:

 【SCL】for循环指令的应用&三层电梯模拟控制


2.编写思路

编写思路这里大家可以想一想平时的电梯都是如何工作的,其实简单的上升下降是比较好控制的,再加一个开门关门就差不多可以实现简单功能了,但是SCL写的话要用比较多的if来判断,这里我们的 上升,下降,开门关门,还有每个楼层外的按钮和电梯内的按钮这些可以都做成一个块,在使用时多次调用就可以,那么一个简单的电梯控制就差不多了,后面我们要根据电梯实际运行时的一个状态,再加一些控制,像简单的优先级,先去2层再去3层等等。


3.功能块部分编程

编程思路确定后,下面来编写具体的程序,这里我们先将多次需要使用的功能写在一个块里,将开关门做一个块,去1层2层3层做成块,最后在一个主的程序中将它们联系起来,来完成控制要求。

这里是用的FB块,建立的形参 ;

【SCL】for循环指令的应用&三层电梯模拟控制

1.开门关门块

这里的要求就是,延时1s开门,延时2s关门,我们来编写一下:

变量m不等于0是触发条件,我们要执行开关门时只要让m不等0就可以了;变量HH是正在开门关门的一个标志位,开关门时不能进行其他操作; 

#T[0].TON(IN := #BZ1,
          PT := t#1s);
#T[1].TON(IN := #BZ2,
          PT := t#2s);
#T[2].TON(IN := #BZ3,
          PT := T#2s);

IF "电梯_DB".M  0 THEN
    #HH := 1;
    #BZ1 := 1;
    //"电梯_DB".CLOSE := 0;
    IF #T[0].Q THEN
        "电梯_DB".OPEN := 1;
        #BZ2 := 1;
    END_IF;
    IF #T[1].Q THEN
        "电梯_DB".OPEN := 0;
        "电梯_DB".CLOSE := 1;
        #BZ3 := 1;
    END_IF;
    IF #T[2].Q THEN
        "电梯_DB".CLOSE := 0;
        #BZ1 := 0;
        #BZ2 := 0;
        #BZ3 := 0;
        "电梯_DB".M := 0;
   
        RESET_TIMER(#T[0]);
        RESET_TIMER(#T[1]);
        RESET_TIMER(#T[2]);
        #HH := 0;
        "数据块_1"."SZ"["数据块_1".T] := 0;
        "数据块_1".T := 0;
        "数据块_1".W := 0;
        "电梯_DB".I := 0;
        "电梯_DB".Q := 0;
        "电梯_DB".O := 0;
 
    END_IF;
END_IF;

 2.去1层2层3层的块

这里我将这个块,分成了3个来写,方便后面调试或者完善; 

【SCL】for循环指令的应用&三层电梯模拟控制

 去1层:(在2层或3层按下1层按钮时会触发)

这里就很简单了,A=1的时候,电梯下降 ,到达1层后给m赋值,执行开门关门,这里&上了一个开关门的一个标志位,代表开关门时无法执行去1层(后面的2层3层也一样)

//电梯去1层
#P[0](CLK := "电梯_DB".SQ1);
IF "电梯_DB".A = 1 & NOT "电梯_DB".BZ1 & NOT "开关门_DB".HH  & "电梯_DB".C = 0 THEN
    "电梯_DB".DOWN := 1;
    IF #P[0].Q THEN
        "电梯_DB".DOWN := 0;
        "电梯_DB".M := 4;
        "电梯_DB".A := 0;
    END_IF;
END_IF;

去2层:(去2层有两种情况,在3层会下降,在1层会上升)

 当b=1执行上升,当b1=2执行下降,到达楼层后停止;

//电梯去往2层
#P[1](CLK := "电梯_DB".SQ2);
IF "电梯_DB".B = 1 & NOT "电梯_DB".BZ2 & NOT "开关门_DB".HH THEN
    "电梯_DB".UP := 1;
ELSIF "电梯_DB".B1 = 2 & NOT "电梯_DB".BZ1 & NOT "开关门_DB".HH THEN
    "电梯_DB".DOWN := 1;
END_IF;
IF #P[1].Q & "电梯_DB".B = 1 THEN
    "电梯_DB".UP := 0;
    "电梯_DB".K := 1;
    "电梯_DB".B := 0;
    "电梯_DB".M := 2;
 
ELSIF #P[1].Q & "电梯_DB".B1 = 2 THEN
    "电梯_DB".DOWN := 0;
    "电梯_DB".K := 1;
    "电梯_DB".B1 := 0;
    "电梯_DB".M := 3;

END_IF;

 去3层:(去3层是上升,不管是1层还是2层呼叫,都会上升)

 这里和去1层基本相同;

//电梯去3层
#P[0](CLK := "电梯_DB".SQ3);
IF "电梯_DB".C = 1 & NOT "电梯_DB".BZ2 & NOT "开关门_DB".HH & "电梯_DB".O=0 THEN
    "电梯_DB".UP := 1;
    IF #P[0].Q THEN
        "电梯_DB".UP := 0;
        "电梯_DB".M := 3;
        "电梯_DB".C := 0;
    END_IF;
END_IF;

 3.主程序部分

 前面两个块好后,我们可以在主程序块中编写一下,让它们执行相应的动作:

 开始先调用一下我们的函数块,后面用3个楼层限位来触发3个楼层标志,再根据楼层标志来触发条件执行相应的的楼层;

    
    "开关门_DB"();   //开关门函数块
 
        "去1层_DB"();//楼层函数块
        "去2层_DB"();
        "去3层_DB"();
    
    // 用3个楼层限位的通和断,来接通或断开中继和楼层指示灯;
    // 是对三个楼层的限位进行控制。
    IF #SQ1 THEN
        #ZJ[1] := 1;
        #ZJ[2] := 0;
        #ZJ[3] := 0;
        #L1 := 1;
        "数据块_1".U := 1;
    ELSE
        #ZJ[1] := 0;
        #L1 := 0;
    END_IF;
    IF #SQ2 THEN
        #ZJ[2] := 1;
        #ZJ[3] := 0;
        #ZJ[1] := 0;
        #L2 := 1;
        "数据块_1".U := 2;
    ELSE
        #ZJ[2] := 0;
        #L2 := 0;
    END_IF;
    IF #SQ3 THEN
        #ZJ[3] := 1;
        #ZJ[2] := 0;
        #ZJ[1] := 0;
        #L3 := 1;
        "数据块_1".U := 3;
    ELSE
        #ZJ[3] := 0;
        #L3 := 0;
    END_IF;
    
    //在运行时进行互锁,上升时不能下降,下降时不能上升
    IF #UP = 1 THEN
        #BZ1 := 1;
    ELSE
        #BZ1 := 0;
    END_IF;
    IF #DOWN = 1 THEN
        #BZ2 := 1;
    ELSE
        #BZ2 := 0;
    END_IF;
    //获取按钮上升沿
    #P[0](CLK := #SQ1);
    #P[1](CLK := #SQ2);
    #P[2](CLK := #SQ3);
    
    #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);





 这里就是楼层执行部分,在1层按下1楼按钮后,执行开门关门,如果按下2层3层按钮就执行我们的去2层去3层的块。

//一层执行
    IF #ZJ[1] THEN
        IF "数据块_1".T = 1 THEN
            #M := 1;
        END_IF;
        IF "数据块_1".T = 2 THEN
            #O := 1;
            #B := 1;
        END_IF;
        IF "数据块_1".T = 3 THEN
            #C := 1;
        END_IF;
        
    END_IF;
    //二层执行
    IF #ZJ[2] THEN
        IF "数据块_1".T = 2 THEN
            #M := 1;
        END_IF;
        IF "数据块_1".T = 1 THEN
            #A := 1;
        END_IF;
        IF "数据块_1".T = 3 THEN
            #C := 1;
        END_IF;
    END_IF;
    //三层执行
    IF #ZJ[3] THEN
        IF "数据块_1".T = 3 THEN
            #M := 1;
        END_IF;
        IF "数据块_1".T = 1 THEN
            #A := 1;
        END_IF;
        IF "数据块_1".T = 2 THEN
            #B1 := 2;
        END_IF;
    END_IF;

4.for循环部分(优先级) 

1.上升优先 

 在电梯执行时,如果在1层按下3 2 1 内部按钮,那么要优先执行距离1层最近的楼层,这里就用到for循环:在循环数组时,执行3,2,1,进行循环,如果按下3再按下2,那么2会将3覆盖掉;我们再判断一下它是否大于当前楼层,如果是就将找到的最小楼层给变量T,然后再执行楼层;

 //上升优先级(后按下的按钮会覆盖掉前面的)
    FOR "数据块_1".W := 3 TO 1 BY -1 DO
        IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
            IF "数据块_1".W > "数据块_1".U THEN
                "数据块_1".T := "数据块_1".W;
            END_IF;
        END_IF;
    END_FOR;

 2.下降优先

 这里和上升优先相反,是从1到3,依次执行,然后判断是否小于当前楼层,如果是就执行;

 //下降优先级
    FOR "数据块_1".W := 1 TO 3 BY 1 DO
        IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
            IF "数据块_1".W < "数据块_1".U THEN
                "数据块_1".T := "数据块_1".W;
            END_IF;
        END_IF;
    END_FOR;

 3.等于楼层时

在等于楼层时,再执行这一种情况; 

 //等于当前楼层时进行判断
        FOR "数据块_1".W := 1 TO 3 BY 1 DO
            IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
                IF "数据块_1".W = "数据块_1".U THEN
                    "数据块_1".T := "数据块_1".W;
                END_IF;
            END_IF;
        END_FOR;

5. 完善程序

这里基本功能和简单优先级都可以实现了,我们再将各部分程序完善一下 ;

 1.上升下降互锁

在上面的楼层部分加上BZ1或BZ2的常闭,就可以了。 

 //在运行时进行互锁,上升时不能下降,下降时不能上升
    IF #UP = 1 THEN
        #BZ1 := 1;
    ELSE
        #BZ1 := 0;
    END_IF;
    IF #DOWN = 1 THEN
        #BZ2 := 1;
    ELSE
        #BZ2 := 0;
    END_IF;

 2.楼层限位判断

 判断是否有多个限位被触发,如果有就停止所有动作;

//判断是否有两个或两个以上的限位被触发,如果有就停止当前所有动作
IF (#SQ1 & #SQ2) OR (#SQ1 & #SQ3) OR (#SQ2 & #SQ3 OR #SQ1 & #SQ2 & #SQ3) THEN
    #BJ100 := 1;
    #L1 := 0;
    #L2 := 0;
    #L3 := 0;
ELSE
    #BJ100 := 0;
END_IF;

 3.启动停止

//停止,按下后运行完当前楼层后停止,按下停止后再按楼层呼叫按钮就无效了
IF #OFF THEN
    #TZ100 := 1;
END_IF;
//按下启动后,按钮恢复初始状态
IF #ON THEN
    #TZ100 := 0;
END_IF;

6.主程序(完整)

 这里还加了一个按下按钮后延时2s后再执行的定时器,主要是在多个按钮按下时有足够的时间来进行一个优先级判断,然后执行。

//判断是否有两个或两个以上的限位被触发,如果有就停止当前所有动作
IF (#SQ1 & #SQ2) OR (#SQ1 & #SQ3) OR (#SQ2 & #SQ3 OR #SQ1 & #SQ2 & #SQ3) THEN
    #BJ100 := 1;
    #L1 := 0;
    #L2 := 0;
    #L3 := 0;
ELSE
    #BJ100 := 0;
END_IF;
//停止,按下后运行完当前楼层后停止,按下停止后再按楼层呼叫按钮就无效了
IF #OFF THEN
    #TZ100 := 1;
END_IF;
//按下启动后,按钮恢复初始状态
IF #ON THEN
    #TZ100 := 0;
END_IF;

IF NOT #BJ100 THEN//多个限位按下就停止
    
    "开关门_DB"();   //开关门函数块
    IF #T[5].Q THEN  //启动延时时间
        "去1层_DB"();//楼层函数块
        "去2层_DB"();
        "去3层_DB"();
    END_IF;
    //启动延时
    #T[5].TON(IN := #BZ5,
              PT := T#2s);
    //当按钮全部复位后,标志位清零
    IF "数据块_1".SZ[1] = "数据块_1".SZ[2] & "数据块_1".SZ[2] = "数据块_1".SZ[3] & "数据块_1".SZ[3] = 0 THEN
        #BZ5 := 0;
    END_IF;
    
    // 用3个楼层限位的通和断,来接通或断开中继和楼层指示灯;
    // 是对三个楼层的限位进行控制。
    IF #SQ1 THEN
        #ZJ[1] := 1;
        #ZJ[2] := 0;
        #ZJ[3] := 0;
        #L1 := 1;
        "数据块_1".U := 1;
    ELSE
        #ZJ[1] := 0;
        #L1 := 0;
    END_IF;
    IF #SQ2 THEN
        #ZJ[2] := 1;
        #ZJ[3] := 0;
        #ZJ[1] := 0;
        #L2 := 1;
        "数据块_1".U := 2;
    ELSE
        #ZJ[2] := 0;
        #L2 := 0;
    END_IF;
    IF #SQ3 THEN
        #ZJ[3] := 1;
        #ZJ[2] := 0;
        #ZJ[1] := 0;
        #L3 := 1;
        "数据块_1".U := 3;
    ELSE
        #ZJ[3] := 0;
        #L3 := 0;
    END_IF;
    
    //在运行时进行互锁,上升时不能下降,下降时不能上升
    IF #UP = 1 THEN
        #BZ1 := 1;
    ELSE
        #BZ1 := 0;
    END_IF;
    IF #DOWN = 1 THEN
        #BZ2 := 1;
    ELSE
        #BZ2 := 0;
    END_IF;
    //获取按钮上升沿
    #P[0](CLK := #SQ1);
    #P[1](CLK := #SQ2);
    #P[2](CLK := #SQ3);
    
    #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 NOT #TZ100 THEN //按下停止后按钮无效
        //根据按下的按钮传入相应的数值,然后启动bz5进行延时(目的是判断是否还有其它按钮按下,如果有在延时时间
        //内进行排序,走离自己比较近的楼层
        IF #PR[0].Q OR #PR[3].Q THEN
            "数据块_1".#"SZ"[1] := 1;
            #BZ5 := 1;
        ELSIF #PR[1].Q OR #PR[4].Q OR #PR[5].Q THEN
            "数据块_1".#"SZ"[2] := 1;
            #BZ5 := 1;
        ELSIF #PR[2].Q OR #PR[6].Q THEN
            "数据块_1".#"SZ"[3] := 1;
            #BZ5 := 1;
        END_IF;
    END_IF;
    //获取数组中的按钮值,进行判断
    //上升优先级(后按下的按钮会覆盖掉前面的)
    FOR "数据块_1".W := 3 TO 1 BY -1 DO
        IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
            IF "数据块_1".W > "数据块_1".U THEN
                "数据块_1".T := "数据块_1".W;
            END_IF;
        END_IF;
    END_FOR;
    //下降优先级
    FOR "数据块_1".W := 1 TO 3 BY 1 DO
        IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
            IF "数据块_1".W < "数据块_1".U THEN
                "数据块_1".T := "数据块_1".W;
            END_IF;
        END_IF;
    END_FOR;
    //等于当前楼层时进行判断
    IF NOT #BZ1 & NOT #BZ2 THEN
        FOR "数据块_1".W := 1 TO 3 BY 1 DO
            IF "数据块_1".SZ["数据块_1".W] = TRUE THEN
                IF "数据块_1".W = "数据块_1".U THEN
                    "数据块_1".T := "数据块_1".W;
                END_IF;
            END_IF;
        END_FOR;
    END_IF;
    
    //一层执行
    IF #ZJ[1] THEN
        IF "数据块_1".T = 1 THEN
            #M := 1;
        END_IF;
        IF "数据块_1".T = 2 THEN
            #O := 1;
            #B := 1;
        END_IF;
        IF "数据块_1".T = 3 THEN
            #C := 1;
        END_IF;
        
    END_IF;
    //二层执行
    IF #ZJ[2] THEN
        IF "数据块_1".T = 2 THEN
            #M := 1;
        END_IF;
        IF "数据块_1".T = 1 THEN
            #A := 1;
        END_IF;
        IF "数据块_1".T = 3 THEN
            #C := 1;
        END_IF;
    END_IF;
    //三层执行
    IF #ZJ[3] THEN
        IF "数据块_1".T = 3 THEN
            #M := 1;
        END_IF;
        IF "数据块_1".T = 1 THEN
            #A := 1;
        END_IF;
        IF "数据块_1".T = 2 THEN
            #B1 := 2;
        END_IF;
    END_IF;
END_IF;





总结

上面就是for循环和最后一个项目三层电梯的所有内容了!

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/b0d3bd2e12.html