zl程序教程

您现在的位置是:首页 >  APP

当前栏目

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

2023-04-18 14:16:04 时间

使用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循环中是执行内容。

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


 2.循环传值

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

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

 效果:


3.嵌套调用

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

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

 这里循环内部就是将变量w和t放在数组中,让他们不断变化,例:第一次的w为0,进入第2个for循环中,t从0循环到5,然后跳出,再走到第1个循环w为2,然后再次进入第2个循环;这样就将二维数组0到5,1到5,2到5,3到5等,全部走一遍。

 
效果:


4.冒泡排序

1.排序

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

 算法原理:


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

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

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

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

 效果:

 2.优化

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

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

 效果:









二、三层电梯模拟控制

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

1.控制要求

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

 电梯参考:

 


2.编写思路

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


3.功能块部分编程

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

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

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个来写,方便后面调试或者完善; 

 去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循环和最后一个项目三层电梯的所有内容了!