Siemens PLC 程序解读 车型指针

1、代码

REGION 初始化值和确认状态
    FOR #I := 1 TO 32 DO
        #ST_Type[#I] := #EmptyType;
        #ST_CS[#I] := #EmptyCS;
    END_FOR;
    FOR #I := 1 TO 64 DO
        #RBT_Type[#I] := #EmptyType;
        #RBT_CS[#I] := #EmptyCS;
    END_FOR;
    //初始化工位和机器人的车型和状态
    
    IF #CFG_STNum < 0 OR #CFG_STNum > 32 OR #CFG_RbtNum < 0 OR #CFG_RbtNum > 64 THEN
        #Err := 1;
        GOTO Lable1 ;//工位和机器人数量设置超限
    END_IF;
    IF #CFG_MAX_P <= 0 OR #CFG_MAX_P >= 99  THEN
        #CFG_MAX_P := #CFG_STNum * 2
        ;
    END_IF;//最大指针数默认为工位数的两倍
    IF #CFG_STNum>0 THEN
        FOR #I := 1 TO #CFG_STNum DO
            IF #HMI.ST_P[#I] = 0 THEN
                #HMI.ST_P[#I] := 1
                ;
            END_IF;
            
            IF #HMI.ST_P[#I] > #CFG_MAX_P THEN
                #Err := 1;
                GOTO Lable1; //指针数值超限
            END_IF;
        END_FOR;
        ;
    END_IF;
    IF #CFG_RbtNum>0 THEN
        FOR #I := 1 TO #CFG_RbtNum DO
            IF #HMI.RBT_P[#I] = 0 THEN
                #HMI.RBT_P[#I] := 1
                ;//初始化
            END_IF;
            IF #HMI.RBT_P[#I] > #CFG_MAX_P THEN
                #Err := 1;
                GOTO Lable1; //指针数值超限
            END_IF;
        END_FOR;
        ;
    END_IF;
    
    #Err := 0;
END_REGION

