☰
S7-1200以太网通信实现六部十层电梯群控调度系统
2026/10/6 9:57:33 网站建设 项目流程

六部十层电梯,单看题目很多人觉得“无非是把单部电梯的程序复制六份”。真正做完西门子智能制造挑战赛这个赛题,才发现最大的坑根本不是电梯逻辑本身,而是六部电梯在以太网通信下如何协调、如何响应外部召唤、如何在裁判系统随机请求下稳定运行。这篇文章把我从需求拆解、硬件组网、S7-1200程序架构到群控调度算法的完整开发过程写下来,尤其侧重以太网通信下的PLC控制器逻辑设计思路,给后面参赛的同学一条可以复现的路径。

1. 竞赛项目的真实规模:不是“电梯程序”而是“分布式控制系统”

1.1 信号点位的数量级估算

先算一笔账,你就知道这个项目为什么不能用单梯思路硬套。十层楼六部电梯,光轿厢内呼按钮就是每部10个、总共60个输入点;每层厅外召唤按钮按真实电梯布置,1层和10层各1个单方向按钮,中间2到9层每层2个方向,就是18个召唤输入点。再加上每部电梯的平层传感器、门区信号、开关门限位、上下极限位、超载信号、光幕信号,一套系统下来离散量输入稳稳超过200点。

这意味着什么?如果用单台PLC的I/O硬接线方案,选型直接往S7-1500大机架上靠,成本高、接线复杂、比赛现场排查故障也麻烦。而比赛给的核心约束是“以太网通信”,所以正确思路是把它当成一个分布式控制系统来做,而不是一台中央控制器包揽所有I/O。

1.2 评审眼中的“隐藏权重”

竞赛评分不是只看电梯能不能动。我从赛后复盘和评委交流中总结出几个关键维度:

  • 群控调度效率:多部电梯同时响应召唤时,派梯策略是否合理,乘客平均候梯时间是否直观可见。
  • 通信稳定性:在持续运行30分钟以上的压力测试中,通信数据是否出现掉线、乱序、丢包。
  • 程序可读性与工程规范性:OB块划分、FC/FB封装、变量命名、注释是否达到工程级标准。
  • 故障处理完备性:困人、超时未响应、开关门故障等异常场景是否有明确逻辑。

这些维度加起来,其实是在模拟工业现场的“功能安全+效率+可维护性”三重评价体系。写程序之前心里就要有这张评分表,否则后期返工非常痛苦。

1.3 团队分工与开发节奏安排

这个项目我一个人全包会非常吃力,建议三人组队。我的分工方式是这样的:

  • 一人负责硬件接线和网络组态,完成PLC选型、交换机连接、IP规划。
  • 一人负责单梯控制逻辑,把开关门、平层、运行状态机做扎实。
  • 一人负责群控调度算法和上位机监控界面,把六台电梯的召唤分配逻辑跑通。

开发节奏上,我强烈建议前两周只做单梯逻辑和通信验证,第三周才合并群控算法。很多队伍上来就直接写六梯联动,结果单梯状态机还没调试稳定,群控一跑就彻底乱套,最后哪里有问题都定位不出来。

2. S7-1200硬件选型与以太网组网方案的设计逻辑

2.1 为什么选S7-1200而不是S7-1500或200 SMART

这个赛题的硬件选型值得专门说。S7-1500性能当然更强,但比赛场景用1200系列完全够,而且有三个实打实的优势:

  • 性价比与采购周期:S7-1200系列CPU相比1500便宜不少,比赛经费有限,没必要把预算砸在冗余性能上。
  • 体积与安装灵活性:如果采用分布式I/O方案,1200配合ET200SP远程I/O模块,安装空间和接线复杂度比一台大CPU加一堆I/O卡件友好得多。
  • 博途平台统一编程:S7-1200和S7-1500共用TIA Portal,代码几乎可以无缝迁移。用1200写好的FB块,以后换1500直接拖过去就能用。

