2026/10/16 15:08:27

单步六层电梯PLC控制实战:基于博图V15.1与SCL状态机

单步六层电梯PLC控制实战:基于博图V15.1与SCL状态机 简介面向工业自动化与PLC编程学习者这份基于博图V15.1环境构建的六层电梯单步控制项目专注解决多层呼叫顺次响应、反向呼叫无效、同层重新计时等经典调度逻辑相比复杂联控更利于教学演示可作为课程设计、技能竞赛或自动化入门工程的可直接参考方案。压缩包共52个文件以项目工程文件plf、ap15_1为核心配合结构化配置与程序块xml、db、cfs以及仿真、索引等辅助数据hsf、dat、idx整体约7.95MB目录结构清晰从工程载入到程序查找均较方便且保留原始组织方式便于逐项核验。控制逻辑覆盖复位停靠一层、启动后指示灯与箭头切换、上升、下降、停止状态间的互锁处理、多楼层按高低顺序逐层运行、运行中反向呼叫无效、停车后再次呼叫重新计时、右端灯管实时显示层数等关键细节通过程序块可逐段学习顺控思路与计时应用。已有875人学习下载适合初学博图PLC的学生对照完整项目理解电梯调度逻辑也适合需要实现类似功能的自动化工程师借鉴。1. 单步六层电梯博图V15.1是入门PLC项目里性价比最高的一个看到“单步六层电梯博图V15.1”这个标题先说一个反常识的结论这个项目真正的难点不在楼层多而在状态多。六层楼的状态组合有几十种但人的大脑一次只能处理一个状态转换。单步控制的价值就是强制把问题切成“一步一动”每一拍只做一件事选目标、运行一层、停车、开门、关门。用博图V15.1把它完整做一遍数据块、函数块、SCL、PLCSIM仿真都能串起来。适合三类人准备入行PLC调试的、自动化专业做课程设计的、以及想验证自己对地址映射和互锁设计理解的下厂工程师。2. 博图V15.1硬件组态与I/O分配先把地址定下来再写程序写电梯程序最忌讳一上来就拖程序块。PLC逻辑写得再漂亮I/O地址错一个到现场全部得重来。我在博图V15.1里做这个项目的固定顺序是先算点数再选CPU再分配地址最后才建程序块。这个顺序看着啰嗦但能省掉后面一大半的排查时间。2.1 选CPU与扩展模块按DI/DO点数倒推六层电梯到底需要多少输入输出取决于你采用哪种信号模型。这里按最常见的“每层平层传感器 每层厅外呼叫 轿厢六选层按钮”来统计平层传感信号6个DI厅外呼叫按钮按一层上呼、六层下呼、中间层上下双呼计算共10个DI轿厢内选层按钮6个DI开门与关门按钮2个DI开关门到位开关2个DI急停1个DI合计27个DI。输出侧上/下行接触器、开门/关门继电器是4个DO楼层指示按三位二进制编码占3个DO运行指示灯1个DO合计8个DO。按这个点数倒推最合适的CPU是S7-1200家族里的1214C DC/DC/DC。它本体自带14个DI和10个DODI不够用右侧加一块SM 1221十六点数字量输入扩展模块DI总量到30点富余3点给检修开关和门区信号。选1214C还有一个实际理由博图V15.1对它的支持最成熟SCL语言里数组、FOR循环、CASE状态机都能直接用比用梯形图写状态转移顺手得多。如果坚持用200 SMART那套路线编程软件都不同和博图V15.1根本对不上。2.2 I/O地址分配表四类信号全部落到PLC在博图V15.1的设备组态里本体输入默认从I0.0开始排扩展模块插在CPU右侧地址从I2.0起排。下面这张表是我实际用过的一版分配新建项目可以直接抄信号类别信号说明PLC地址备注平层检测一层至六层平层传感器I0.0 ~ I0.5只有电梯处于该层位置时为TRUE厅外呼叫一层上行I0.6一层只有上行按钮厅外呼叫二层上行 / 二层下行I0.7 / I1.0中间层双按钮厅外呼叫三层上行 / 三层下行I1.1 / I1.2厅外呼叫四层上行 / 四层下行I1.3 / I1.4厅外呼叫五层上行 / 五层下行I1.5 / I2.0厅外呼叫六层下行I2.1六层只有下行按钮轿厢指令轿厢选层一至六I2.2 ~ I2.7轿厢内楼层按钮开关门开门按钮 / 关门按钮I3.0 / I3.1轿厢内按钮边沿有效开关门开门到位 / 关门到位I3.2 / I3.3门极限开关安全急停I3.4常闭触点断开为急停输出上行接触器 / 下行接触器Q0.0 / Q0.1软件互锁硬件再加机械互锁输出开门继电器 / 关门继电器Q0.2 / Q0.3用脉冲触发不用电平触发输出楼层指示三位二进制Q0.4 ~ Q0.6对应1~6层编码输出运行指示灯Q0.7电梯运行时点亮这张表里最容易被忽略的是急停的常闭逻辑。急停按钮是常闭触点PLC读到的是TRUE表示正常断开才表示故障。新手容易按“按下为TRUE”去处理结果急停按钮一按程序反而正常运行方向完全反了。2.3 组态时先调好的三个参数第一个是CPU的IP地址。博图V15.1下载程序、PLCSIM仿真、HMI通信都走以太网新建项目就固定一个IP比如192.168.0.10子网掩码255.255.255.0。PLCSIM仿真时虚拟网卡沿用同一个IP省得每次仿真前改来改去。第二个是DI滤波时间。S7-1200的数字量输入默认滤波时间按CPU型号走一般几毫秒到几十毫秒。平层信号来自机械位置的感应开关最容易在楼层分界处反复通断滤波时间调大到10ms以上能吃掉大部分抖动。但滤波和响应速度是矛盾的太大的滤波会让PLC对真实平层的识别变慢建议取10ms到20ms之间够用又不会让运行过程拖沓。第三个是保持性设置。电梯掉电后当前楼层和目标楼层如果丢失上电后整套逻辑就不知道轿厢在哪得重新“寻址”这在现场很烦。在博图V15.1里选中存放楼层信息的DB右键属性把“保持性”勾上掉电再上电时当前楼层还在电梯直接恢复运行。坚持用保持性DB是做过现场维护的人一定会提的建议。3. 单步控制逻辑六层电梯的状态机与方向判定I/O分完接下来是核心问题这个“单步”到底怎么理解。前面几章都在准备工具从这一章开始才真正进入电梯控制的设计。3.1 单步的定义一次只走一个目标楼层单步模式区别于集选模式的核心就一句话任何时刻系统只认一个目标楼层一次运行任务只服务这个目标。运行途中经过其他有呼叫的楼层不停。比如电梯在一层三层和五层同时有呼叫单步逻辑先选最近的三层运行到三层、开门、上下客、关门然后重新计算五层为目标再跑一趟。我一般建议初学者先做单步再做集选原因很直接单步把“瞬时只有一个目标”的约束写死在逻辑里需要处理的互锁条件少出问题容易倒回去查。等五态状态机调顺了再往集选里加“顺向截停”条件思路不会乱。直接一上来就做集选很容易被方向优先和截停逻辑绕晕最后哪层都不停。3.2 呼叫登记与清除规则呼叫登记分两类轿厢内选层按钮和厅外呼叫按钮。SCL里用两个数组保存登记位car_call[1..6]和hall_call[1..6]。按钮按下置位服务完成后清除。这里最容易踩坑的是清除规则。单步模式下我建议电梯到达目标楼层并开门后清除该楼层的轿内登记和厅外呼叫。理由很简单既然已经开到这个楼层无论乘客从轿内选的还是从厅外呼的都该在这一层上下客了登记位留着只会让系统二次响应同一层。如果上、下呼叫分开采集这一步可以按层全清省得判断方向后面避坑章还会专门讲一次。3.3 目标楼层计算最近优先上行优先目标计算我用“最近优先”在所有已登记的呼叫楼层里选和当前楼层距离最短的一个。SCL里一个FOR循环加绝对值就能解决。距离相同时比如电梯在3层、2层和4层同时呼叫我习惯让上行优先也就是先选高层。这样更符合使用习惯避免轿厢被上下呼梯反复折腾。方向判定很直接目标楼层大于当前楼层方向为上小于当前方向为下等于当前无需运行直接进开门状态。三个方向值用整数1、-1、0表示在SCL里用INT类型操作比用枚举方便写入DB后监控也直观。3.4 五态状态机状态转移条件表整个电梯程序的骨架是状态机。我用DB里的整数status表示状态0待机、1运行、2开门、3关门、4急停。转移条件分两条事业部写清当前状态触发条件下一状态动作待机存在有效目标楼层且关门到位、急停未触发运行启动方向电机运行到达目标楼层且平层信号有效开门停车、清该层登记开门开门延时结束或手动按关门按钮关门开门继电器断开关门关门到位且没有新目标待机关门继电器断开关门关门到位但存在新目标运行直接转入运行任意状态急停触发急停切断全部输出SCL里用CASE语句实现状态转移比梯形图一坨线圈清晰得多。这个项目的代码量不大真正的难点就在状态转移条件的边界平层信号一直没到怎么办开门过程中被呼走怎么办关门没到位又来了呼叫怎么办。这些边界只能一个个在仿真里试出来这也是下一章写程序时重点处理的地方。4. 用SCL把单步逻辑写进博图V15.1核心程序块逐个拆这一章直接给能抄的代码。我在博图V15.1里新建的是S7-1200项目程序语言全部选SCL。相比梯形图SCL处理数组、FOR循环和CASE状态机顺手得多代码量能少一半。4.1 全局数据块DB_Elevator状态放哪IO映射放哪先建两个全局数据块。第一个叫DB_Elevator存放电梯全部运行状态当前楼层、目标楼层、方向、登记数组、平层状态、门限位等。第二个建议做IO映射块把物理IO地址统一放到一块程序逻辑只读映射变量不直接碰IO地址以后改硬件接线不用动逻辑代码。// DB_Elevator 全局数据块 status : INT : 0; // 0待机 1运行 2开门 3关门 4急停 current_floor : INT : 1; // 当前楼层掉电后从保持区恢复 target_floor : INT : 1; // 目标楼层 direction : INT : 0; // 1上行 -1下行 0无方向 car_call : ARRAY[1..6] OF BOOL; // 轿内选层登记 hall_call : ARRAY[1..6] OF BOOL; // 厅外呼叫登记 car_btn_prev : ARRAY[1..6] OF BOOL; // 轿内按钮上周期状态 hall_btn_prev : ARRAY[1..6] OF BOOL; // 厅外按钮上周期状态 floor_sensor : ARRAY[1..6] OF BOOL; // 平层传感器状态 door_open_limit : BOOL; // 开门到位 door_close_limit : BOOL; // 关门到位 door_timer_elapsed : BOOL; // 开门延时到current_floor和target_floor在DB属性里勾上保持性掉电不丢。其他运行态变量不需要保持上电自动归零反而更安全。比如status上电后回到0待机比停在运行状态安全得多。4.2 FC_CallReg用上升沿做呼叫登记按钮信号不能直接置位登记位否则按钮按住的每个扫描周期都会重复置位。这里用“上一周期状态”做边沿检测比R_TRIG好懂而且在FC里不会出现没法实例化边沿对象的问题。// FC_CallReg // 输入car_btn[1..6]、hall_btn[1..6] 来自IO映射块 // 动作按钮上升沿时置位登记位 VAR_INPUT car_btn : ARRAY[1..6] OF BOOL; hall_btn : ARRAY[1..6] OF BOOL; END_VAR VAR_TEMP i : INT; END_VAR FOR i : 1 TO 6 DO // 轿内选层按钮上升沿有效 IF #car_btn[i] AND NOT DB_Elevator.car_btn_prev[i] THEN DB_Elevator.car_call[i] : TRUE; END_IF; DB_Elevator.car_btn_prev[i] : #car_btn[i]; // 厅外呼叫按钮上升沿有效 IF #hall_btn[i] AND NOT DB_Elevator.hall_btn_prev[i] THEN DB_Elevator.hall_call[i] : TRUE; END_IF; DB_Elevator.hall_btn_prev[i] : #hall_btn[i]; END_FOR;这段逻辑本身没有玄机核心是“比较上周期状态”这个动作。上一周期是FALSE、这一周期是TRUE说明按钮刚被按下只在此刻置位。之后按钮一直按住前后周期都为TRUE条件不成立不会重复登记。car_btn_prev和hall_btn_prev两个数组必须放在DB里因为FC执行完不保存局部变量上一个扫描周期的信息只能靠DB记住。4.3 FC_TargetCalc最近目标与方向判定目标计算是单步逻辑的主心骨。规则是最近优先距离相同时上行优先。SCL写出来很紧凑// FC_TargetCalc // 依赖DB_Elevator中的登记数组和当前楼层 // 输出目标楼层和方向写入DB_Elevator VAR_TEMP i : INT; dist : INT; min_dist : INT : 999; END_VAR // 第一步在所有登记楼层中找最近目标 FOR i : 1 TO 6 DO IF DB_Elevator.car_call[i] OR DB_Elevator.hall_call[i] THEN dist : ABS(i - DB_Elevator.current_floor); IF dist min_dist THEN min_dist : dist; DB_Elevator.target_floor : i; END_IF; END_IF; END_FOR; // 第二步方向判定 IF DB_Elevator.target_floor DB_Elevator.current_floor THEN DB_Elevator.direction : 1; ELSIF DB_Elevator.target_floor DB_Elevator.current_floor THEN DB_Elevator.direction : -1; ELSE DB_Elevator.direction : 0; END_IF;min_dist初值设成999保证至少有一个登记楼层时必然能更新target_floor。所有呼叫都清除后target_floor停留在最后一次目标direction归0电梯自然进入待机。这里要特意说明“距离相等时选高层”的实现SCL的FOR循环从小到大扫描dist min_dist是严格小于所以当2层和4层距离相等时先扫描到的2层先被选中不会自动实现上行优先。想要上行优先需要把条件改成dist min_dist这样后扫描到的高层会覆盖为新的目标。这一点在项目里调过的人都懂一个符号就是两种运行习惯。4.4 FC_MotionCtrl运行条件与平层停车运行控制要综合方向、平层、门限位和急停四个条件。输出用接口参数传递方便在OB1里接线// FC_MotionCtrl // 输出motor_up、motor_down、door_open、door_close VAR_INPUT emergency_stop : BOOL; // 急停信号TRUE为正常 END_VAR VAR_OUTPUT motor_up : BOOL; motor_down : BOOL; door_open : BOOL; door_close : BOOL; END_VAR // 状态 1运行 IF DB_Elevator.status 1 THEN // 运行前提门已关好、急停未触发 IF DB_Elevator.door_close_limit AND #emergency_stop THEN // 方向输出带互锁 motor_up : DB_Elevator.direction 1 AND NOT motor_down; motor_down : DB_Elevator.direction -1 AND NOT motor_up; ELSE DB_Elevator.status : 4; // 门未关好或急停进故障 END_IF; // 到目标层平层停车 IF DB_Elevator.floor_sensor[DB_Elevator.target_floor] THEN motor_up : FALSE; motor_down : FALSE; DB_Elevator.status : 2; // 转开门 // 清除当前楼层登记轿内和厅外一起清 DB_Elevator.car_call[DB_Elevator.target_floor] : FALSE; DB_Elevator.hall_call[DB_Elevator.target_floor] : FALSE; END_IF; END_IF; // 状态 2开门 IF DB_Elevator.status 2 THEN door_open : TRUE; door_close : FALSE; END_IF; // 状态 3关门 IF DB_Elevator.status 3 THEN door_open : FALSE; door_close : TRUE; END_IF;motor_up那一行做了互锁方向为上且motor_down为FALSE时才允许输出。这是软件层的双保险后面避坑章还会强调硬件接触器也要机械互锁。平层停车判断直接读目标楼层的传感器这里隐含一个前提运行过程中每扫描一次就把所有平层信号读一遍只有目标层平层信号变TRUE才停车。仿真时这个信号的手动顺序问题下一章专门讲。开关门部分的开门继电器和关门继电器是互斥的一个为TRUE另一个必定为FALSE。开门延时用OB1里的TON定时器实现5秒到把status从2切到3关门到位后status切回0或直接切到1。我把定时器的调用放在OB1里不在FC里写省得在函数里管理定时器实例的背景数据块。4.5 OB1主程序调用顺序先登记再算目标最后执行OB1主程序按固定顺序调用三个FC顺序不能乱FC_CallReg先更新登记位FC_TargetCalc才能基于最新登记算出目标FC_MotionCtrl再根据目标和方向执行动作。// OB1 主程序 FC_CallReg(car_btn : IO_Input_DB.car_btn, hall_btn : IO_Input_DB.hall_btn); FC_TargetCalc(); FC_MotionCtrl(emergency_stop : IO_Input_DB.emergency_stop, motor_up : IO_Output_DB.motor_up, motor_down : IO_Output_DB.motor_down, door_open : IO_Output_DB.door_open, door_close : IO_Output_DB.door_close);IO_Input_DB和IO_Output_DB是前面说的映射块物理IO地址只在设备组态和映射块里出现一次。FC读写的都是DB变量以后现场改了接线只动映射块逻辑代码一行不改。这一步做得很规整的项目后期维护成本会低很多。5. 单步电梯调试与避坑PLCSIM仿真和五个高频坑程序写完别急着下载实物先在博图V15.1自带的PLCSIM里把状态机完整走一遍。这一步能挡掉一半以上的低级错误。提前说一句PLCSIM终究是个黑匣子很多现场机械问题它模拟不出来但做六层单步电梯的调试它已经够用了。5.1 用PLCSIM仿真单步流程手动给信号的顺序有讲究PLCSIM V15.1下载完程序后仿真窗口会自动列出I/O点。我的习惯是变量表里建好关键变量按“平层信号、呼叫按钮、门到位”的顺序手动给信号模拟完整流程电梯在一层先把平层I0.0置TRUE再给三层呼叫观察FC_TargetCalc算出的target_floor变成3direction变成1然后置关门到位I3.3观察motor_up输出最后把三层平层I0.2置TRUE观察停车和开门。仿真里最容易翻车的点就是平层信号。真实电梯运行过程中当前楼层平层信号会自然变FALSE、目标楼层平层信号变TRUE但仿真里你得手动先把当前楼层平层信号置FALSE再把目标楼层平层信号置TRUE。顺序反了电梯会认为自己一直停在原地永远不动作。这个“给信号的时序”和真实机械动作的时序必须保持一致否则仿真通过了现场反而翻车。5.2 避坑1平层信号抖动导致“过站”不停车现象运行到目标楼层时偶尔不停车直接冲过去到下一层才停。原因平层感应开关在楼层分界线上反复通断PLC扫描时恰好抓到一次FALSE判定为还没到平层错过了停车时机。这类问题在机械安装精度不高的现场非常常见。解决在博图V15.1的DI组态里把平层信号的滤波时间调到10ms以上同时在程序里对平层信号加“延时确认”即平层信号持续TRUE达到设定时间后才视为有效。滤波加延时确认双保险实体安装时能省掉大量现场调参时间。5.3 避坑2上下行接触器没有互锁现象电机的上行接触器和下行接触器偶尔同时吸合轻则跳闸重则烧电机。原因软件里只写了简单的IF判断但PLC扫描周期交替或输出刷新顺序问题可能让两个输出瞬间同时为TRUE。这是电梯控制的红线问题只靠程序逻辑里的IF完全不保险。解决程序里输出段强制互锁motor_up : direction 1 AND NOT motor_downmotor_down : direction -1 AND NOT motor_up硬件上两个接触器还要加机械互锁。软件互锁和硬件互锁缺一不可谁省了谁就是在埋事故隐患。5.4 避坑3关门继电器一直吸合门电机发热现象门关好以后关门继电器还是TRUE门电机一直通电时间长了发热甚至烧毁。原因关门动作用了电平触发而不是脉冲触发。关门到位以后输出没有复位。解决关门输出只在关门过程中为TRUE检测到关门到位立即复位。手动关门按钮也应该用边沿触发按一次关一下而不是按住才关。开门继电器同理开门到位后要立刻断开输出不能一直给电。5.5 避坑4到达目标层后呼叫没清干净电梯反复跑同一层现象电梯到达某一层后没人呼梯了结果过一会儿又自己跑回刚才那层。原因到达目标层后只清了轿内登记或只清了厅外呼叫另一组登记还留在原处。单步模式下目标计算再次扫到残留登记电梯被召回。解决到达目标层并开门后同时清除该楼层的car_call和hall_call。如果楼层上、下呼叫分开采集这一步也要把两个方向都清掉。单步逻辑里不要想着“保留一个方向的呼叫做顺向继续”那是集选模式的事在单步逻辑里混着做状态一定会乱。5.6 避坑5博图V15.1下载和仿真版本不匹配现象PLCSIM能启动但程序下载一直失败提示无法建立连接。原因博图V15.1和PLCSIM的版本号必须完全对齐装成V15.0或V16都不行。另外电脑防火墙拦了虚拟网卡的通信也会表现成连接失败。解决安装前确认两个软件版本完全一致下载时先启动PLCSIM再在博图里选择下载目标“PLCSIM”。防火墙弹窗时允许对PLCSIM的访问不要图省事直接关防火墙。安装版本这件事属于下载软件前就该确认好的问题等到下载报错才排查就慢了。6. 进阶技巧把状态机映射成常量标记为集选控制留好接口调试单步电梯状态机里最容易懵的不是逻辑而是盯着一个整数status想不起来2代表开门还是关门。我习惯一开头就把五个状态定义成常量标记放在一个单独的全局DB里// DB_Const 状态常量标记 STANDBY : INT : 0; RUNNING : INT : 1; DOOR_OPEN : INT : 2; DOOR_CLOSE : INT : 3; FAULT : INT : 4;所有比较都写成IF DB_Elevator.status DB_Const.DOOR_OPEN而不是“IF status 2”。代码可读性提升一个档次十五天后再打开这个项目不用重新去数字和状态的对应表。再配合博图V15.1的轨迹记录功能把状态切换时序和电机输出录下来排查“偶尔不关门”这类玄学问题会非常有效。从单步控制往集选控制扩展时这套状态机结构基本不用动要改的是目标计算和截停条件。比如把“最近优先”改成“顺向优先”增加“运行方向上有呼叫则停”的判断这在现有代码里只是多一层条件计算。单步项目当时把状态机当模板维护的后面做集选就能比别人省下两三天时间。我第一次在PLCSIM里跑通六层单步电梯时也犯过平层信号顺序给反的错那次之后我记住一个原则仿真时要像对待真实设备一样尊重信号的时序。希望这篇笔记能帮你少掉几根头发希望帮到你。本文还有配套的精品资源点击获取