1. 项目概述与需求拆解1.1 从现场需求说起为什么需要“编号启动”先聊一个很常见的现场场景。车间里一排电机比如水泵、风机、传送带驱动操作工要通过触摸屏或者柜门按钮启停它们。如果只有几台一对一启停按钮完全够用梯形图加起来也快。可一旦电机数量多起来比如十几个甚至几十个柜门上密密麻麻全是按钮你都不知道哪个按钮管哪台电机调试时挨个核对线号能把人逼疯。这时候就自然想到一种更集中的控制方式——操作员不用直接按下某个物理按钮而是在触摸屏或者上位机里输入一个数字编号比如“输入5然后按启动”设备就知道要启动第5号电机。这就是“编号启动”控制模式。它的本质不是让PLC学会“数数”而是把“电机编号”这个抽象输入翻译成PLC内部实实在在的位M点、Q点、DB位再通过对应的输出回路驱动接触器或变频器最终让目标电机得电运转。我之前做过一个S7-1200的项目客户就是这么要求的车间有十几台小型水泵不要求联动不要求顺序就是要求“编号启动”和“编号停止”——触摸屏上输一个编号点启动对应水泵转起来点停止对应水泵停下来。用S7-1200做这个逻辑非常合适CPU的运算能力绰绰有余而且TIA Portal里写逻辑也清晰。这篇文章就把这个项目的设计思路、梯形图实现、常见坑点完整拆开聊一遍给正在做类似需求的朋友一个参考。1.2 用S7-1200做这个控制的核心优势选择S7-1200而不是直接用S7-200 SMART或者三菱FX有几个实际考量。首先是S7-1200的存储区和数据块管理比老一代PLC更灵活LED指示灯、工艺对象、诊断缓冲区这些功能在调试多电机系统时特别好用——哪台电机没启动起来CPU的诊断缓冲区会直接告诉你I/O访问错误的通道号省去拿万用表一段段量线的痛苦。另一个优势是TIA Portal的编程环境。S7-1200支持梯形图LAD、函数块图FBD、结构化控制语言SCL和语句表STL混合编程。处理“编号启动”这类逻辑要么用一堆比较指令把编号拆开要么直接用SCL写一个CASE语句可读性完全不一样。我一般习惯在OB1里用梯形图做框架在FC或者FB里用SCL做编号解析逻辑两者结合在移植、维护、查错方面都更高效。还有就是通讯扩展能力。一台S7-1200通过Modbus RTU或者Modbus TCP可以带几十台变频器和“编号启动”的需求天然互补——你不但可以“启动编号对应的电机”还可以通过变频器通讯修改编号对应的频率、读取电流做到完整的单机集中监控。这个场景后续我会专门展开。1.3 项目边界做什么不做什么这个项目不涉及变频器通讯、不涉及PID调节、不涉及多段速控制就是纯粹的“数字量输出启停电机”逻辑。控制对象是带接触器控制的异步电机每个电机一个中间继电器PLC输出点接中间继电器线圈中间继电器触点控制接触器接触器主触点控制电机。变频器控制的方式原理相同只要把启动输出接到变频器的数字量输入端子即可。安全保护方面每台电机要有热继电器或者电机保护断路器的辅助触点反馈到PLC的输入点用于过载报警和禁止启动。这个必须做不是可选项——一旦电机过载热继电器动作反馈点断开PLC必须能及时断开输出避免烧电机。咱们做的是设备控制安全底线不能丢。2. 控制方案设计从编号到电机启动的完整映射2.1 三种可行的实现思路对比实现“编号启动”根据硬件配置和编程风格的不同常见有三种方案方案A离散输出映射。每个电机对应一个Q点用一个“编号译码”逻辑把输入的数值和每个Q点对应的编号比较相等则置位输出。这个方案最直观适合控制点数在几十个以内的场景。对于点数特别多的场景会用I/O子模块扩展或远程I/O但逻辑本质不变。方案B移位寄存器实现。类似流水灯思路通过一个首地址把启动脉冲移到对应编号的位。这个方案在老的S7-300里有人用但在S7-1200里逻辑反而绕而且查错不直观。我不会推荐。方案CSCLCASE指令。直接从数学映射角度解决输入编号通过CASE或者IF语句判断编号落在哪个区间然后置位对应的输出。这个方案代码量最小、最清晰特别适合数量多、且编号规划有规律比如1-8对应第一个输出模块9-16对应第二个输出模块的场合。实际项目中我最常用的是方案A的“优化版”用SCL写一个FC传入需要启动的电机编号函数内部用一个FOR循环或者CASE逐一比对返回对应的输出地址索引然后用POKE或者直接访问IO映射的DB块来写输出。不过话说回来如果只是做简单的十几路电机启停也不一定非得上SCL。梯形图里用比较指令完全能做一段一段写下来虽然啰嗦一些但胜在电工师傅看着也容易理解后续维护门槛低。这个取舍要看你项目交付后是谁在维护。工业现场可维护性很多时候比炫技更重要。2.2 编号映射的三种方式物理映射、逻辑映射、动态映射设计“编号启动”前第一个问题是电机编号和PLC输出点之间的对应关系怎么建立物理映射编号和PLC输出通道完全一一对应。比如1号电机对应Q0.02号电机对应Q0.1。这种最简单适合电机布局固定、后期不改动的项目。缺点是如果某台电机检修拆走编号就空了一个坑其他编号不连续。逻辑映射PLC内部建立一个DB块DB里有数组数组的下标是电机编号数组的值是该电机对应的输出点地址。也就是说“1号电机对应哪个输出点”不是固定写死的而是通过组态数据配置的。这种方式的优势是灵活电机编号可以自由分配比如现场因为配电柜调整原来3号电机的输出点挪到了第24路只需要改DB里的数据不需要改逻辑代码。这是我最推荐的做法而且S7-1200用DB块数组来干这个事非常顺手。动态映射通过触摸屏或者上位机在线修改映射关系。这种方式灵活过头了一般用于工艺经常调整的场景。对于多数固定设备逻辑映射已经足够。动态映射还有个风险——操作员改错数据导致电机误动作安全上不好把控除非有权限管理否则我不会轻易做。从我实际经验看逻辑映射是性价比最高的方案既要了灵活性又不会把程序搞得太复杂。下面的实现就以逻辑映射为基线来展开。2.3 启动与停止逻辑的状态机设计“编号启动”不能只做一个瞬间的输出动作。完整的电机控制逻辑必须包含状态机停止状态输出为0电机不转。 启动过程收到启动指令对应输出置1电机开始运转。 运行状态输出保持1。 停止过程收到停止指令对应输出置0电机降速停止。 故障状态热继电器动作或反馈丢失输出强制断开并且需要手动复位才能重新启动。在PLC程序里我通常用一个二维数组或者结构体数组来保存每台电机的状态比如DB结构StartCmdBOOL启动命令StopCmdBOOL停止命令RunFbBOOL运行反馈FaultBOOL故障信号OutputBOOL实际输出ModeINT手动/自动模式然后用一个循环或者逐台扫描的逻辑对每台电机执行“状态机处理”。其实这就是一个简化版的“功能块实例化”——如果你用的TIA Portal V13以上版本完全可以直接写一个FB叫MotorControl然后创建多个背景数据块每个电机一个实例。这样代码写一遍重复调用就行。热搜词里提到的“多重实例”就是这个东西后面第三部分我会讲具体怎么组。3. 硬件组态与软件架构3.1 S7-1200的模块化组成架构S7-1200 CPU本身有集成数字量I/O1214C DC/DC/DC这款集成14个数字量输入和10个数字量输出。如果项目规模只有6台电机一个CPU就够如果电机数量多通过添加SM 1222数字量输出模块扩展。先说模块化架构。S7-1200的组成典型如下CPU模块含电源、集成I/O、PROFINET口信号板SB放在CPU前盖板里可扩展少量I/O或通讯口信号模块SM插在CPU左侧扩展数字量/模拟量I/O通讯模块CM插在CPU左侧扩展RS232/RS485/Profibus等通讯通讯处理器CP插在CPU左侧扩展PROFINET/PROFIBUS DP等CPU左侧最多可以插8个信号/通讯模块右侧是CPU本体的I/O。组态时在TIA Portal的硬件配置里拖拽即可注意模块版本和固件版本要一致否则编译会报错。对于“编号启动”这个项目IO组态的核心是数字量输出。我会按“每块SM 1222输出16点”来规划每台电机占用一个输出点然后预留至少10%的备用点方便后期增加设备。CPU本身能带多少输出具体依据不同型号而定但128点以内的数字量输出1214C加模块完全够用价格也合理。3.2 TIA Portal项目结构规划在TIA Portal里我一般建议把程序分成以下几个区域OB1主程序循环调用主控制FB。FB_MotorControl单台电机控制功能块包含启动/停止/故障/反馈处理。FB_MotorGroupManage电机组管理功能块处理编号解析查询电机配置循环调用FB_MotorControl。DB_MotorConfig电机配置数据块数组方式存储每台电机的“编号-输出点映射”、参数、当前状态。FC_NumberDecode编号解码函数输入操作员给的编号输出对应的电机索引。HMI变量表和PLC变量表统一规划变量命名方便触摸屏绑定。这种结构的好处是新增一台电机时不用改逻辑只要在DB_MotorConfig里增加一条配置然后硬件组态里增加一个输出点就行。程序维护成本极低。这也是我坚持用“配置驱动逻辑”的主要原因。3.3 多重背景数据块的设计思路热搜词里提到了西门子PLC的多重实例这个和本项目有关系。所谓多重背景Multi-instance是指在一个FB里调用另一个FB被调用的FB的数据存储在主FB的静态变量区而不是生成独立的背景DB。举个实际例子我写了一个FB_MotorControl它内部需要用到定时器、沿检测等如果每台电机生成一个背景DB10台就有10个DB看起来很多但如果我在上层FB_MotorGroupManage里以多重实例方式调用FB_MotorControl那么所有电机的实例数据都集中在这个管理FB的背景DB里数据结构变成一个数组每个数组元素对应一台电机的完整状态。这样做的好处是数据集中查看状态方便。可以方便地用循环或变量索引来处理多台电机。背景DB结构清晰触摸屏或上位机可以按数组索引统一读数据。减少DB数量项目树干净不少。实现上其实就是声明一个“MotorControl实例”作为FB的静态变量类型VAR MotorInst : Array[1..16] of FB_MotorControl; // 多重实例数组 END_VAR然后在代码里用FOR循环或者按索引调用FOR i : 1 TO MotorCount DO MotorInst[i](RunCmd:..., StopCmd:..., Fault:...); END_FOR;这个方法在TIA Portal V14及以上版本完全支持属于正规用法。3.4 变量表命名规范这个项目看着逻辑简单但如果变量命名一塌糊涂调试时一样抓瞎。我给一个基本的命名规范大家可以在自己项目里直接套用电机启动命令Mot_Start_Cmd[编号]例如Mot_Start_Cmd1电机停止命令Mot_Stop_Cmd[编号]电机运行反馈Mot_Run_Fb[编号]电机故障信号Mot_Fault[编号]电机输出地址Mot_Out_Q[编号]手自动模式Sys_Auto_Mode如果用的是DB块数组方式那么变量名还是一样的只是访问时带有数组下标比如MotorDB.Motor[3].StartCmd MotorDB.Motor[3].Output触摸屏上做输入域时HMI变量一般绑定到DB的具体元素这样操作员输入编号后HMI直接调用PLC内部的解析逻辑。4. 核心逻辑实现编号解码与启停控制4.1 输入编号的校验与合法性判断操作员在触摸屏上输入一个编号这个编号未必是合法的。比如一共8台电机编号应该只能填1到8结果操作员填了9或者填了0或者填了负数、非数字这些情况都必须处理如果不校验直接去访问数组下标轻则启动错误的电机重则导致PLC访问越界、程序卡死、CPU进入STOP状态。我在项目中做的校验逻辑主要分三层第一层HMI端的输入限制。触摸屏上把输入域的类型设置为整数范围限定到1到最大编号之间。这能拦截大部分误输入。第二层PLC内的数值范围检查。SCL里写IF #input_number 1 AND #input_number #max_number THEN // 合法编号执行启动 ELSE // 非法编号返回错误代码 END_IF;第三层映射表有效性检查。即使编号在范围内如果该编号对应的输出点被禁用比如维护模式也不能启动。DB配置里我加了一个Enable位只有Enable为TRUE的编号才允许动作。这三层下来基本能杜绝“幽灵启动”。千万不要嫌校验麻烦就直接把输入编号当数组下标用这是大忌。4.2 梯形图实现比较指令陷阱与排除如果不用SCL用梯形图直接做编号解析最常见的做法是|--[ #input_number 1 ]----( Mot_Out_Q0.0 )--| |--[ #input_number 2 ]----( Mot_Out_Q0.1 )--| ...看起来简单但有一个很隐蔽的坑如果启动命令是“沿信号”也就是只在按下启动按钮的那一拍产生一个脉冲那么比较结果和输出线圈之间一定要用置位/复位指令。否则你可以想象这个场景操作员输入编号“5”后按下启动输入编号的保持寄存器一直是5输出点就一直得电。如果操作员随后把编号改成“3”按下了停止按钮可是因为编号不再是55号电机的输出已经自动断了。这变成了“编号决定启停”而不是“命令决定启停”置信度完全不对。正确的逻辑是启动按钮的上升沿加上当前编号的有效性判断置位对应电机的输出位。停止按钮的上升沿复位对应电机的输出位。故障信号动作时也复位对应输出。也就是说编号输入只负责“告诉PLC操作员想操作哪台电机”真正的触发还是来自启动命令的沿信号。这个思路在梯形图里一定不能拧过来。4.3 SCL实现CASE指令的优雅写法如果是SCL代码简洁很多。以一个FC或者FB内部片段为例// 输入参数 // #op_code : INT (1启动, 0停止) // #motor_no : INT (电机编号) CASE #op_code OF 1: // 启动命令 IF #motor_no 1 AND #motor_no #max_no THEN MotorDB.Motor[#motor_no].StartCmd : TRUE; END_IF; 0: // 停止命令 IF #motor_no 1 AND #motor_no #max_no THEN MotorDB.Motor[#motor_no].StopCmd : TRUE; END_IF; END_CASE;然后在下层的FB_MotorControl里处理StartCmd和StopCmd的沿信号// 上升沿检测 #start_edge(CLK : #StartCmd, Q #start_rise); #stop_edge(CLK : #StopCmd, Q #stop_rise); IF #start_rise AND NOT #Fault THEN #Output : TRUE; END_IF; IF #stop_rise OR #Fault THEN #Output : FALSE; END_IF;这样逻辑就完整了操作员的编号输入只是传参启动/停止动作由命令沿触发故障信号具有最高优先权。这里有个额外的细节用置位/复位而不是直接赋值好处是故障复位后输出不会自动恢复需要操作员重新按下启动。这在工业现场是必须的——如果故障消失了电机自己又转起来很容易出安全事故。4.4 故障处理与手动复位机制每台电机都必须有热继电器或马达保护断路器的辅助触点反馈。通常接法热继电器辅助触点常闭点串入接触器控制回路硬线互锁防止PLC异常时电机仍然运行。同时辅助触点信号接入PLC输入点用于程序联锁。PLC程序里IF NOT #FbFault THEN // 正常状态 ELSE #Fault : TRUE; #Output : FALSE; END_IF; // 复位按钮 #reset_edge(CLK : #ResetCmd, Q #reset_rise); IF #reset_rise AND NOT #FbFault THEN #Fault : FALSE; END_IF;注意复位条件是“故障点已恢复且手动按下复位按钮”。如果故障没有消除复位按钮是无效的。这种设计是安全惯例不要省略。另外故障信息要在触摸屏上显示是哪台电机什么故障这样操作员不用查柜子。S7-1200自带的报警指令块用起来也方便把每台电机的故障信号用Program alarm触发HMI上就能弹出报警记录。4.5 顺起逆停与时间间隔联锁热搜词里提到了“西门子s7-1200顺起逆停”就是有几台设备要求启动时按顺序1、2、3依次启动停止时按3、2、1依次停止防止管道压力突变或者其他工艺问题。这个需求在电机编号启动的基础上很容易扩展。做法是在上层组管理FB里加入顺序逻辑// 启动顺序 IF #auto_start_all THEN FOR i : 1 TO #max_no DO IF #allow_start[i] THEN MotorDB.Motor[i].StartCmd : TRUE; EXIT; // 一次只启动一台启动完这台后结束本轮 END_IF; END_FOR; END_IF;实际项目中还会加“延时继电器”来保证两台电机启动的间隔比如每台电机启动间隔5秒防止多台大功率电机同时启动导致变压器过载。S7-1200用TON定时器非常方便#ton_interval(IN:#start_all_active, PT:#interval_time); IF #ton_interval.Q THEN // 触发下一台 END_IF;这个话题展开又够一篇长文了这里点到为止。你只要知道“编号启动”不是孤立的它可以和顺序启动、联锁逻辑、变频器控制无缝整合。5. 实操过程从组态到调试的关键环节5.1 TIA Portal项目创建与硬件组态步骤下面是我实际做项目的操作流程一步步来。第一步创建TIA Portal项目。打开TIA Portal V16或V17我用的V16新版本操作类似在“创建新项目”中输入项目名比如“MotorNumberControl”。第二步添加设备。左侧项目树里双击“添加新设备”选择“控制器→SIMATIC S7-1200→CPU”选型注意实际订货号和固件版本。以1214C DC/DC/DC为例订货号是6ES7 214-1AG40-0XB0。如果固件不一致后续下载时可能报错要么升级固件要么在组态里选择兼容版本。第三步组态数字量输出模块。如果需要SM 1222从硬件目录里拖拽到CPU左侧的插槽。SM 1222有16点继电器输出6ES7 222-1HH32和16点晶体管输出版本继电器输出的负载能力强一些。电机控制用继电器输出足够了但注意继电器输出有机械寿命频繁启停虽然不至于很快坏但定期检查是必要的。第四步设置PROFINET/以太网参数。双击CPU在“PROFINET接口”里设置IP地址比如192.168.0.10子网掩码255.255.255.0。如果现场有多台PLCIP地址规划要提前做好别都配成一样的。建议IP地址和电机编号或者柜号有一定关联方便记忆。第五步PLC变量表的规划。在PLC变量表里建立数字量输入、数字量输出的符号名。我习惯直接用符号编程而不是绝对地址这样程序可读性强很多。比如%I0.0 - Mot1_Fault%I0.1 - Mot2_Fault%Q0.0 - Mot1_Out%Q0.1 - Mot2_Out第六步编写程序。先建FB_MotorControl然后建DB_MotorConfig最后建FB_MotorGroupManageOB1里调用。5.2 FB_MotorControl功能块的接口设计与代码示例以单台电机控制为例做一个可复用的FB本体FUNCTION_BLOCK FB_MotorControl VAR_INPUT StartCmd : BOOL; // 启动命令 StopCmd : BOOL; // 停止命令 RunFb : BOOL; // 运行反馈接触器辅助触点 FaultIn : BOOL; // 故障信号热继电器常闭点 ResetCmd : BOOL; // 复位命令 END_VAR VAR_OUTPUT OutQ : BOOL; // 输出到接触器/变频器 IsRunning: BOOL; // 是否在运行 Fault : BOOL; // 故障指示 END_VAR VAR start_edge : R_TRIG; stop_edge : R_TRIG; reset_edge : R_TRIG; END_VAR代码逻辑#start_edge(CLK : #StartCmd); #stop_edge(CLK : #StopCmd); #reset_edge(CLK : #ResetCmd); IF #start_edge.Q AND NOT #Fault THEN #OutQ : TRUE; END_IF; IF #stop_edge.Q OR #FaultIn OR #Fault THEN #OutQ : FALSE; END_IF; // 故障锁存 IF #FaultIn AND NOT #reset_edge.Q THEN #Fault : TRUE; ELSIF #reset_edge.Q AND NOT #FaultIn THEN #Fault : FALSE; END_IF; #IsRunning : #OutQ AND #RunFb;注释OutQ置位后如果运行反馈RunFb迟迟没有到位说明接触器可能没吸合或者电机回路有问题这时IsRunning一直为FALSE可以在上位机做“启动失败报警”。这个反馈对于判断现场故障很有价值建议有条件都接上。5.3 编号解析与组合调用DB数组是核心DB_MotorConfig的结构体设计我建议这样TYPE MotorStruct STRUCT Number : INT; // 电机编号 Enable : BOOL; // 是否启用 OutAddr : INT; // 输出点索引比如1对应Q0.0 RunFbAddr : INT; // 反馈点索引 FaultAddr: INT; // 故障点索引 StartCmd : BOOL; // 命令 StopCmd : BOOL; Mode : INT; // 0手动1自动 END_STRUCT END_TYPE然后DB里定义MotorArray : ARRAY[1..16] OF MotorStruct这里“OutAddr”并不直接是I/O地址而是一个索引。实际输出访问时可以用S7-1200的PEEK/POKE指令或者更简单地把数字量输出通道映射到一个EW/AB字节然后通过索引操作。比如8台电机用一个字节的8个位那么OutputByte_1.%X0 : MotorDB.MotorArray[1].OutQ;其实最简便的方法是不用间接寻址直接在程序里指定Mot1_Out : MotorDB.MotorArray[1].OutQ; Mot2_Out : MotorDB.MotorArray[2].OutQ;如果电机数量不多比如不超过32台这种显式映射完全没问题代码量也还好。如果数量很大那再上间接寻址。我经常会遇到有人问为什么不直接用“数组下标编号”来做映射因为实际项目里编号和物理通道往往不是连续对应的。比如厂区改造1号电机挪到新的配电柜输出点变到了第9路。如果用数组下标直接映射那就得把数组重新排序严重影响后续维护。而加了OutAddr这一层映射之后只需要改数据库里的一个数字逻辑完全不用动。这就是之前说的“逻辑映射”的价值所在。5.4 触摸屏编号输入与操作画面设计如果项目带HMI比如西门子KTP700或MTP1000操作画面可以做得非常简单直观画面上有一个“电机编号”输入域一个“启动”按钮一个“停止”按钮一个“复位”按钮一个故障报警指示灯区。操作员输入编号后按下启动PLC收到命令并执行对应电机的启动。需要注意输入域的数据类型要和PLC变量一致。比如PLC里编号变量是INTHMI里也要选“INT”类型否则通讯时数据类型不匹配显示乱码或者无法输入。另外我习惯在HMI上显示当前编号对应的电机状态。比如操作员输入了5画面上立即显示“5号电机运行中/停止/故障”这样操作员不用傻傻按下按钮才知道结果。这个可以通过HMI的多状态显示域绑定DB里MotorArray[5].IsRunning来实现。还有一点HMI按钮的“按下/释放”事件在标准做法里是把“按下”作为启动信号的置位“释放”作为复位。但我们的逻辑是沿触发所以更推荐的做法是HMI按钮“按下”时置位一个布尔变量PLC检测该布尔变量的上升沿后执行启动然后复位该布尔变量。如果用HMI自带的“置位”按钮功能按一下变量为TRUE再按一下为FALSE这也能用但容易造成误操作——操作员以为按了启动实际是取消命令。所以我在项目里会做一个“沿触发”转换而不是直接拿按钮状态来控制电机。5.5 离线仿真与在线调试TIA Portal带了S7-PLCSIM仿真器调试阶段强烈建议先用仿真跑一遍逻辑再去现场联调。仿真时注意几件事S7-PLCSIM仿真的是PLC的逻辑不仿真真实I/O接线。所以数字量输入需要手动强制输出状态要监视。仿真模式下可以用“仿真表”强制变量模拟热继电器故障、运行反馈丢失等场景验证故障锁存和复位逻辑。如果用了S7-1200的PROFINET或者Modbus通讯功能S7-PLCSIM不一定能完全模拟特别是第三方设备通讯这部分要现场联调。在线联调时我用得最多的工具是TIA Portal里的“监控表”Watch table。把关键变量拖进去电机输出位、启动/停止命令、故障标志、反馈信号强制或者修改数值观察逻辑是否符合预期。还有一个非常实用的小技巧在TIA Portal里右键变量选择“修改为1”或“修改为0”可以快速模拟输入信号。比如我要模拟1号电机热继电器故障直接修改Mot1_Fault为TRUE观察OutQ是否变为FALSE、Fault是否锁存。整个调试效率高很多。6. 常见问题与排查技巧实录6.1 电机编号输入后无响应这个是最容易遇到的问题。通常排查顺序如下第一确认操作员输入的编号在合法范围内。很多情况就是输了个超范围的编号HMI上又没提示感觉“按键没反应”。第二检查PLC变量是否成功接收HMI的数据。联机后在监控表里看输入域绑定的变量的值如果一直为0要么是HMI变量绑定错误要么是通讯中断。第三检查启动命令的沿检测是否触发。在监控表里看FB里的start_rise变量如果一直FALSE说明命令信号没有产生上升沿。可能原因HMI按钮的“释放”事件把命令变量复位了导致PLC根本没捕捉到“0→1”的变化。这是HMI编程时最容易犯的毛病——按下置位释放又复位命令信号持续时间太短PLC扫描周期没赶上。解决方法要么PLC的扫描周期足够快S7-1200默认扫描周期通常几毫秒基本能捕捉到HMI的置位信号要么HMI按钮改成“置位后保持由PLC复位”保证信号宽度足够。还有一个情况如果通讯周期正好和扫描周期撞上偶发丢信号。稳妥的办法是用HMI的“事件-按下时取反”或者干脆在HMI里做“多重按下确认”防止误触。不过对于电机启停这种操作我一般不建议做复杂确认操作员在触摸屏上按错是正常的关键是启动后能立刻看到状态反馈可以马上停止。6.2 DB块地址偏移导致HMI访问错误S7-1200的DB块默认有“优化的块访问”属性。这个属性打开后DB变量没有固定的偏移地址HMI访问时通过符号名访问问题不大。但如果程序里用了间接寻址或者老的HMI项目不支持符号访问就要小心。有一种常见报错HMI连接PLC变量时提示“变量不存在”或“地址区不合法”。多半原因DB块的“优化块访问”勾选状态和HMI期望的不一致。变量类型不匹配。HMI里声明的是WORDPLC里是INT符号名一样也会报错。背景DB被多重调用覆盖导致HMI读取的DB不是目标实例。我的建议对于HMI需要直接访问的DB可以在属性里去掉“优化的块访问”勾选这样地址变成确定的比如DB1.DBX0.0HMI直接按地址访问也没问题。但注意改了这个选项之后如果DB结构变化偏移地址会乱需要重新生成。6.3 多台电机启动时电流冲击过大如果现场是多台大功率电机同时启动变压器或发电机可能支撑不住电压骤降甚至跳闸。即使用编号启动操作员也有可能快速连续输入多个编号启动多台电机。我见过一个案例操作员在触摸屏上点了4台15kW水泵的启动间隔不到1秒结果车间照明明显闪烁了一下变压器嗡嗡叫吓得业主赶紧喊停。解决思路是在PLC里加“最大同时运行电机数”限制。比如设定最多同时运行3台当第4台启动请求来时程序直接拒绝并提示“运行数量已满”。这个限制在自动工艺控制里很常用在手动编号启动场景下同样适用。还有一种做法是“启动队列”或“启动延时”。把启动请求排队每5秒释放一台。这其实就是前面提到的顺起逆停的变种按启动先来后到排序排队执行。S7-1200做这个逻辑不难数据块的数组加几个标志位就行。6.4 触摸屏通讯突然中断S7-1200自带PROFINET口和触摸屏组网时最常用的是PROFINET或者普通工业以太网。如果触摸屏和PLC之间的通讯时断时续常见原因IP地址冲突。检查现场是否有别的设备占了同一个IP。网线或者交换机端口故障。S7-1200的网口不是隔离型的现场干扰大或者接地不好可能导致通讯异常。HMI项目里PLC连接的“访问点”选错或者“机架号/插槽号”配置不对。如果组态的是S7-1200一般不需要填这些参数但个别HMI型号有默认值比如机架0插槽0有时候实际是插槽1。我处理过一例也是奇怪得很触摸屏偶尔弹通讯错误但过一两秒自己恢复。后来查了半天发现是交换机的一个端口老化偶尔丢包。换了个端口就好了。这种隐性故障现场排查起来确实费时。所以做项目时网络关键链路尽量用工业级交换机有些地方省不得。6.5 TIA Project里FB调用时DB块无法分配热搜词里有一条“博途调用FB时填不了DB块”很典型。新手常遇到的情况在OB1里调用一个FB系统要求分配背景DB但下拉列表是空的没法新建背景。常见原因FB的接口声明没有完成比如某个VAR_INPUT缺少数据类型。FB属性里勾选了“在多重实例中调用”这时候不允许生成自己的背景DB只能在另一个FB里以多重实例方式调用。项目处于离线状态且对应FB没有编译。先把该FB单独编译一遍再回OB1调用。解决办法就按上面三点检查即可。如果是多重实例模式你不需要也不能生成独立背景DB就这么设计的。6.6 常见问题速查表问题现象可能原因排查与解决编号启动无反应编号超范围 / HMI绑定错误 / 命令沿丢失检查输入范围、监控表看变量值、修改HMI按钮事件逻辑电机启动后不停停止命令没有沿信号 / 输出被外部回路保持接触器自锁检查PLC停止逻辑检查接触器控制回路是否有自锁硬线互锁。故障复位不了故障信号未消除 / 复位逻辑条件不满足检查故障输入点实际状态确认热继电器已复位多台同时启动缺乏数量限制PLC内增加同时运行数量统计和限制HMI通讯中断IP冲突 / 网络故障 / 组态参数错误检查IP、交换机端口、连接参数FB无DB可分配多重实例模式 / 未编译确认FB属性、编译后再调用或改为非多重实例输出点爆掉输出过载 / 感性负载无吸收回路PLC输出加中间继电器继电器线圈两端并联续流二极管或RC吸收接触器线圈两端也加浪涌抑制7. 向更复杂场景扩展变频器通讯与多轴控制7.1 编号启动加上变频器从启停到调速前面的逻辑只处理了接触器控制如果电机要调速就得换成变频器了。热搜词里“abb变频器与西门子plc”、“西门子plc与施耐德eta系列变频器modbus通讯”这类词说明大家实际项目中经常要把PLC和变频器联动。把编号启动和变频器控制结合起来逻辑会稍复杂一些。除了启停数字量信号外还要考虑频率给定方式。最省接线的方式是走通讯PLC通过Modbus RTU或者Modbus TCP读写变频器的运行命令、频率设定、电流反馈。S7-1200做Modbus通讯很方便用MB_COMM_LOAD和MB_MASTER指令或者Modbus TCP的MB_CLIENT。不过要注意S7-1200的Modbus RTU需要额外的通讯模块比如CM1241 RS485或者CB1241CPU本体没有串口。有人问一台PLC控制32台变频器Modbus通讯可行吗硬件上是可以的RS485理论上最多挂32个节点加中继可以更多Modbus TCP理论上更多。但关键是通讯轮询周期。每台变频器读一组数据写一组指令算下来32台每台通讯时间按50ms算一轮就1.6秒。如果你需要同时监视32台变频器的实时电流这个刷新速度可能不够。所以实际项目中会做“分组轮询”关键数据比如运行状态、故障高频刷新非关键数据比如累计电量低频刷新必要时划分优先级。7.2 32台变频器轮询程序的基本框架轮询框架大致如下建立一个DB数组每个元素存一台变频器的读写数据。用一个INT变量做轮询指针每个扫描周期或定时触发轮到一个变频器执行MB_MASTER/MB_CLIENT请求。通信完成后指针加1到末尾回绕。每台变频器有独立的超时计数超时则标记通讯故障但不影响其他变频器的轮询。这里有一个容易踩的坑MB_MASTER或MB_CLIENT是异步指令调用一次不一定立即完成需要检查“完成位”和“错误位”。有些新手直接在一个扫描周期里连续调用32次MB_MASTER以为能并行通讯结果是串行排队搞不好卡死。正确的做法是每次调用一个完成后再调用下一个。具体的轮询指令时序网上资料很多项目里照抄时要注意指令的“REQ”必须用沿信号触发否则会持续发送请求导致总线拥堵。7.3 通过PROFINET与变频器通讯如果现场变频器支持PROFINET比如西门子G120、SINAMICS V90那么控制方式又不一样了。通过GSD文件组态到TIA Portal里PLC直接以I/O方式访问变频器的控制字、状态字、速度设定值实时性和可靠性比Modbus高很多。S7-1200通过PROFINET控制G120常用的报文是“西门子111报文”这是标准报文包含控制字STW1、状态字ZSW1、速度设定值NSOLL_A等。使用时要严格按照报文格式映射数据控制字里每个位的含义要弄明白比如位0是“ON/OFF1”位1是“OFF2”自由停车位3是“使能运行”不能随便乱写。很多人第一次用111报文时变频器就是转不起来排查下来往往是对控制字的不熟悉。#111报文的控制字结构简要如下位含义Bit0ON/OFF1Bit1OFF2Bit2OFF3Bit3脉冲使能Bit7故障确认Bit10由PLC控制启动时要同时置位Bit0、Bit1、Bit2、Bit3并且按顺序来不能一上来就全写1。停止时要有对应的斜坡停车时序。这些细节都是调试中容易卡壳的地方。7.4 编码器反馈与视觉/仪表联动再往大了说电机编号启动只是底层设备控制工厂里往往还要上游传感器、仪表联动。热搜词里有“视觉与PLC通讯”、“C#和西门子PLC通讯”这些都是扩展方向。如果视觉系统需要和PLC交换数据最简单的方案是走PROFINET或者Socket通讯把视觉检测结果OK/NG写入PLC然后PLC根据结果决定是否允许下一次编号启动。比如某工位要求上一站视觉检测合格才允许启动对应电机那就在电机启动允许条件里加上“视觉判定结果为OK”。C#和S7-1200通讯一般用的是S7comm协议网上有Sharp7、S7.Net Plus这些开源库。上位机可以读取PLC的状态或者在界面上以更灵活的方式操作电机编号启动。不过上位机介入时要注意PLC侧的控制逻辑必须留有“允许上位机控制”的权限位否则两个操作端容易打架。8. 项目总结与我的几点实操心得结构到这儿正文核心内容已经完整了。最后分享几个我在类似项目里攒下来的经验不一定都写在文档里但对实际交付很有用。第一点电机编号和PLC输出点的映射表一定要在项目交付时同步给电气图。光有PLC程序没有点表后续维护电工根本玩不转。我每次都会生成一张“电机编号-柜内中间继电器-接触器-PLC输出点-热继电器反馈点”的对应表交给业主存档。这个东西比程序还值钱。第二点沿信号处理。在S7-1200里用R_TRIG、F_TRIG这类指令块是处理沿的最稳方式直接比较当前值和上次值虽然也能实现但代码冗余且容易出错。建议统一用沿检测指令块。第三点程序要写注释。TIA Portal支持在程序段里写注释不要嫌麻烦。尤其SCL代码一段复杂逻辑过了半年再回头看没注释就是天书。这个习惯在项目多的时候尤其实用。第四点测试一定要全面。仿真通过只是第一步现场联调要从单机测试到多机测试逐步来。先手动强制输出点确认每个中间继电器动作正确然后通过编号启动测试每台电机最后才做联锁和故障模拟测试。特别是故障模拟有价值但容易被忽略——拉掉热继电器测试反馈确认PLC能锁存故障并停止输出。就这些。S7-1200做电机编号启动核心不是什么高深算法而是清晰的逻辑结构、可靠的信号处理、严谨的故障联锁。把这个基本功打扎实了后续扩展变频器通讯、PROFINET控制、上位机监控都是水到渠成的事。