具体型号我用的是CPU 1214C DC/DC/DC,集成14路数字量输入和10路数字量输出,再配合两个SM 1234模拟量模块和若干远程I/O。比赛模型电梯的传感器和执行器数量,这个组合刚刚好。

2.2 网络拓扑:一台主站与五台智能从站的分布式架构

我的整体拓扑是把六部电梯的控制器角色拆开:一台S7-1200作为群控主站,负责全局调度算法,其余五台S7-1200作为智能从站,各自控制一部电梯的现场逻辑。第六部电梯的逻辑直接集成在主站CPU里,这样六台设备的通讯量相对均衡。

为什么不干脆六台都独立再设一台单独的上位机做调度?因为裁判系统直接通过以太网连接PLC读取数据,如果调度逻辑放在PC上位机里,一旦通信链路波动,整个系统就失去调度能力。把调度下沉到PLC主站,实时性更有保障。

IP规划看似简单但特别重要,比赛现场我看到不少队伍吃过亏。我的规划是这样的:

  • 主站:192.168.0.10
  • 智能从站1号至5号:192.168.0.11到192.168.0.15
  • 裁判系统/监控上位机:192.168.0.20
  • 子网掩码统一:255.255.255.0
  • 所有设备接入同一个工业以太网交换机

这里有个必须注意的细节:PLC的PROFINET接口默认IP和电脑网卡IP要在一个网段,否则博途在线诊断会一直报“无法访问设备”。比赛前一定要检查每台PLC的IP是否被占用或冲突。

2.3 PUT/GET通信机制与数据一致性的取舍

S7-1200之间做以太网通信有几种方式:PROFINET IO、PUT/GET、TSEND_C/TRCV_C协议通信。比赛场景里我最推荐PUT/GET,原因有两条:

  • 配置简单,直接在博途里填对方的IP地址、DB块号和偏移量就行。
  • 数据量不大,每台从站向主站上报的状态字也就几十个字节,PUT/GET完全扛得住。

PUT/GET使用前有一个关键设置在博途里,选中CPU属性,在“防护与安全”里勾选“允许来自远程对象的PUT/GET通信访问”。不勾这个,程序下载后通信死活不通,这是我身边好几个队伍踩过的坑。

数据块区域划分上,我建立了一套通信规约:每台从站PLC提供一个状态数据块和一个指令接收数据块。状态数据块从DB100开始,指令数据块从DB200开始,通过偏移地址区分不同电梯。主站定期调用PUT读取从站状态字,用GET下发派梯指令。

关于数据一致性,PUT/GET本身是分块读取的,如果读取一个结构体里的多个元素,理论上存在数据不一致的窗口期。针对电梯这种控制场景,我的做法是在每个从站的状态字里增加一个“数据有效”位,只有这位为1时,主站才解析整包数据。这样即使读取过程中刷新了数据,也不会把中间状态当成有效输入。

3. 群控调度算法:核心逻辑与SCL实现

3.1 两种调度策略的对比

电梯群控调度算法,我以前本科课程设计时只会做最简单的“固定分区”,就是1号和2号梯管1到5层,3号和4号梯管6到10层。这种方案在比赛模型下有两个致命问题:

  • 固定分区不能响应跨区召唤,乘客在1层想上10层,分区管控的1号梯接到任务后往上跑,如果2号梯刚好闲置,系统不会重新分配。
  • 遇到考核场景集中召唤时,某些区间的电梯排队,其他区间电梯空跑。

所以这次比赛我直接放弃了固定分区,选用了动态派梯策略,核心算法是最小预计到达时间(Estimated Time of Arrival,简称ETA)。

3.2 最小ETA算法的工程化设计

最小ETA算法的思路并不复杂:当一个新的厅外召唤产生时,系统为每部电梯计算“如果派它去响应这个召唤,预计需要多久能到达召唤楼层”,然后选择ETA最小的电梯派去。

