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 THENFOR #I := 1 TO #CFG_STNum DOIF #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 THENFOR #I := 1 TO #CFG_RbtNum DOIF #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_REGIONREGION 流水号计算#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+日)*10000END_IF;IF #Type_Real[100].Type.SN<>0 THEN#Set_Type.Type.SN := #Type_Real[100].Type.SN; //启用MSE后 记录最后一次MES写入的流水号END_IF;END_REGIONREGION 指针查询,在最小指针大于1的时候集体减1#Min := 99;#Max := 0;IF #CFG_STNum > 0 AND #CFG_STNum <= 32 THENFOR #I := 1 TO #CFG_STNum DOIF #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 THENFOR #I := 1 TO #CFG_RbtNum DOIF #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 THENFOR #I := 1 TO #CFG_STNum DO#HMI.ST_P[#I] := #HMI.ST_P[#I] - 1;END_FOR;;END_IF;IF #CFG_RbtNum>0 THENFOR #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 DOIF #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_REGIONREGION 车型画面显示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_REGIONREGION 车型修改 指针在需要的时候减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 THENFOR #I := 1 TO #CFG_STNum DOIF #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 DOIF #HMI.RBT_P[#I] > #SelectNum THEN#HMI.RBT_P[#I] := #HMI.RBT_P[#I] - 1;END_IF;END_FOR;END_IF; //清除车型后,将指针大于当前被清除车型编号的工位指针和机器人指针减1END_IF;END_REGIONREGION 车型插入,指针在需要的时候加1IF #Enable[2] AND #HMI.Select > 0 AND #PB_Insert AND #Set_Type.Type.Num = 0 AND #Type_Real[100]=#EmptyTypeAND #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 DOIF #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 DOIF #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_REGIONREGION 批量输入车型(*此段程序只能从后面插入车型,不能实现批量删除或修改车型,如果启用此段程序则需要删除此区域下一段程序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-1IF #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_REGIONREGION 空车型或异常车型清除 车型移动FOR #I := 1 TO 99 DOIF #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_REGIONREGION 清除Enable信号IF #Out_Num > 0 THENFOR #I := 1 TO #Out_Num DO#Type_Real[#I].Enable := 0;END_FOR;;END_IF;END_REGIONREGION 通过指针寻车型IF #CFG_STNum>0 THENFOR #I := 1 TO #CFG_STNum DOIF #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 THENFOR #I := 1 TO #CFG_RbtNum DOIF #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_REGIONLable1:
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(制造执行系统)最后一次写入的流水号。
- 当系统时间为凌晨 0 点 0 分 0 秒且日期不为 0 时,根据月和日计算每日流水号的年月日部分,公式为
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 秒后,将其清零。
