『7x24小时有问必答』
题目:

今天写一个轻松一点的例子。

假设输送线上来了一件物料,前面有 8 个缓存工位、分拣口或者投料口。每个工位有自己的位置坐标,有的工位空闲,有的已经占用,有的正在故障或被屏蔽。

现在 PLC 要做一个选择:从这些工位里挑一个“可以用,并且离当前物料最近”的工位。

这个小需求看起来像算法题,其实现场味道很浓。做缓存线、转盘分配、分拣口投放、AGV 投料点选择时,都会遇到类似问题。

本例用 SCL 写一个通用 FC,实现最近空闲工位选择。

设计分析:

最简单的分配方法是轮询:1 号能用就给 1 号,1 号不能用就看 2 号,依次往后找。

轮询很好理解,也很稳定。但有些设备上,轮询不一定是最合适的。

比如物料当前在输送线 1200 mm 的位置,3 号工位在 1300 mm,7 号工位在 5000 mm。如果两个工位都空闲,从机械动作距离、节拍和等待时间看,显然 3 号更顺手。

所以我们把问题拆成三步:

先判断每个工位是否可用:Ready 为 TRUE,Occupied 为 FALSE,Blocked 为 FALSE。

计算物料当前位置 sourcePos 与工位位置 stationPos 的距离。

在所有可用工位里,找出距离最小的那一个。

这就是一个很朴素的“最小值搜索”。它不神秘,但放在 PLC 项目里很实用。

创建功能 FC:

本例创建一个 FC,命名为:

PickNearestFreeStation
为什么这里用 FC,而不是 FB?
因为这个功能本身只是根据当前输入做一次计算,不需要记忆历史状态。它更像一个计算工具:输入一组工位状态,输出推荐工位编号。
真正的“选中后保持”、“发命令”、“等待到位”、“异常处理”,应该放在上层顺控 FB 里。

定义接口变量:

定义输入变量:
enable:功能使能。
request:本扫描周期是否需要计算推荐工位。
sourcePos:物料当前位置,单位可以按项目约定,例如 mm。
count:实际使用的工位数量,最大 8。
stationReady:工位就绪状态数组。
stationOccupied:工位占用状态数组。
stationBlocked:工位屏蔽或故障状态数组。
stationPos:每个工位的位置坐标数组。
定义输出变量:
返回值:推荐工位编号。0 表示没有可用工位。
valid:是否找到可用工位。
minDistance:推荐工位与物料当前位置的距离。
stationAvailable:每个工位本次计算得到的可用状态。
定义临时变量:
tempI:循环变量。
tempValidCount:有效工位数量。
tempDistance:当前工位距离。
tempBestDistance:当前找到的最小距离。
tempFirstFound:是否已经找到第一个可用工位。

程序代码:

调用方法:

可以建立一个全局 DB,命名为:
GdbStationPicker
在 DB 中定义工位状态和计算结果,例如:
在 OB1 或设备主 FB 中调用:

一个小例子:

假设物料当前位置 sourcePos = 1180。
当前 1 号工位位置 500,距离 680;2 号工位位置 1000,距离 180;3 号工位位置 1500,距离 320;4 号工位位置 2000,距离 820。
如果 2 号和 3 号都可用,程序会选择 2 号,因为 180 比 320 更近。
如果 2 号已经占用,程序会跳过 2 号,选择 3 号。
如果所有工位都不可用,函数返回 0,同时 valid 为 FALSE。

代码测试:

调试时可以用监控表做几组输入,观察 SelectedIndex、Valid 和 MinDistance。
全部工位 Ready,全部未占用,sourcePos 放在 1180,确认选择距离最近的工位。
把最近工位 Occupied 置 TRUE,确认程序会自动选择第二近的可用工位。
把某个工位 Blocked 置 TRUE,确认它不会参与选择。
把 request 置 FALSE,确认返回 0,valid 为 FALSE。
把 count 改成 4,确认 5 到 8 号工位不会参与选择。
这几个测试做完,基本能确认计算逻辑没有跑偏。

工程注意事项:

第一,函数输出的是“推荐值”,不是最终命令。
PLC 程序里经常有一个坑:刚算出 SelectedIndex,下一扫描周期工位状态变了,SelectedIndex 也变了。如果你已经开始执行动作,就不应该让推荐值继续飘。
更稳妥的做法是:在顺控步骤开始时,把 SelectedIndex 锁存到 CurrentTargetStation。后续动作都用锁存值,直到本次任务结束。
第二,平局规则要讲清楚。
如果两个工位距离一样,本例会选择编号小的那个。因为代码里用的是 distance < bestDistance,而不是 distance <= bestDistance。这个细节看起来小,但调试时很重要。
第三,位置单位要统一。
sourcePos 和 stationPos 要用同一个单位。都用 mm,就都用 mm;都用编码器脉冲,就都用脉冲。不要一个用 mm,一个用脉冲,程序不会骂人,设备会。
第四,Blocked 不只是故障。
Blocked 可以表示故障屏蔽,也可以表示人工禁用、维护模式、工位未启用、工艺不匹配。把它单独作为一个输入,比把所有条件揉进 Ready 更清楚。

常见问题:

第一,把选择算法写在一堆 IF 里。
8 个工位还勉强能看,16 个、32 个就很难维护。数组加 FOR 循环,是 SCL 在这类场景里的优势。
第二,没有处理“没有可用工位”。
返回 0 和 valid := FALSE 一定要有。上层程序看到无效结果时,应等待、报警或进入无目标状态,而不是继续给某个默认工位发命令。
第三,把推荐工位当成实时目标。
推荐值可以实时变化,目标值不应该随便跳。动作一旦开始,就要有清楚的状态边界。
第四,所有条件都写成一个 Ready。
Ready、Occupied、Blocked 分开写,调试时一眼就知道工位为什么不能选。现场查问题,靠的就是这种可读性。

老炮儿建议:

如果是缓存线或分拣口,优先把“选择算法”和“动作顺控”拆开,算法只负责推荐,顺控负责执行。
如果要兼顾工位负载均衡,可以在距离相同或距离接近时,再加入使用次数、等待时间等权重。
如果项目对节拍要求高,可以把工位数量上限固定下来,避免写成没有边界的大循环。
如果选择结果要给 HMI 显示,建议同时显示 SelectedIndex、MinDistance 和 StationAvailable 数组,调试会舒服很多。

总结:

本例用 SCL 写了一个最近空闲工位分配器。
它的核心思想很简单:先筛选可用工位,再计算距离,最后找最小值。
这类小算法不一定华丽,但很适合 PLC 工程。它能让程序从“能跑”往“好调、好改、好解释”走一步。
自动化项目里很多有趣的算法,最后都不是为了炫技,而是为了让设备少走弯路,让调试少绕圈。
实例分享链接:
https://pan.quark.cn/s/c2713ce10da4

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码