ETA的计算需要考虑三个组成部分:

  • 电梯当前所在楼层与目标楼层的距离
  • 电梯当前运行方向与目标方向是否顺路
  • 电梯已经登记的楼层任务数量(如果电梯正忙,响应新召唤的时间要增加)

公式简化后:

ETA = 空闲时间基数 + 距离折算时间 + 方向惩罚系数 × 不顺路层数 + 任务排队惩罚 × 当前登记任务数

距离折算时间,每个楼层差折算1.5秒,方向惩罚系数,顺路取0,不顺路取2.0秒/层,任务排队惩罚每多一个登记任务增加1.0秒。

这个公式本身不难,难在参数整定。我一开始方向惩罚系数取太大,导致系统总是派最近的一台电梯,哪怕它已经满载;后来把惩罚系数调小,又出现多台电梯同时跑向同一楼层的情况。最终是通过连续几轮模拟测试,把惩罚系数稳定在2.0左右,并增加了“任务数超过4个则不再参与新派梯”的保护条件。

3.3 上下行高峰模式的动态切换

比赛场景里,裁判系统会随机模拟高峰客流,比如连续15个请求都集中在1层上行方向。如果这时候还用静态ETA参数,电梯群会疲于奔命,出现“大家都在跑但没有一台停在正确楼层”的混乱。

我增加了一个高峰检测模块:统计最近3分钟内上行召唤数量,如果超过设定阈值,系统自动切换到上行优先模式。在这个模式下,所有空闲电梯自动向低楼层基站靠近,而不是停留在任意楼层。下行高峰同理,电梯群自动巡航到高层基站。

这个设计在最终比赛演示时效果很明显,评委随机灌入一组密集请求,系统能在几秒钟内自动调整梯队布局,候梯时间显著下降。

3.4 SCL核心代码片段:派梯决策

下面给出我实现派梯决策的SCL核心代码。这段代码在OB30循环中断里执行,每100毫秒扫描一次。

FUNCTION_BLOCK FB_Dispatch VAR_INPUT newCallFloor : INT; newCallDirection : INT; // 1=上行, -1=下行 END_VAR VAR_IN_OUT liftStates : ARRAY[1..6] OF "LiftStateType"; END_VAR VAR i : INT; bestLift : INT; bestETA : REAL; tempETA : REAL; END_VAR bestLift := 0; bestETA := 9999.0; FOR i := 1 TO 6 DO // 跳过大故障或正在维修的电梯 IF liftStates[i].fault OR liftStates[i].maintenance THEN CONTINUE; END_IF; // 任务数过载的电梯不参与新派梯 IF liftStates[i].taskCount >= 4 THEN CONTINUE; END_IF; tempETA := CALC_ETA(liftState := liftStates[i], targetFloor := newCallFloor, direction := newCallDirection); IF tempETA < bestETA THEN bestETA := tempETA; bestLift := i; END_IF; END_FOR; IF bestLift <> 0 THEN // 写入派梯指令,触发从站执行 DispatchCmd[bestLift].targetFloor := newCallFloor; DispatchCmd[bestLift].commandValid := TRUE; DispatchCmd[bestLift].callDirection := newCallDirection; END_IF;

这段逻辑的调用频率是100毫秒一次,完全没有性能压力。真正需要关注的是liftStates数组的数据来源,它由PUT/GET通信从各从站读入,必须在读取更新周期内保证一致性。我的做法是:OB30里先调用通信函数块刷新liftStates,再执行派梯决策。顺序颠倒会导致派梯逻辑基于旧数据工作,出现明显的逻辑滞后。

4. 程序架构与PLC状态机设计:让六部电梯共享一套逻辑

4.1 用FB封装单梯控制逻辑,避免六份重复代码

很多初学者写多电梯程序时,会把一个电梯的程序复制六份,改成不同的DB号,再改内部地址。这个做法非常糟糕,后期想调整一个逻辑细节,要重复改六次,漏改一次就出现“1号梯正常但5号梯异常”的诡异现象。

