简介:面向自动化、机电一体化及电气控制相关专业师生与PLC初学者,这份基于PLC的大小球分拣系统设计文档以三菱FX2N系列可编程控制器为核心,通过控制机械臂上下、左右移动以及抓取与释放动作,完成大球与小球的自动分类传送,可用于课程设计、毕业设计选题参考和PLC控制逻辑入门练习。压缩包内共1个docx文件,约251KB,正文按概述、硬件设计、软件设计、软硬调试等章节展开,包含主电路设计、I/O地址分配及接线图、元件选型,以及系统流程图、顺序功能图、梯形图与指令表、程序分析等内容,并附使用说明、设计感想和参考文献,目录结构完整。目前已有643人学习下载,读者可据此了解从控制要求分析到梯形图编程、再到联机调试的完整思路,适合作为PLC顺序控制类项目的仿写与排错参考。
1. 用PLC做大小球分拣,为什么比单片机方案更稳
一条钢球分选线上,直径 20 mm 和 40 mm 两种球混装从振动盘上料,落到传送带上依次经过检测位,带末必须在几百毫秒内把大球推进侧向料道,慢了两种球就撞在一起。这类工位在教学实训台和中小型产线上非常常见,"基于PLC的大小球分拣系统设计"这个题目考的不是分拣这个动作,而是三件事:传感器能不能稳定区分直径、程序能不能在球到达推杆位置的那一刻准时输出、参数改了以后现场的人能不能自己调回来。
单片机方案在实验室跑得通,一到车间就露怯:24 V 电磁阀断电时的反电动势、粉尘、后期多加一个工位就得重画板子。PLC 的价值在于 I/O 模块化、梯形图可维护,现场电工拿着图纸就能改一段逻辑,这是 PLC 编程 被产线选中的真实原因。
这套设计要落地,需要一条完整的链路:I/O 点表、带速与遮光时长的换算、状态步序程序、气缸动作时序,以及现场误判的排查顺序。适合做 PLC 课程设计 的学生、刚从电气转自动化的工程师,以及要把分拣做成标准工位的人。
2. 大小球分拣系统的硬件选型与I/O点表设计
2.1 传送、检测、执行三段各自的器件怎么挑
整条线拆成三段看:传送段负责把球按固定间距送出来,检测段负责量直径,执行段负责把大球拨走。传送段最常见的是三相异步电机加减速机配变频器,也有用步进的,步进的好处是带速恒定,缺点是成本和调试量都上去了。我一般先按 0.2~0.5 m/s 这个区间定带速,因为再快就会把检测段的余量吃干净。
检测段是整套系统的精度来源。两种球差 20 mm,听起来很好分,但光电开关的响应时间和光斑直径会一起吃掉有效时间。选型时优先看响应时间,1 ms 以内的对射式光电是基本要求,光斑直径要明显小于小球直径,否则小球遮光时间被拉长,直接判成大球。
| 环节 | 常用器件 | 选型要点 | 容易踩的坑 |
|---|---|---|---|
| 传送 | 三相异步电机 + 减速机 + 变频器 | 带速 0.2~0.5 m/s,能整定 | 变频器频率漂移导致测径误差 |
| 检测 | 对射式光电开关 | 响应 ≤1 ms,光斑小于小球直径 | 用漫反射式,背景反光误触发 |
| 执行 | 双作用气缸 + 二位五通电磁阀 | 缸径按推力算,行程盖住料道口 | 不加调速阀,推杆冲击把球打飞 |
| 控制 | PLC 本体 + DI/DO 模块 | 输入点数留 20% 余量 | 公共端接反,输入全不亮 |
2.2 按工艺动作拆 I/O 点表,留 20% 余量
点表不要照着器件抄,要照着动作拆。整机动作只有四个:启动输送、检测球径、延时到位、推杆分拣,再加急停和报警。按这个拆,输入点会落在 6~8 个,输出点 4 个左右,选 14 点或 16 点的本体就够,但我会直接上 24 点的机型,因为料道满检测、气缸缩回到位这些点早晚要加。
| 地址 | 符号名 | 类型 | 说明 |
|---|---|---|---|
| I0.0 | InletSensor | DI | 入口光电,球到达检测位为 1 |
| I0.1 | SizeSensor | DI | 测径光电,遮光为 1 |
| I0.2 | CylFront | DI | 气缸伸出到位磁开关 |
| I0.3 | StartBtn | DI | 启动按钮,常开 |
| I0.4 | StopBtn | DI | 停止按钮,常开 |
| I0.5 | EStopOK | DI | 急停回路正常为 1 |
| Q0.0 | Conveyor | DO | 传送带接触器 |
| Q0.1 | Diverter | DO | 分拣气缸电磁阀 |
| Q0.2 | RunLamp | DO | 运行指示灯 |
| Q0.3 | AlarmLamp | DO | 故障报警灯 |
同样的点表换成三菱 FX 系列,就是 X0~X5 对应输入、Y0~Y3 对应输出,逻辑一模一样。做 I/O 点表时把符号名一次写好,后面写梯形图还是写 SCL 都省事,这也是 PLC 编程入门基础知识 里最容易被跳过、又最影响后期维护的一步。
2.3 输入映射与公共端的接线细节
PLC 的物理输入不要直接散落到程序各处,先做一层语义映射。这样换机型或者改点位时,只需要动映射这一处,梯形图和 SCL 都不用碰。西门子博途里可以用一个全局 DB 存映射结果,也可以用 M 区,看团队习惯。
// 输入信号映射:物理地址 -> 语义变量 // 建议放在 OB1 的第一个网络,每周期执行一次 "InputMap".InletSensor := "I_0_0"; // 入口光电,球到达时 = 1 "InputMap".SizeSensor := "I_0_1"; // 测径光电,遮光时 = 1 "InputMap".CylFront := "I_0_2"; // 气缸伸出到位,到位 = 1 "InputMap".StartBtn := "I_0_3"; // 启动,常开接法 "InputMap".StopBtn := "I_0_4"; // 停止,常开接法 "InputMap".EStopOK := "I_0_5"; // 急停串在安全回路里,正常 = 1映射段本身没有逻辑,它的价值在后面:所有功能块只引用语义变量,不引用 I 地址。参数上要注意急停信号,接常闭回路进 PLC 时,正常状态是 1,一旦断线或按下急停就变 0,程序里用NOT EStopOK判断停机,比用常开接法安全,因为断线也会触发停机。
接线层面还有两个细节值得单独说。一是输入公共端,NPN 型传感器要配漏型输入,PNP 型配源型输入。二是电磁阀线圈一定要并续流二极管,靠 PLC 输出点自己扛反电动势,短期看不出问题,几个月后输出点就会粘死。
提示:气缸的进出气口都装上调速阀,把推杆伸出速度调到 0.2 s 左右。速度太快会把球弹到料道外面,后面再排查会以为是程序问题。
3. PLC分拣程序:状态步序、球径判定与定时器整定
3.1 用状态步序替代一排自锁回路
新手写分拣程序,容易写成一堆自锁:启动按钮自锁传送带、光电自锁延时、延时到位自锁气阀。段数一多,中间继电器满天飞,改一处逻辑就要顺着看十几行,出故障时根本不知道停在哪一步。PLC 梯形图 里更稳的写法是状态步序,一个整数变量表示当前步,每个扫描周期只执行当前步的动作和跳转条件。
这套系统的步序很干净:0 待机、10 输送中、20 气阀动作、30 气阀复位、90 停止。急停和停止按钮可以直接从任意步跳到 90,出问题时看一个变量就知道机器卡在哪一环。步序还有个好处在调试期,用编程软件的监控表盯着 Step 这个变量,球走到哪一步、卡在哪一步,一眼就能看见,比在梯形图里顺着看输出点快得多。
3.2 球径怎么算:带速乘遮光时间
球经过对射光电时,会遮挡光路一段时间,这段时间等于球的直径除以带速。带速 0.3 m/s 时,20 mm 小球遮光约 67 ms,40 mm 大球约 133 ms,两个数差了一倍,中间留出 100 ms 做阈值就很稳。这里的关键是带速必须准,用变频器面板显示的频率反推带速误差太大,我一般用秒表量球从测径位走到分拣位的时间,反推实际带速,再写进参数。
除了判定阈值,还需要一个输送延时。测径位和分拣位之间有一段距离 L,球走完这段要用 L/v,程序在检测到球通过后延时这么久,再决定要不要开阀。L 取 150 mm、v 取 0.30 m/s 时,延时正好是 500 ms。
| 参数 | 符号 | 典型取值 | 说明 |
|---|---|---|---|
| 带速 | v | 0.30 m/s | 用秒表实测反推,不信面板显示 |
| 检测位到分拣位距离 | L | 150 mm | 机械安装尺寸,卡尺量 |
| 输送延时 | T_Delay | 500 ms | L / v |
| 小球遮光时长 | t_small | 约 67 ms | 20 mm / v |
| 大球遮光时长 | t_big | 约 133 ms | 40 mm / v |
| 判定阈值 | T_Threshold | 100 ms | 取两值中间,两侧余量约 30% |
| 气阀保持时间 | T_Blow | 200 ms | 保证球离开料道口 |
3.3 分拣核心逻辑的 SCL 实现
时间测量用上升沿启动定时器、下降沿读当前值的方式。注意定时器每个扫描周期只能调用一次,把调用放在 IF 分支里是常见错误,会导致计时值跳变。下面的写法和状态步序合在一起,梯形图和 SCL 都能照这个结构搭。
FUNCTION_BLOCK "FB_BallSort" VAR_INPUT InletSensor : Bool; // I0.0 入口光电,球到达 = 1 SizeSensor : Bool; // I0.1 测径光电,遮光 = 1 CylFront : Bool; // I0.2 气缸伸出到位 StartBtn : Bool; // I0.3 启动,常开 StopBtn : Bool; // I0.4 停止,常开 EStopOK : Bool; // I0.5 急停回路正常 = 1 T_Delay : Time := T#500MS; // 输送延时,由 L/v 算出 T_Threshold : Time := T#100MS; // 大球判定阈值 T_Blow : Time := T#200MS; // 气阀保持时间 END_VAR VAR_OUTPUT Conveyor : Bool; // Q0.0 传送带 Diverter : Bool; // Q0.1 分拣气缸电磁阀 RunLamp : Bool; // Q0.2 运行指示 Alarm : Bool; // Q0.3 气缸超时报警 END_VAR VAR RiseEdge : R_TRIG; FallEdge : R_TRIG; WidthTimer : TON_TIME; // 遮光时间计时 WidthEnable : Bool; DelayTimer : TON_TIME; // 输送延时 DelayEnable : Bool; BlowTimer : TON_TIME; // 气阀保持 CylTimer : TON_TIME; // 气缸到位监视 Step : Int := 0; // 当前步序号 IsBigBall : Bool; PulseWidth : Time; BigCount : DInt; // 大球计数,验收用 SmallCount : DInt; // 小球计数,验收用 END_VAR BEGIN // ---- 边沿检测 ---- #RiseEdge(CLK := #SizeSensor); #FallEdge(CLK := #SizeSensor); // ---- 定时器每周期只调用一次 ---- #WidthTimer(IN := #WidthEnable, PT := T#1S); #DelayTimer(IN := #DelayEnable, PT := #T_Delay); #BlowTimer(IN := #Diverter, PT := #T_Blow); #CylTimer(IN := #Diverter AND NOT #CylFront, PT := T#500MS); #Alarm := #CylTimer.Q; // ---- 遮光时间测量:上升沿起表,下降沿锁存 ---- IF #RiseEdge.Q THEN #WidthEnable := TRUE; END_IF; IF #FallEdge.Q THEN #WidthEnable := FALSE; #PulseWidth := #WidthTimer.ET; // 锁存本次遮光时长 IF #PulseWidth > #T_Threshold THEN #IsBigBall := TRUE; #BigCount := #BigCount + 1; ELSE #IsBigBall := FALSE; #SmallCount := #SmallCount + 1; END_IF; #DelayEnable := TRUE; // 触发输送延时 END_IF; // ---- 状态步序 ---- CASE #Step OF 0: // 待机 #Conveyor := FALSE; #Diverter := FALSE; #RunLamp := FALSE; IF #StartBtn AND #EStopOK THEN #Step := 10; END_IF; 10: // 输送中 #RunLamp := TRUE; #Conveyor := TRUE; IF (NOT #EStopOK) OR #StopBtn THEN #Step := 90; END_IF; IF #DelayTimer.Q THEN // 球已到分拣位 #DelayEnable := FALSE; IF #IsBigBall THEN #Step := 20; // 大球,推入大球道 END_IF; END_IF; 20: // 气阀伸出 #Diverter := TRUE; IF #BlowTimer.Q THEN #Step := 30; END_IF; 30: // 气阀复位 #Diverter := FALSE; IF NOT #BlowTimer.Q THEN #Step := 10; END_IF; 90: // 停止 #Conveyor := FALSE; #Diverter := FALSE; #RunLamp := FALSE; IF #StartBtn THEN #Step := 0; END_IF; END_CASE; END_FUNCTION_BLOCK逻辑说明:边沿检测和三个定时器的调用放在 CASE 之前,保证每个扫描周期定时器只被调用一次;WidthTimer计时上限设 1 s,超过这个值说明光路被长期遮挡或传感器损坏,读到的值一定是大球,会被判错,所以上限值本身就是个异常信号。DelayTimer用使能位控制启停,比在 CASE 里直接调用可靠。CylTimer监视气阀通电后 500 ms 内气缸是否伸出到位,不到位就报警,这是最早能发现气压不足的地方。
参数说明:T_Threshold是最核心的一个值,改带速或者换球径都要重算;T_Delay只跟安装尺寸和带速有关,机械不动就不用改;T_Blow一般给 150~250 ms,给短了推杆提前缩回,球会卡在料道口。
3.4 定时器与计数器的参数整定表
定时器不是拍脑袋给的,每个值都有对应的物理量。整定时按下面这个顺序走:先用秒表量实际带速,再算阈值和延时,最后微调气阀保持时间。整定完之后把这三个值记录下来,换品种时要重新算。
| 定时器 | 时间基准 | 整定依据 | 异常表现 |
|---|---|---|---|
| WidthTimer | 1 s 上限 | 最长遮挡时间 | 长期计时说明光路遮挡 |
| DelayTimer | 100 ms 分辨率 | L / v | 偏大球被推空,偏小球没到就推 |
| BlowTimer | 10 ms 分辨率 | 推杆行程 / 推速 | 偏短卡料,偏长打乱节拍 |
| CylTimer | 100 ms 分辨率 | 气缸全行程时间 + 余量 | 频繁报警说明气压不足 |
计数方面,BigCount和SmallCount不是装饰。整机跑一小时以后,这两个数加起来应该等于上料球数,如果对不上,说明有球从测径位溜过去了,问题在检测段而不是执行段。这个判断能省掉大量盲猜。
注意:所有 Time 类型参数的比较都用 TIME 类型直接比,不要转成整数毫秒再比。不同机型对时间内部单位的处理不一样,直接比较能避开这个差异。
4. 分拣误动作排查:从传感器标定到扫描周期
4.1 误判大球、漏推、推空的成因对照
现场出问题时,先分清楚是识别错了还是执行错了。识别错的典型特征是计数对不上,执行错的典型特征是计数对得上但落料位置不对。按照下面这张表顺序排查,八成的问题在前两行就能定位。
| 现象 | 优先怀疑 | 现场动作 |
|---|---|---|
| 小球被推进大球道 | 阈值偏小,或光斑大于小球直径 | 监控 PulseWidth 实测值,重算阈值 |
| 大球漏推 | 输送延时不准,带速漂移 | 秒表复测 L/v,检查变频器频率 |
| 推杆推空 | 气阀保持时间短,或气压低 | 保持时间加到 250 ms,查减压阀 |
| 无规律连续动作 | 输入滤波太短,干扰被当球 | DI 滤波时间由 0.1 ms 调到 3.2 ms |
| 气缸报警频繁 | 节流阀开度小,或电磁阀卡滞 | 调大节流阀,手动测试阀体动作 |
表里最容易误判的是"无规律连续动作"。很多人第一反应是程序逻辑写错了,其实是测径光电的输入滤波时间设得太短,车间里变频器和高频设备的干扰被当成了一次遮光,程序照样走完一整套分拣动作。
4.2 带速一高就漏检:输入滤波与扫描周期的边界
带速提到 0.8 m/s 以上时,20 mm 小球的遮光时间只剩 25 ms,如果有干扰,测量误差就会明显放大。这时候两个边界要盯住:一是 PLC 数字量输入的滤波时间,默认值通常在毫秒级,球速快时滤波会把有效脉宽削掉一截;二是扫描周期,如果主程序里塞了大量浮点运算或者通讯,扫描周期超过 10 ms,边沿检测本身就会丢脉冲。
实测办法很简单,把测径光电的脉冲宽度用一个计数器累加,跟理论值对比。差得不多说明是滤波,差一个数量级说明是丢脉冲,得把边沿检测挪到硬件中断里,或者改用高速计数器模块测量脉宽。
// 诊断段:统计过球数、判大球数、气阀动作次数,三者对照定位故障段 // 放在 FB 末尾或单独的诊断 FC 里 IF #RiseEdge.Q THEN "Dbg".SizeEdgeCnt := "Dbg".SizeEdgeCnt + 1; // 测径位过球次数 END_IF; IF #FallEdge.Q AND #IsBigBall THEN "Dbg".BigJudgeCnt := "Dbg".BigJudgeCnt + 1; // 判定为大球的次数 END_IF; IF #Diverter THEN "Dbg".ValveOnCnt := "Dbg".ValveOnCnt + 1; // 气阀通电次数 END_IF; // 诊断结论: // SizeEdgeCnt = BigJudgeCnt + SmallJudgeCnt -> 识别段正常 // BigJudgeCnt = ValveOnCnt -> 执行段正常这段代码没有控制作用,纯统计。三个数一旦出现差值,就能直接定位问题段:SizeEdgeCnt大于两个判定数之和,说明有球的遮光时间落进了不判定区间,问题在定时器上限或者滤波;BigJudgeCnt大于ValveOnCnt,说明有判定没输出,问题在步序跳转或者急停条件被误触发。整定期间可以把这三个数放到 HMI 上,现场人员看到数值对不上就能打电话报故障段,不用等工程师到现场。
4.3 用三个计数做分拣准确率的验收
验收不要靠肉眼看,抓 100 个球(大球小球按实际配比混装),跑完统计三组数:上料总数、大球道收料数、小球道收料数。准确率要求一般能做到 99% 以上,达不到就按计数差值往回查。验收还要覆盖两个边界条件:空载连续运行 30 min 看有没有误动作,满载运行 10 min 看节拍能不能跟上,这两个测试能暴露绝大部分偶发问题。
5. 分拣参数配方化:把球径阈值与延时交给HMI去改
调试完成后,真正决定这套系统好不好用的,是换品种时改参数要花多久。把球径、带速、安装距离这些工程参数放进一个配方数据块,换算在启动时做一次,操作工只需要在 HMI 上填两个直径和一个带速。
// 全局 DB:分拣配方,HMI 只读写这个块 DATA_BLOCK "DB_Recipe" VAR BallSmall_mm : Real := 20.0; // 小球直径 BallBig_mm : Real := 40.0; // 大球直径 BandSpeed_mps : Real := 0.30; // 实测带速 Distance_mm : Real := 150.0; // 测径位到分拣位 ValveHold_ms : Int := 200; // 气阀保持时间 ThMs : DInt; // 换算结果:判定阈值 DelayMs : DInt; // 换算结果:输送延时 END_VAR换算只需要两行,因为长度用毫米、带速用米每秒时,算出来的数值正好就是毫秒数,省掉了单位换算这一步。距离 150 mm 除以带速 0.30 m/s 得 500,直接就是 500 ms;球径均值 30 mm 除以 0.30 m/s 得 100,直接就是 100 ms。
// 在启动步(Step 0 跳 10 之前)执行一次即可 "DB_Recipe".DelayMs := REAL_TO_DINT("DB_Recipe".Distance_mm / "DB_Recipe".BandSpeed_mps); "DB_Recipe".ThMs := REAL_TO_DINT( (("DB_Recipe".BallSmall_mm + "DB_Recipe".BallBig_mm) / 2.0) / "DB_Recipe".BandSpeed_mps); // 转成 TIME 后传给功能块 #T_Delay := DINT_TO_TIME("DB_Recipe".DelayMs); #T_Threshold := DINT_TO_TIME("DB_Recipe".ThMs); #T_Blow := DINT_TO_TIME("DB_Recipe".ValveHold_ms);配方之外还有一个技巧:把ThMs和实测到的PulseWidth一起显示在 HMI 的趋势图上,换品种时先空跑十几个球看实测脉宽落在阈值的哪一侧。大球实测值离阈值至少要有 20% 余量,小球同理,两边都够才说明带速稳定、光斑合适。这一步比反复调阈值有效得多,很多"怎么调都不准"的情况,根子在于带速本身在漂,而不是阈值没找对。
本文还有配套的精品资源,点击获取