REGION 流水号计算
    #RET:=RD_LOC_T(#SYS_Time); //系统时间
    #SYS_Year := UINT_TO_DINT(#SYS_Time.YEAR);
    #SYS_Month := USINT_TO_DINT(#SYS_Time.MONTH);
    #SYS_Day := USINT_TO_DINT(#SYS_Time.DAY);
    
    IF (#SYS_Time.HOUR = 0 AND #SYS_Time.MINUTE = 0 AND #SYS_Time.SECOND = 0)AND #SYS_Time.DAY <> 0 THEN
        #Set_Type.Type.SN:= ( #SYS_Month * 100 + #SYS_Day)* 10000  ;
        //计算每日流水号年月日信息(月*100+日)*10000
    END_IF;
    IF #Type_Real[100].Type.SN<>0 THEN
        #Set_Type.Type.SN := #Type_Real[100].Type.SN; //启用MSE后 记录最后一次MES写入的流水号
      
    END_IF;
    
END_REGION

REGION 指针查询,在最小指针大于1的时候集体减1
    #Min := 99;
    #Max := 0;
        IF #CFG_STNum > 0 AND #CFG_STNum <= 32 THEN
        
           FOR #I := 1 TO #CFG_STNum DO
            IF #HMI.ST_P[#I] < #Min THEN
                #Min := #HMI.ST_P[#I];
            END_IF;
            IF #HMI.ST_P[#I] > #Max THEN
                #Max := #HMI.ST_P[#I];
            END_IF;
           END_FOR;
        END_IF;
        IF #CFG_RbtNum > 0 AND #CFG_RbtNum <= 64 THEN
            FOR #I := 1 TO #CFG_RbtNum DO
                IF #HMI.RBT_P[#I] < #Min THEN
                    #Min := #HMI.RBT_P[#I];
                END_IF;
                IF #HMI.RBT_P[#I] > #Max THEN
                    #Max := #HMI.RBT_P[#I];
                END_IF;
            END_FOR;  //查询最大指针,最小指针
            ;
        END_IF;
        
        
      
        IF #Min >= 2 THEN
            #Type_Real[1] := #EmptyType;
            IF #CFG_STNum>0 THEN
                FOR #I := 1 TO #CFG_STNum DO
                    #HMI.ST_P[#I] := #HMI.ST_P[#I] - 1;
                END_FOR;
                ;
            END_IF;
            IF #CFG_RbtNum>0 THEN
                FOR #I := 1 TO #CFG_RbtNum DO
                    #HMI.RBT_P[#I] := #HMI.RBT_P[#I] - 1;
                END_FOR;
                ;
            END_IF;
            
        END_IF;    //最小指针大于1时,清除第一个车型,指针全部减一
       
        FOR #I := 1 TO 100 DO
            IF #Type_Real[#I].Type.SN <> 0 OR #Type_Real[#I].Type.CT <> 0 THEN
                #Num := #Num + 1;  
            END_IF;
        END_FOR; //查询堆栈内共有多少数据
    
    #Min_P := #Min;
    #Max_P := #Max;
    #Out_Num := #Num;
   
END_REGION

REGION 车型画面显示
    IF #HMI.Page < 1  THEN
        #HMI.Page := 1;
    END_IF;
    IF  #HMI.Page > 10 THEN
        #HMI.Page := 10;
    END_IF;  //翻页处理
    
        FOR #I := 1 TO 10 DO
            #HMI.Type_View[#I] := #Type_Real[#I + (#HMI.Page - 1) * 10];
        END_FOR;
   
    END_REGION
    
    
    REGION 车型修改 指针在需要的时候减1
        #Enable[2] := #Set_Type.Enable AND NOT #Enable[3];
        #Enable[3] := #Set_Type.Enable;
        
        IF #Enable[2] AND #HMI.Select > 0 AND NOT #PB_Insert AND #Set_Type.Type.Num = 0 THEN
            #SelectNum := (#HMI.Page - 1) * 10 + #HMI.Select;
            #Type_Real[#SelectNum] := #Set_Type; //车型修改
            IF #Set_Type.Type.SN <> 0 AND #Set_Type.Type.CS <> 0 AND #Set_Type.Type.CT <> 0 THEN
                #Set_Type.Type.SN += 1; //有效车型每次写入后流水号+1;
            END_IF;
            IF #Type_Real[#SelectNum].Type.SN = 0 THEN
                FOR #I := 1 TO #CFG_STNum DO
                    IF #HMI.ST_P[#I] > #SelectNum THEN
                        #HMI.ST_P[#I] := #HMI.ST_P[#I] - 1;
                    END_IF;
                END_FOR;
                FOR #I := 1 TO #CFG_RbtNum DO
                    IF #HMI.RBT_P[#I] > #SelectNum THEN
                        #HMI.RBT_P[#I] := #HMI.RBT_P[#I] - 1;
                    END_IF;
                END_FOR;
            END_IF; //清除车型后,将指针大于当前被清除车型编号的工位指针和机器人指针减1
        END_IF;
        
    END_REGION
    REGION 车型插入,指针在需要的时候加1
        IF #Enable[2] AND #HMI.Select > 0 AND #PB_Insert AND #Set_Type.Type.Num = 0 AND #Type_Real[100]=#EmptyType
           AND #Set_Type.Type.SN <> 0 AND #Set_Type.Type.CS <> 0 AND #Set_Type.Type.CT <> 0//选择插入车型,且插入车型信息完整
        THEN
            #SelectNum := (#HMI.Page - 1) * 10 + #HMI.Select;
            
            FOR #I := 99 TO #SelectNum BY -1 DO
                #Type_Real[#I + 1] := #Type_Real[#I];//车型后移
              
                
            END_FOR;
            #Type_Real[#SelectNum] := #Set_Type; //车型插入
             #Set_Type.Type.SN += 1; //有效车型每次写入后流水号+1;
             
                FOR #I := 1 TO #CFG_STNum DO
                    IF #HMI.ST_P[#I] >= #SelectNum THEN
                        #HMI.ST_P[#I] := #HMI.ST_P[#I] + 1;
                    END_IF;
                END_FOR;
                FOR #I := 1 TO #CFG_RbtNum DO
                    IF #HMI.RBT_P[#I] >= #SelectNum THEN
                        #HMI.RBT_P[#I] := #HMI.RBT_P[#I] + 1;
                    END_IF;
                END_FOR;
             //插入车型后,将指针大于等于当前被插入车型编号的工位指针和机器人指针加1
                #PB_Insert := 0;
        END_IF;
    END_REGION
    
REGION 批量输入车型
    (*此段程序只能从后面插入车型,不能实现批量删除或修改车型,如果启用此段程序则需要删除此区域下一段程序
    
       IF #Set_Type.Enable THEN
            #Enable[3] := 1;
            ;
        END_IF;
        
        IF NOT #Use_MES AND #HMI.Select = 0 AND #Enable[3] AND #Set_Type.Type.Num>0 AND #Set_Type.Type.SN>0 AND #Type_Real[100].Type.SN=0 THEN
            #Type_Real[100] := #Set_Type;
            #Set_Type.Type.SN +=1;
            #Set_Type.Type.Num -= 1;
          
        END_IF;
        IF #Num=100 THEN
            #Set_Type.Type.Num := 0;// 车型输入满后 设置车型数量清零
        END_IF;
        
        IF #Set_Type.Type.Num = 0 THEN
            #Enable[3] := 0;
         
        END_IF;
        *)
        IF #Set_Type.Enable THEN
            #Enable[1] := 1;
            ;
        END_IF;
        WHILE #Set_Type.Type.Num > 0 AND #Set_Type.Type.Num <= 100 AND #Enable[1] AND #HMI.Select = 0 DO
            
            #Type_Real[101 - #Set_Type.Type.Num].Type := #Set_Type.Type;
            
            #Set_Type.Type.Num -= 1; //车型每次写入后NUM-1
            IF #Set_Type.Type.SN <> 0 AND #Set_Type.Type.CS <> 0 AND #Set_Type.Type.CT <> 0 THEN
                #Set_Type.Type.SN += 1; //有效车型每次写入后流水号+1;
                
            END_IF;
            
        END_WHILE;
        #Enable[1] := 0;
    END_REGION
    REGION 空车型或异常车型清除 车型移动
        FOR #I := 1 TO 99 DO
            
            IF #Type_Real[#I].Type.SN = 0 OR (#Type_Real[#I].Type.CT = 0 AND #Type_Real[#I].Type.CS = 0) THEN
                #Type_Real[#I] := #EmptyType;
                ;
            END_IF; //异常车型清除
            
            IF #Type_Real[#I].Type.SN = 0 AND #Type_Real[#I + 1].Type.SN <> 0 THEN
                #Type_Real[#I] := #Type_Real[#I + 1];
                #Type_Real[#I + 1] := #EmptyType;
            END_IF; //车型移动
        END_FOR;
        
    END_REGION
    REGION 清除Enable信号
        IF #Out_Num > 0 THEN
            FOR #I := 1 TO #Out_Num DO
                #Type_Real[#I].Enable := 0
                ;
            END_FOR;
            ;
        END_IF;
        
    END_REGION
    
    REGION 通过指针寻车型
        IF #CFG_STNum>0 THEN
            FOR #I := 1 TO #CFG_STNum DO
                IF #HMI.ST_P[#I] > 0 AND #HMI.ST_P[#I] < #CFG_MAX_P THEN
                    
                    #ST_Type[#I] := #Type_Real[#HMI.ST_P[#I]];
                    #ST_CS[#I].NotDo := #ST_Type[#I].Type.CS = 1; //空过
                    #ST_CS[#I].Normal := #ST_Type[#I].Type.CS = 2; //正常
                    #ST_CS[#I].CheckPartOut := #ST_Type[#I].Type.CS = 3;//检测下线
                    #ST_CS[#I].CheckPartIn := #ST_Type[#I].Type.CS = 4;//检测上线
                    #ST_CS[#I].Bad := #ST_Type[#I].Type.CS = 5;//不良品
                    #ST_CS[#I].KD := #ST_Type[#I].Type.CS = 6;//KD件
                    #ST_CS[#I].TryOn := #ST_Type[#I].Type.CS = 16;//空循环
                END_IF;
            END_FOR;
            ;
        END_IF;
        IF #CFG_RbtNum>0 THEN
            FOR #I := 1 TO #CFG_RbtNum DO
                IF #HMI.RBT_P[#I] > 0 AND #HMI.RBT_P[#I] < #CFG_MAX_P THEN
                    
                    #RBT_Type[#I] := #Type_Real[#HMI.RBT_P[#I]];
                    #RBT_CS[#I].NotDo := #RBT_Type[#I].Type.CS = 1; //空过
                    #RBT_CS[#I].Normal := #RBT_Type[#I].Type.CS = 2; //正常
                    #RBT_CS[#I].CheckPartOut := #RBT_Type[#I].Type.CS = 3;//检测下线
                    #RBT_CS[#I].CheckPartIn := #RBT_Type[#I].Type.CS = 4;//检测上线
                    #RBT_CS[#I].Bad := #RBT_Type[#I].Type.CS = 5;//不良品
                    #RBT_CS[#I].KD := #RBT_Type[#I].Type.CS = 6;//KD件
                    #RBT_CS[#I].TryOn := #RBT_Type[#I].Type.CS = 16;//空循环
                END_IF;
            END_FOR;
            ;
        END_IF;
        
    END_REGION
   
    Lable1:
REGION 画面显示
        FOR #I := 1 TO 10 DO
            #HMI.NUM[#I] :=(#HMI.Page - 1) * 10 +#I ; //车型列表编号
        END_FOR;
        #HMI.ST_Num := #CFG_STNum;
        #HMI.RBT_Num := #CFG_RbtNum;
        #HMI.Min_P := #Min_P;
        #HMI.Max_P := #Max_P;
        #HMI.Out_Num := #Out_Num;
        #HMI.Err[1] := #Err;
       
        #TON(IN := #HMI.Enable,
             PT := T#60S);
        IF #TON.Q THEN
            #HMI.Enable := 0
            ;
        END_IF;
        
        
    END_REGION

2、程序解释:

这段代码是用 PLC 编程语言(IEC 61131 - 3 标准语言)编写的,主要用于工业自动化场景中对工位、机器人以及车型相关信息的管理和处理。以下是对代码各部分的详细解释:

1、初始化值和确认状态

  • 数组初始化
    • 两个 FOR 循环分别对 #ST_Type#ST_CS(共 32 个元素 )和 #RBT_Type#RBT_CS(共 64 个元素 )数组进行初始化,将每个元素赋值为 #EmptyType 和 #EmptyCS ,清空工位和机器人相关的车型和状态信息。
  • 参数合法性检查
    • 检查 #CFG_STNum(工位数量配置 )和 #CFG_RbtNum(机器人数量配置 )是否在合理范围(0 - 32 和 0 - 64 )内,若超出范围则设置错误标志 #Err 为 1,并跳转到 Lable1 。
    • 检查 #CFG_MAX_P(最大指针数 ),若不在 0 - 99 范围,将其设置为 #CFG_STNum 的两倍。
  • 指针初始化与检查
    • 对于工位和机器人的指针数组 #HMI.ST_P 和 #HMI.RBT_P ,如果指针值为 0 则初始化为 1;若指针值超过 #CFG_MAX_P ,则设置错误标志并跳转。最后将错误标志 #Err 清零。

2、流水号计算

  • 获取系统时间并转换:使用 RD_LOC_T 函数获取系统时间 #SYS_Time ,并将其中的年、月、日转换为合适的数据类型存储在 #SYS_Year#SYS_Month#SYS_Day 中。
  • 流水号计算逻辑:
    • 当系统时间为凌晨 0 点 0 分 0 秒且日期不为 0 时,根据月和日计算每日流水号的年月日部分,公式为 (#SYS_Month * 100 + #SYS_Day)* 10000 。
    • 若 #Type_Real[100].Type.SN(可能是某种真实车型记录的流水号 )不为 0,则使用该值作为流水号,用于记录 MES(制造执行系统)最后一次写入的流水号。

3、指针查询,在最小指针大于 1 的时候集体减 1

  • 查找最大最小指针:通过 FOR 循环分别在工位指针数组 #HMI.ST_P 和机器人指针数组 #HMI.RBT_P 中查找最小和最大指针值,记录在 #Min 和 #Max 中。
  • 指针调整:若最小指针 #Min 大于等于 2,将 #Type_Real[1] 清空(赋值为 #EmptyType ),然后将所有工位和机器人指针值减 1。最后统计 #Type_Real 数组中有效数据(车型信息 )的数量存储在 #Num 中,并记录最小、最大指针和有效数据数量到 #Min_P#Max_P#Out_Num 。

4、车型画面显示

  • 翻页处理:限制 #HMI.Page(人机界面页码 )在 1 - 10 范围内,若超出则修正。
  • 车型视图更新:通过 FOR 循环根据当前页码 #HMI.Page ,将 #Type_Real 数组中对应位置的车型信息赋值给 #HMI.Type_View 数组,用于在人机界面显示当前页的车型信息。

5、车型修改 指针在需要的时候减 1

  • 使能条件判断:根据 #Set_Type.Enable(车型设置使能 )等条件计算 #Enable[2] 和 #Enable[3] 。
  • 车型修改逻辑:当满足使能条件、有车型选择(#HMI.Select > 0 )、非插入操作(NOT #PB_Insert )且车型编号为 0 时,进行车型修改操作。将选中车型位置的 #Type_Real 数组元素设置为 #Set_Type ,若车型信息有效则流水号加 1。若修改后车型流水号为 0,将大于该车型编号的工位和机器人指针减 1。

6、车型插入,指针在需要的时候加 1

  • 插入条件判断:当满足使能条件、有车型选择、是插入操作(#PB_Insert )、车型编号为 0、目标位置为空且车型信息完整时,执行车型插入操作。
  • 车型插入逻辑:将插入位置及之后的车型后移,插入新车型并将流水号加 1。然后将大于等于插入位置编号的工位和机器人指针加 1,最后将插入按钮信号 #PB_Insert 清零。

7、批量输入车型

  • 使能处理:根据 #Set_Type.Enable 设置 #Enable[1] 。
  • 批量输入逻辑:当车型数量配置 #Set_Type.Type.Num 在合理范围(1 - 100 )、使能且无车型选择时,通过 WHILE 循环从后往前将车型信息依次写入 #Type_Real 数组,每次写入后车型数量减 1,若车型信息有效则流水号加 1,最后将 #Enable[1] 清零。

8、空车型或异常车型清除 车型移动

  • 异常车型清除:通过 FOR 循环遍历 #Type_Real 数组,若车型流水号为 0 或车型类型和状态都为 0,则将该车型元素赋值为 #EmptyType 。
  • 车型移动:若当前车型流水号为 0 且下一个车型流水号不为 0,则将下一个车型信息前移,清空原位置车型信息。

9、清除 Enable 信号

若有效车型数量 #Out_Num 大于 0,通过 FOR 循环将 #Type_Real 数组中所有有效车型的使能信号 Enable 清零。

10、通过指针寻车型

  • 工位车型查找:当有工位配置(#CFG_STNum > 0 )时,通过 FOR 循环遍历工位指针数组 #HMI.ST_P ,若指针值在有效范围(大于 0 小于 #CFG_MAX_P ),则根据指针值从 #Type_Real 数组获取对应车型信息赋值给 #ST_Type ,并根据车型状态字段设置 #ST_CS 数组中各状态标志。
  • 机器人车型查找:类似地,当有机器人配置(#CFG_RbtNum > 0 )时,对机器人指针数组 #HMI.RBT_P 进行相同操作,获取车型信息并设置状态标志。

11、画面显示

  • 车型列表编号设置:通过 FOR 循环根据当前页码 #HMI.Page 计算并设置人机界面车型列表编号 #HMI.NUM 数组。
  • 界面参数更新:将工位数量、机器人数量、最小指针、最大指针、有效数据数量和错误标志等信息更新到人机界面相关变量中。
  • 定时器处理:使用定时器 #TON ,当使能信号 #HMI.Enable 为 ON 持续 60 秒后,将其清零。

本研究利用Sen+MK方法分析了特定区域内的ET(蒸散发)趋势,重点评估了使用遥感数据的ET空间变化。该方法结合了Sen斜率估算器和Mann-Kendall(MK)检验,为评估长期趋势提供了稳健的框架,同时考虑了时间变化和统计显著性。 主要过程与结果: 1.ET趋势可视化:研究利用ET数据,通过ET-MK和ET趋势图展示了蒸散发在不同区域的空间和时间变化。这些图通过颜色渐变表示不同的ET水平及其趋势。 2.Mann-Kendall检验:应用MK检验来评估ET趋势的统计显著性。检验结果以二元分类图呈现,标明ET变化的显著性,帮助识别出有显著变化的区域。 3.重分类结果:通过重分类处理,将区域根据ET变化的显著性进行分类,从而聚焦于具有显著变化的区域。这一过程确保分析集中在具有实际意义的发现上。 4.最终输出:最终结果以栅格图和png图的形式呈现,支持各种应用,包括政策规划、水资源管理和土地利用变化分析,这些都是基于详细的时空分析。 ------------------------------------------------------------------- 文件夹构造: data文件夹:原始数据,支持分析的基础数据(MOD16A2H ET数据 宁夏部分)。 results文件夹:分析结果与可视化,展示研究成果。 Sen+MK_optimized.py:主分析脚本,适合批量数据处理和自动化分析。 Sen+MK.ipynb:Jupyter Notebook,复现可视化地图。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三阶码叟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值