正确的做法是写一个通用功能块FB_Elevator,把电梯控制的所有逻辑封装进去,然后用多重背景的方式实例化六次。这样六部电梯共享完全相同的代码,只是各自的数据块不同。后续修改一次FB,编译下载后六部电梯全部生效。

我的FB_Elevator接口包含了开关门控制、平层检测、运行方向切换、内呼登记、外呼响应、故障上报、急停逻辑、超时保护。内部使用一个状态机管理电梯的运行状态,下面详细展开。

4.2 电梯控制核心状态机

状态机的设计我按照经典电梯控制方式拆成六个状态:空闲、开门、关门、运行、平层停车、故障封锁。每个状态的事件和处理逻辑如下:

  • 空闲:电梯停在某层,无任务。收到新任务后自动进入开关门流程。
  • 开门:门正在打开,等待门限位信号到位,然后保持开门若干秒,再触发关门。
  • 关门:门正在关闭,如果光幕被触发则立即重新开门。
  • 运行:电梯根据目标方向选择上行或下行,持续运行直到接近目标楼层。
  • 平层停车:运行到目标楼层后减速,平层传感器信号确认到位,进入开门状态。
  • 故障封锁:发生超速、门锁异常、急停等故障时,封锁电梯,停止响应一切召唤。

状态机的实现用SCL的CASE语句最清晰。下面是个简化片段:

CASE liftState OF LiftState_Idle: IF newTask THEN liftState := LiftState_Opening; END_IF; LiftState_Opening: IF doorOpenLimit THEN openTimer(IN := TRUE); IF openTimer.Q THEN liftState := LiftState_Closing; END_IF; END_IF; LiftState_Closing: IF lightCurtain THEN // 光幕触发,重新开门 liftState := LiftState_Opening; ELSIF doorCloseLimit THEN liftState := LiftState_Running; END_IF; LiftState_Running: IF floorSensor[targetFloor] THEN liftState := LiftState_Leveling; END_IF; LiftState_Leveling: IF levelSensor THEN liftState := LiftState_Opening; END_IF; LiftState_Fault: // 保持封锁,直到人工复位 IF resetSignal THEN liftState := LiftState_Idle; END_IF; END_CASE;

这个状态机看着简单,但实际调起来有不少细节。比如关门限位和运行启动之间,一定要加一个短暂延时,否则门还没完全关严,电机就启动,模型电梯的机械结构会发出明显的撞击声。我的做法是关门限位到位后延时300毫秒再发运行指令。

4.3 全局数据块与组内联锁逻辑

六部电梯虽然共享FB,但毕竟是独立执行机构,组内联锁必须靠全局数据块配合。我建了一个全局DB,保存六部电梯各自的当前位置、当前方向、当前状态、登记任务表,以及每层的召唤请求状态。群控调度模块读这个DB,修改这个DB,单梯FB也扫描这个DB。

联锁逻辑中比较重要的是“同一时间只允许一部电梯响应同一召唤”。具体实现是:召唤信号在DB中有一个“assignedLift”字段,一旦被某部电梯领取,其他电梯扫描到该字段非0就自动忽略。这样可以避免两部电梯同时开向同一楼层。

4.4 变量表命名规范

这个说是规范,其实是血泪教训。第一版程序里我的变量名随意起,比如“a1”“b2”“temp”。到了联调阶段,群控模块和单梯模块之间来回对地址,对着对着就晕了。后来我按“楼层传感器”和“召唤按钮”统一命名:

  • 楼层传感器:FlrSns_L1到FlrSns_L10
  • 内呼按钮:CabBtn_L1到CabBtn_L10
  • 厅外上行召唤:HallUp_L2到HallUp_L9
  • 厅外下行召唤:HallDn_L2到HallDn_L9

这样变量表本身就是文档,后期调试找点特别快。建议命名规范在项目第一天就定下来,代码写多了再改命名等于重写。

