六部电梯各自在跑,呼梯信号却没人接。这是我在西门子智能制造挑战赛现场最紧张的一刻,前面十分钟的功能演示一切正常,到了压力测试阶段,六部十层电梯模型突然有一台对轿厢内选层毫无反应,而它的以太网通信指示灯正在慢闪。后来排查发现,问题出在主站与从站的握手时序上,和电梯机械结构一点关系都没有。这篇文章就从这套六部十层电梯程序的开发过程说起,把我在PLC S7-1200上做多电梯群控逻辑设计的完整思路、通信拓扑、算法取舍和调试教训一次讲透。
如果你是准备参加智能制造挑战赛的选手,或者正在做多设备协同控制的项目,这篇内容会很对胃口。我会把硬件选型、网络组态、程序架构、群控算法、现场调试这几块拆开讲,所有关键参数和逻辑都给出我实际使用的方案,你拿到手就能抄作业。
1. 系统架构怎么搭:一台S7-1200带着六个电梯跑的通信拓扑
先回答很多人问我的第一个问题:六部十层电梯,到底用一台PLC还是六台PLC?答案是都有,但都有限制。
用六台PLC各自控制一台电梯,通信靠PROFINET或者S7协议互相交换数据,好处是单梯逻辑不互相干扰,坏处是群控协调需要一个主大脑来做派梯决策,六台PLC之间的数据一致性要花很大精力维护。用一台S7-1200控制全部六部电梯,好处是群控算法全部放在一个PLC里,数据天然一致,坏处是I/O点数和程序扫描周期会成为瓶颈。
我最后的方案是:一台S7-1200 CPU 1215C作为主站,外加PROFINET分布式IO从站扩展点表。电梯的极限位、门区、上下行呼叫、轿厢内选层这些信号全部接到分布式IO上,主站通过以太网总线统一读写。这个架构既保留了单PLC群控逻辑的一致性,又不会因为信号太多把CPU的集成IO点撑爆。
1.1 硬件点表统计与扩展方案
先把点数算清楚,这一步不能拍脑袋。六部电梯十层楼,每部电梯需要的开关量输入包括:每层一个上呼按钮(10个)、一层到九层每层一个下呼按钮(9个)、轿厢内十个选层按钮(10个)、上极限/下极限/平层感应/开门到位/关门到位/超载开关(6个)。累计算下来每部电梯大约35个输入信号,六部就是210个。
输出侧每部电梯需要:上行接触器、下行接触器、开门继电器、关门继电器、层显数码管数据(如果走并行则要20个点位,走总线通信则占用通信接口)、蜂鸣器、到站钟,大约25个,六部就是150个。
一台CPU 1215C自带的数字量输入14点、输出10点,根本不够用。所以扩展方案我选的是ET200SP分布式IO从站,每个从站挂一个16点输入模块和一个16点输出模块,每部电梯分配一个从站,正好六组从站。这样从站和电梯一一对应,后期查故障非常方便。主站和从站之间走PROFINET,通信速率100Mbps,应对开关量这种毫秒级响应的信号绰绰有余。
1.2 为什么走以太网通信而不是硬接线
很多人习惯用硬接线把按钮信号直接拉到PLC柜里,六部电梯就是六百多点,控制柜里光是接线端子就能占满整排导轨,调试阶段排查断线会让人崩溃。以太网分布式IO的好处是每部电梯只需出一根工业网线到主站交换机,信号采集点离电梯现场越近,布线越短,干扰越少。
另外参赛现场的评审老师尤其看重系统的扩展性,我答辩的时候直接说了一句:“这套架构在电梯数量从六部增加到八部时,只需要增加一个ET200SP从站和一段网线。”这句话的效果比任何PPT都直观。
2. 群控调度算法设计:六部电梯协同的核心逻辑
单梯逻辑大家都懂,上行下行、开关门、平层停靠,这是基础。六部电梯真正难的是谁去响应呼梯、怎么避免两部电梯同时扑向同一个呼梯信号、怎样在早晚高峰调整策略。这一章我把群控算法的设计全过程写出来。
2.1 呼梯信号的分类与优先级
首先把所有呼梯信号分成三类:轿厢内选层指令、厅外上行呼梯、厅外下行呼梯。轿厢内选层的优先级永远最高,因为乘客已经站在轿厢里了,这时候电梯必须先响应内部指令。厅外呼梯按方向分,同方向的顺路呼梯可以截梯响应,反方向的呼梯则要单独判断是否值得掉头。
优先级的具体参数我这样定义:内部指令权重为10,同方向顺路厅外呼梯权重为7,反方向厅外呼梯权重为4。每台电梯维护一张自己的任务链表,每次扫描周期遍历所有未被响应的呼梯信号,按权重和距离综合打分,分最高的电梯获得该呼梯的响应权。
这里要强调一个关键点:同一个厅外呼梯信号,绝对不能同时分配给两部电梯,否则六部电梯会在同一层扎堆开门,乘客体验极差。我的做法是设置一个“呼梯占用标志”,谁先抢到,其他电梯就只能在调度表里看到该信号已被响应,不再参与竞争。
2.2 分区调度:六部电梯的默认管辖范围
静态分区的思路很简单:十层楼六部电梯,低区三部管1到5层,高区三部管6到10层,每区内部再按电梯编号轮转。这个默认方案能覆盖大多数工况,但有一个致命缺陷:如果低区没有请求,低区的三台电梯就闲在那里,而高区排了长队。
所以我在静态分区的基础上加了一个动态互援逻辑。每一部电梯除了自己的管辖楼层,还实时计算旁边分区的呼叫队列长度,如果相邻分区呼叫数超过3条而本分区没有呼叫,就把本电梯的响应范围扩展到整个楼层。说白了就是“本职工作优先,闲下来就去帮邻居”。
互援逻辑的判定周期我设置为2秒。太短会造成电梯在大楼中频繁改变目标层,表现为电梯一会儿往高区跑一会儿往低区跑,乘客会晕;太长则失去互援效果。实测下来2秒是个平衡点。
2.3 顺路截梯与反向顺路:减少停站的算法核心
单梯运行过程中遇到顺路呼梯,要判断是否停车。判断条件有三条,缺一不可:
一是电梯当前运行方向和呼梯方向一致。电梯正在上行,只响应上行厅外呼梯和当前轿厢内选层指令,下行呼梯一律忽略,除非执行完所有上行任务后没有新的上行指令且该下行呼梯离当前楼层较近。
二是目的地楼层在电梯当前楼层和当前最高目标楼层之间。比如电梯在3层,正前往8层,那么5层的上行呼梯是顺路的,响应它只需要在5层加一个停靠,不浪费行程。
三是呼梯响应后不会导致电梯反向。这条是很多新手会忽略的,一部电梯正在上行途中,如果某个呼梯信号位于电梯当前楼层下方,就算方向相同也不能响应,因为响应它意味着电梯要先下行,运行效率反而降低。
顺路截梯的实现我写在FC块里,每次电梯运行方向改变时重新排序任务链表,把顺路停靠层插入到最优位置,保证电梯的停站序列始终是沿当前方向上单调递增或递减的,避免来回折返。
2.4 高峰模式的判定与切换
六部电梯的调度策略不能一套参数走到黑。早上上班时间,呼梯集中在一层上行方向,这时候如果还按静态分区跑,低区的电梯会全部扎堆一层,高区电梯却收不到任何请求。我的方案是在群控主程序中设了一个高峰模式判定FB,统计最近5分钟内每部电梯的呼梯到达率,超过阈值就切换调度算法。
高峰模式下的派梯逻辑改为“层层停靠,不分高低区”:所有电梯统一响应一层上行呼梯,尽量做到每隔七八秒就发出一部电梯,减少乘客在候梯厅的等待焦虑。高峰期呼梯的分配采用最小等待时间算法,每部电梯根据当前楼层和运行方向,计算到达一层呼梯点所需的预估时间,选时间最短的电梯响应。
这个预估时间不是简单距离除以速度,还要叠加预估停靠时间。我设定每停靠一层额外加8秒,用来补偿开关门和乘客进出时间,这样的计算结果在现场演示中非常接近实际运行表现。
2.5 群控算法伪代码直出
用SCL语言写群控派梯模块,核心逻辑如下:
// 六部电梯统一扫描,分配所有未被响应的厅外呼梯 FOR call := 1 TO MAX_CALLS DO IF call_status[call] = UNASSIGNED THEN best_score := 9999; best_elev := 0; FOR elev := 1 TO 6 DO IF elevator_state[elev].fault = FALSE THEN score := CalcDispatchScore(elev, call); IF score < best_score THEN best_score := score; best_elev := elev; END_IF; END_IF; END_FOR; IF best_elev <> 0 THEN AssignCall(best_elev, call); call_status[call] := ASSIGNED; END_IF; END_IF; END_FOR;打分函数CalcDispatchScore综合考虑电梯当前楼层、运行方向、任务链表长度、呼梯方向与电梯方向的匹配程度,分数越低优先级越高。方向匹配时扣掉20分作为加成,顺路时再扣掉15分,确保算法优先派那些本来就顺路又空闲的电梯。
3. 程序实现与调试验收:S7-1200上的工程落地细节
有了算法框架,接下来是把逻辑变成LAD和SCL代码,并在一台真实的S7-1200 PLC上调通的过程。
3.1 程序块架构:OB、FB、FC的职责划分
S7-1200的程序结构直接影响后期调试效率。我把程序划分为四个层次,对应不同OB和块类型。
主循环OB1只做一件事:调用群控调度FB。所有电梯的单梯逻辑都封装在FB_电梯控制块里,每部电梯创建一个背景数据块实例,互不干扰。单梯块内部处理状态机:空闲、定向、运行、开门、维持、关门、故障。这种状态机结构在任何PLC平台上都通用,评审老师看程序结构时也最容易给分。
通信接口统一封装在FC_通信收发块里,主站与六个分布式从站的I/O刷新全部在这个FC中完成。这样做的好处是,如果赛后要移植到S7-1500或者其他品牌的PLC,只需要重写通信FC,群控算法和单梯状态机可以原封不动搬走。
3.2 数据块设计:群控数据交换的核心
群控数据交换我用了三个共享数据块:DB_群控指令区、DB_电梯状态区、DB_系统标志区。DB_群控指令区存放所有厅外呼梯信号、内部指令和各电梯的任务链表;DB_电梯状态区存放每部电梯的当前楼层、方向、运行速度、开关门状态、故障代码;DB_系统标志区存放高峰模式标志、消防模式标志、司机模式标志等全局信息。
数据块布局有一个经验值得记住:把需要频繁修改的数据集中放在一个DB里,访问时整体读取到临时变量再做逻辑判断。这样比每条逻辑都去单独读DB地址要快很多,S7-1200的数据访问虽然不慢,但在群控这种多循环多次遍历的场景下,访问方式的优化能明显降低扫描周期。我实测优化前扫描周期是18毫秒,优化后降到12毫秒。
3.3 平层校正确保停靠精度
电梯停靠精度是现场评审的重点。我的方案是红外平层感应器配合PLC高速计数,每层楼安装一个平层隔磁板,电梯轿厢安装两个上下平层感应器。当两个感应器同时进入隔磁板区域时,PLC判断电梯已处于平层区间,触发减速和停车。
平层校准参数在调试时要做一遍全程“爬楼学习”:让每一部电梯从一层到十层慢速运行,在每个平层位置记录隔磁板中心与上下感应器中点的偏差量,存入DB_平层补偿表中。高速运行时会因为惯性产生轻微过冲,补偿表正好用来修正这个误差,实测补偿后停靠精度稳定在±5毫米以内,满足模型验收要求。
3.4 功能测试清单:赛前必须跑完的验证项
我整理了一份完整的测试清单,贴在调试站旁边,每一项不跑完不开工演示。清单包括:每部电梯的上下极限位触发保护、超载时持续开门不关门、开关门时间超时报警、厅外呼梯全部由六部电梯轮转响应、同一呼梯信号不会重复派梯、任意一部电梯断网后其余五部正常联动、主站PLC断电重启后自动恢复群控状态。
断网恢复这一项尤其重要。PROFINET通信中断后,主站会在一段时间内判定从站离线,此时该电梯要进入故障锁定状态,不能再参与派梯。网络恢复后主站要自动重新识别从站,并复位故障标志。这个功能听着简单,实际联调时最容易出bug,因为S7-1200的PROFINET断线重连时间不是固定值,跟从站数量、网络负载都有关系,我在代码里对重连状态做了三帧确认才置位恢复标志。
4. 现场实战避坑录:通信、平层与答辩的雷区
这一章全是我在参赛现场和赛后复盘中踩过的坑,每一项都值得记下来。
4.1 通信断站导致电梯集体失联
第一次联调六部电梯全部接上PROFINET网络,系统运行不到十分钟,第三部电梯的从站突然掉线,接着第五部跟着掉线,最后六部全部掉线。排查后发现两个原因叠加:一是交换机的端口缓冲区太小,六路IO数据同时刷新时出现拥塞;二是主站DB块里的通信超时设置太短,从站只是延迟返回了一个扫描周期,主站就报了故障并执行了停梯。
解决方法是双管齐下。硬件上把普通交换机换成工业管理型交换机,开启组播过滤,PROFINET流量只在主站和对应从站之间有效,避免广播风暴;软件上把通信超时从默认的20毫秒延长到300毫秒,同时增加了连续三次超时才判定断站的逻辑。改完之后整场演示再也没有出现掉线。
这里有个经验分享:比赛场地网络环境复杂,场地无线信号、其他队伍的工业设备都可能干扰你的以太网通信,所以通信参数必须留足余量。千万别为了追求快的响应时间把超时设得太紧,现场不是你一个人在用这块频谱。
4.2 平层抖动造成重复校准
平层感应器在隔磁板边缘会出现信号抖动,也就是1和0之间快速切换几十毫秒。当时电梯明明已经停平稳了,PLC却因为抖动信号误判电梯还没进平层区,反复触发校正动作,表现为电梯在平层位置轻微点头。
处理办法是在程序中加数字滤波:感应器信号连续扫描5次均为同一电平,才认定状态变化有效。这个滤波不放在通信读取FC里,而是放在单梯FB的状态机入口处,避免影响平层感应器的实时响应速度。
4.3 答辩评审问得最多的三个问题
答辩环节评审老师最习惯问的问题,提前准备好答案就不会慌。
第一个问题:如果六部电梯同时接到一层上行呼梯,你的算法如何避免走廊里挤满六部电梯?这个问题其实是想考察你对派梯独占机制的理解,要把呼梯分配标志和打分函数讲清楚。
第二个问题:你的系统能否扩展到二十层、十部电梯?这个问题的潜台词是你有没有做过性能估算。我计算过,S7-1200的程序存储空间和扫描周期在十部二十层情况下仍然有余量,但PROFINET从站的通信负载会明显增加,可能需要分段组网。
第三个问题:电梯困人时你的系统如何响应?这体现你对安全功能的考量。我的方案是消防模式信号接入后,所有电梯立即返回首层,开门释放乘客,同时群控算法暂停派梯,这个逻辑单一来源,不接受群控覆盖。
4.4 千万别忽略机械零位和原点
开场提到的问题让我印象深刻。当时那台电梯不响应内选,排查到最后发现不是通信问题,而是这台电梯调试时先手动开到了六层以外,控制器里的当前楼层值和机械实际楼层不统一,楼层计数跑飞了。也就是说相关位置信息已经和机械体系脱节,反馈值和期望值对不上,控制逻辑自然拒绝执行新的内选指令。
六部电梯统一上电后,第一步必须做“回参考点”操作。我在程序中加了一个信号:如果电梯上电后发现没经过一层限位开关,则强制定向到一层,以限位开关作为零位重新标定楼层。这个逻辑放在OB100启动组织块中,每次上电自动执行,就再也没有出现过跑飞故障。
另外有个细节,程序里涉及到多部电梯同时开门的问题。我原来允许两部电梯同一时间开门,结果现场演示时六部电梯有两次同时到达一层,形成排队开门,乘客评价体验不好。后来我在群控逻辑里加了一条互锁:同一层同一方向,只允许一部电梯开门,其他电梯即使到达该层也要等待,等第一扇门关闭后再开。这条互锁在程序上只加了一行判断,但对运行品质的提升立竿见影。
5. 最后的干货:程序注释规范和代码量统计参考
很多选手把程序写出来就算完事,实际上评委翻开程序注释的那一刻,你的分数就已经定了。
我每一部电梯的信号配置和每一个群控分支都有完整中文注释,块头注释写明作者、日期、版本、功能描述。FC和FB的接口变量注释尤其重要,评委在查看程序时主要看接口变量的定义是否清晰,不关心你内部循环是怎么写的。
程序总代码量参考:单梯控制FB约八百行SCL,群控调度FB约五百行SCL,通信接口FC约三百行LAD,初始化OB100和故障处理代码约两百行,加在一起不到两千行。S7-1200的存储空间完全够用,但你如果全部用LAD写,代码量可能膨胀到三千行以上,可读性反而下降。所以我的经验是算法用SCL,逻辑控制用LAD,混编才是S7-1200下的最优解。
整套程序从拿到赛题到最终通过验收,我一共用了九周时间。前两周搭模型和硬件,中间四周写单梯和群控逻辑,最后三周全部花在联调和抗干扰测试上。如果让我重新做一次,我会把联调的时间再拉长一周,因为真正影响比赛成绩的从来不是算法多花哨,而是系统在连续七十二小时高负荷演示下能不能一次故障都不出。以太网通信下的多设备协同,往往最脆弱的就是通信这一环,但把它调稳了,整个系统的价值才能真正显现出来。