5. 调试方法论与现场排障:从仿真到实物的沟沟坎坎

5.1 仿真跑得通,实物就一定会出问题

我在博途里用PLCSIM仿真,六部电梯的逻辑和调度算法在虚拟环境里跑得非常顺畅,当时还挺得意。结果一接到实物模型上,第一天就冒出三个问题:

  • 通信掉线:跑一段时间后某个从站的状态字不再更新,主站一直读到旧数据。
  • 信号抖动:平层传感器在接近感应位置时反复通断,导致电梯在同一楼层反复开关门。
  • 机械卡顿:模型电梯的抱闸释放和电机启动之间没有做好时序配合,启动时出现明显抖动。

先说通信掉线。排查过程是逐步缩小范围的:先看交换机指示灯所有端口都亮,说明物理链路没问题;再看博途在线诊断里的通信连接状态,发现掉线的从站连接确实处于中断状态。最后定位到问题根源是从站PLC的看门狗时间设置太短,主站偶尔因为扫描周期波动,通信间隔超过从站设定的监控时间,从站自动断开了连接。解决办法是把通信监控时间从默认的1秒放宽到3秒,同时保证主站侧PUT/GET调用周期稳定在100毫秒。

5.2 平层信号抖动:软件消抖与硬件滤波双管齐下

平层信号抖动是电梯控制的经典问题。模型电梯用的是接近开关,当金属挡片刚好处于开关检测边界时,信号会快速抖动几毫秒。程序如果直接读取这个信号做状态切换,就会出现电梯已经平层却反复开门关门的情况。

我的处理分两层。硬件层面,在博途的DI通道属性里启用数字量输入滤波,设置成6.4毫秒,能把大部分机械抖动滤掉。软件层面,在FB里加了信号确认机制:平层信号必须连续两次扫描都为1,才认为平层有效。这个确认时间大约是20毫秒,足够排除绝大多数干扰。

另外还有一个隐蔽的坑:六部电梯的平层传感器安装位置有细微差异,有的偏高有的偏低。我在每部电梯的DB里加了一个“平层补偿偏移”参数,通过现场逐层标定来修正每层停车位置的偏差。这个参数如果不加,电梯在部分楼层会停得明显偏出平层区。

5.3 一个需要重点处理的场景:电梯长时间无响应

竞赛压力测试中,裁判系统会故意制造一些异常请求。最典型的是:某部电梯收到派梯指令后,由于机械卡阻或传感器丢失,一直没有到达目标楼层。如果程序不对这种情况做处理,整个调度系统会卡住,后续所有请求都无法分配。

我为每部电梯增加了一个“任务超时监控”功能块。当某部电梯领取任务后,系统计算理论最大到达时间(按电梯最大速度、楼层间距和额外冗余),如果实际消耗时间超过理论值的1.5倍,任务还未完成,就判定“疑似卡梯”,触发以下动作:

  • 将该电梯状态标记为故障待检。
  • 清空该电梯的所有登记任务。
  • 把任务重新释放回全局召唤池,由调度模块重新分派给其他电梯。

释放任务的重分配逻辑要特别注意:必须在“任务超时”状态确认后方可释放,不能一超时就立即释放,否则可能出现电梯其实马上要到达,但任务已经被分配出去的情况,造成两部电梯同时响应。我的做法是超时判定延迟2秒,给电梯一个缓冲窗口。

5.4 现场快速排障的调试工具选择

调试阶段我强烈建议准备以下工具:

  • 博途在线监控:直接看FB内部变量和状态机当前状态。
  • Wireshark抓包:如果怀疑通信问题,直接用Wireshark抓PROFINET数据包,看PUT/GET数据是否正常往来。
  • Excel记录脚本:用PLC的Trace功能或者DataLog功能记录连续运行数据,赛后复盘时把曲线拉出来看。

特别是Wireshark,很多同学只会用博途在线诊断,遇到通信层面的问题就抓瞎。实际上Wireshark抓包能清晰看到每台PLC发送数据的周期性、数据包大小、是否存在重传。有一次排查一个偶尔掉线的bug,博途诊断半天没结果,用Wireshark一看,发现有一台从站在每隔几秒重传同一个数据包,顺藤摸瓜找到是网络线序压接问题。

6. 竞赛评分与答辩准备的实战经验

6.1 评分演示容易丢分的细节

评委现场评分时,不会只看你PPT上写得有多好,而是现场跑系统的实际表现。我总结了几个容易丢分的细节:

  • 电梯开关门逻辑不符合真实需求:门开着的时间必须可调,关门遇到阻挡必须立即开门。有些队伍为了赶进度,门动作写得很快,看起来“效率”很高,但电梯模型的机械惯性会带来很大的顿挫感,画面观感不好,也会被评委质疑工程合理性。
  • 缺少数码管/指示灯状态显示:模型电梯通常配了指示灯显示当前楼层、运行方向、开关门状态。如果程序没有把状态同步到这些指示输出上,评委无法直观看到电梯正在做什么,减分很直观。
  • 急停恢复逻辑不完整:急停按下后,电梯必须进入安全状态,急停复位后必须从空闲状态重新开始,不能直接继续原来的任务。比赛现场我见过有队伍急停复位后电梯自己乱跑,这个场景非常影响评分。

6.2 答辩时如何讲清楚调度算法

答辩环节很多队伍栽在“只讲功能不讲设计理由”。评委问“为什么选择这个调度算法”时,如果回答“因为大家都用这个”,基本就告别高分了。

我的答辩思路是把算法当成一个工程决策来讲述:

  • 先列出候选方案:固定分区、最小等待时间、能量优化调度。
  • 说明每种方案的优缺点和适用场景。
  • 结合竞赛模型的特点(六部梯、十层、随机客流、通信实时性要求)说明为什么选ETA,以及ETA参数如何通过测试整定。

另外一定要准备对比数据。我在演示前专门跑了两组测试:一组用固定分区,一组用ETA动态派梯,各灌入100个随机召唤,统计平均候梯时间。最终ETA方案平均候梯时间比固定分区缩短了约28%。这个数据放出来,比任何口头描述都有说服力。

6.3 一份能支撑长期维护的项目文档怎么写

比赛结束后很多队伍的程序就烂在U盘里了,但优秀的工程习惯应该是让程序具有可延续性。我的建议是项目文档至少包含三部分:系统架构图、通信地址表、算法参数说明。

通信地址表尤其重要。比赛里所有PLC的IP、通信DB块号、数据结构定义,全部要整理成一张表。我记得决赛现场有一个队伍临时改IP,改完之后有几台电梯通信不上,主控老师过来帮忙排查,结果他们自己都说不清楚哪些IP是哪些电梯,现场非常混乱。提前做好地址表,这种问题不存在。

7. 最后补充:想在这个赛题上拿高分的三个建议

坦白说,如果你现在刚开始接触这个赛题,我建议你先不要急着写群控算法。先把单台S7-1200控制一部电梯的逻辑写透,跑通,再加上通信。一次通信连接调通,再做第二台、第三台,直到六台全部联网。群控调度再厉害,底层单梯逻辑不稳定,一切都是空中楼阁。

第二点建议是亲自去现场看一次真实电梯的运行状态。我在参赛前专门去看了小区电梯的开关门时序、平层停车的位置感,尤其是电梯到站时开门瞬间的减速手感。把这些真实体验映射到程序里,参数设计会合理很多。比如关门后启动前的延时,就是看了实物运行才意识到必须加的。

最后一点,关于算法不要追求花哨。比赛时间有限,ETA动态派梯已经足够支撑你拿奖。我见过有队伍想把强化学习装到PLC上,结果模型训练和部署都没跑通,整个系统反而在基础功能上漏洞百出。根据实际需求选合适的算法,把基础功能做到稳定可靠,才是竞赛里更稳妥的策略。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询