
简介围绕西门子S7-1215C PLC与信捷视觉系统构建工业机器人分拣系统的期刊论文PDF面向自动化、机电一体化专业技术人员以及职业院校技能大赛选手与指导教师重点解决分拣机器人软硬件集成、通讯调试与故障排查等实践问题。资源为1个pdf文件压缩包约374KB内容对应2015年全国职业院校技能大赛“工业机器人技术应用”赛项设备载体。内容系统梳理工业机器人、托盘与工件盒生产线、视觉系统、立体仓库及AGV机器人等六大部分详述汇博HR.20-1700-C10机器人、信捷X-sight视觉与S7-1200系列1215C DC/DC/DC的选型配置并展开PLC与视觉系统、机器人之间的通讯、视觉检测软件流程编辑、系统调试步骤与典型问题现象、原因及解决办法。读者可据此理解柔性分拣产线的控制逻辑、模块分工与联调思路对参赛备赛和工程实践均有直接参考价值。已有282人学习。1. 为什么分拣线要选 S7-1215C 加视觉系统这套组合一条小型分拣线最怕的不是机器人本体贵而是视觉给了坐标、PLC 没接住或者机器人动作和视觉触发差半拍。S7-1215C 出现在这类项目里通常不是因为它算力最强而是它把 PROFINET 口、本体 IO、SCL 编程和紧凑体积凑在了一个能落地的价位。视觉系统负责把工件的位置、角度、类别变成数字S7-1215C 负责把这些数字变成机器人能执行的取放节拍。适合做设备集成的电气工程师、自动化方向的毕设学生以及要给产线加视觉分拣但预算有限的团队。一个反直觉的地方视觉分辨率从 500 万升到 1200 万分拣节拍未必变快PLC 与视觉的通讯协议、数据结构和超时处理才是真正的瓶颈。2. S7-1215C 与视觉系统通讯链路和数据结构设计2.1 三种视觉与 PLC 通讯方式选型对比视觉系统输出给 PLC 的东西一般就几类像素坐标、物理坐标、角度、类别、状态字。通讯方式决定了这些数据怎么进 S7-1215C。常见做法有三种硬线 IO、PROFINET IO、开放式用户通讯 TCP。硬线 IO 最稳但只能传“有料/无料/合格/不合格”坐标和角度传不了。PROFINET IO 适合智能相机支持 GSD 文件的情况周期稳定但改一次数据长度要重新组态。TCP socket 最灵活视觉工控机当客户端S7-1215C 当服务器传 JSON 或自定义二进制帧调试方便代价是要自己处理粘包和超时。通讯方式典型周期开发量适合场景硬线 IO1~5 ms低仅分合格/不合格无坐标PROFINET IO1~4 ms中智能相机带 GSD数据固定TCP 开放式用户通讯5~50 ms中高工控机视觉数据可变需解析S7-1215C 的 PROFINET 接口支持开放式用户通讯指令库里有 TCON、TSEND、TRCV、TDISCON。如果视觉软件跑在 PC 上我一般会选 TCP因为改协议不用动博途硬件组态。如果视觉是康耐视或基恩士的智能相机且支持 PROFINET优先走 PROFINET IO节拍更稳。2.2 用 TCP 开放式用户通讯建立视觉链路的最小实现下面这段 SCL 写的是 S7-1215C 作为 TCP 服务器视觉客户端主动连过来。放在 OB1 或循环中断里调用背景 DB 用全局库。代码只保留关键逻辑// 在 OB1 中调用背景 DB 为 TCON_DB // 连接参数需要提前在 DB 里定义 TCON_Param TCON_DB(REQ : StartConnect, ID : 1, CONNECT : ConnParam, DONE ConnectDone, BUSY ConnectBusy, ERROR ConnectError, STATUS ConnectStatus); // 接收视觉数据假设最大 256 字节 TRCV_DB(EN_R : ConnectDone, ID : 1, DATA : RecvBuffer, LEN : 256, DONE RecvDone, NDR RecvNewData, ERROR RecvError, STATUS RecvStatus, RCVD_LEN RecvLen);逻辑说明TCON 建立被动连接参数里本地端口设为 2000远程 IP 可以不填因为服务器等客户端连入。TRCV 每扫描周期尝试收数据NDR 为真表示收到新帧。参数说明ID 是连接号同一个连接后续收发都用同一个 IDDATA 是接收缓冲区建议用Array[0..255] of ByteLEN 是缓冲区长度不要小于实际最大帧长RCVD_LEN 告诉你实际收到多少字节。注意TRCV 不是每周期都产生新数据必须用 NDR 触发解析否则会把同一帧反复处理。视觉端我常用 Python 写一个测试客户端确认 PLC 能收到再上产线import socket import struct # PLC 的 IP 和端口端口要和 TCON 中一致 PLC_IP 192.168.0.10 PLC_PORT 2000 # 帧格式X坐标(float) Y坐标(float) 角度(float) 类别(uint8) 校验和(uint8) payload struct.pack(fffBB, 125.4, 230.8, 15.2, 1, 0) checksum sum(payload) 0xFF frame b\xAA\x55 payload bytes([checksum]) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((PLC_IP, PLC_PORT)) s.sendall(frame) print(sent, len(frame), bytes)这段 Python 只用于验证链路发一帧固定坐标在博途里监控 RecvBuffer 就能看到字节。参数说明fffBB表示小端浮点、浮点、浮点、无符号字节、无符号字节帧头AA55用来做帧同步校验和用累加和。实际项目里可以把帧头、长度、校验做成固定协议PLC 收到后先找 AA55再按长度取一帧。2.3 分拣结果的数据结构从字节数组到 UDT视觉给的是字节流PLC 内部最好马上转成 UDT。在博途里新建一个数据类型typCargoTYPE typCargo VERSION : 0.1 STRUCT X : Real; // 机器人基坐标 X单位 mm Y : Real; // 机器人基坐标 Y单位 mm Angle : Real; // 工件角度单位度 Class : Int; // 类别编号1A2B3C Status : Int; // 0空1待取2已取3异常 Timestamp : DInt; // 入队时的系统时间ms END_STRUCT; END_TYPE然后在全局 DB 里声明CargoQueue : Array[1..20] of typCargo;。解析函数把 RecvBuffer 里的浮点数按偏移量搬到 UDT 中。参数说明偏移量 2 开始是因为前两个字节是帧头Real 在 S7-1200 中占 4 字节大端存储但 TCP 收到的是小端所以要用SWAP或自定义字节交换函数。我一般写一个DWordSwapFC 把 4 字节反过来再DWORD_TO_REAL。这个结构决定了后面 FIFO 和机器人取件的接口是否清晰不要用一堆 M 点硬拼。3. 机器人分拣动作的 PLC 状态机与 FIFO 队列实现3.1 分拣工位状态划分与 IO 握手时序工业机器人分拣不是“给坐标就动”PLC 和机器人之间要有明确的握手。常见做法是 PLC 把目标位姿写入机器人输入区然后置位DataReady机器人回Busy取件完成回DonePLC 复位DataReady。如果走 PROFINET这些信号可以打包成 16 字节的输出区机器人侧映射成系统变量。如果走硬线 IO至少需要 5 根线DataReady、Busy、Done、Error、Ack。状态划分我通常用这几个Idle、WaitVision、DataReady、RobotMoving、PickDone、Fault。每个状态超时都要有计时器比如 DataReady 超过 3 秒没收到 Busy就进 Fault。状态迁移表可以写在 DB 里但代码里用 CASE 更直接。注意 PLC 扫描周期是毫秒级机器人 Busy 信号可能抖动所以输入信号要加 50 ms 滤波或者用TON延时确认。3.2 在博途里用 SCL 写一个可复位的状态机下面是一个简化状态机放在 FB 里背景 DB 保存状态和计时器CASE #State OF 0: // Idle IF #Start THEN #State : 10; END_IF; 10: // WaitVision IF #VisionDataReady THEN #State : 20; ELSIF #VisionTimeout.Q THEN #State : 90; END_IF; 20: // DataReady把坐标发给机器人 #Robot_X : #Cargo.X; #Robot_Y : #Cargo.Y; #Robot_Angle : #Cargo.Angle; #DataReady : TRUE; IF #Robot_Busy THEN #State : 30; ELSIF #HandshakeTimeout.Q THEN #State : 90; END_IF; 30: // RobotMoving IF #Robot_Done THEN #DataReady : FALSE; #State : 40; ELSIF #Robot_Error THEN #State : 90; END_IF; 40: // PickDone出队并回到等待 #Dequeue : TRUE; #State : 10; 90: // Fault #DataReady : FALSE; #FaultCode : #LastError; IF #Reset THEN #State : 0; END_IF; END_CASE;逻辑说明State 是 Int每个分支只做一件事。VisionDataReady来自视觉解析完成HandshakeTimeout和VisionTimeout是 TON 实例的背景数据。参数说明State 编号留间隔以后插入新状态不用改所有数字Robot_X、Robot_Y 等是输出给机器人的 REALFaultCode 记录错误来源方便在 HMI 上显示。注意DataReady 置位后不要马上复位要等机器人 Busy 或 Done 再复位否则机器人可能丢触发。3.3 FIFO 队列视觉结果入队与机器人取件出队视觉可能一次给多个工件机器人一个一个取所以需要一个 FIFO。S7-1215C 没有现成的 FIFO 指令自己用环形缓冲写一个 FC。下面用 SCL 实现入队// 入队把 #NewCargo 写入队列头指针前移 IF #Count 20 THEN #Tail : #Tail 1; IF #Tail 20 THEN #Tail : 1; END_IF; #CargoQueue[#Tail] : #NewCargo; #Count : #Count 1; #EnqueueOK : TRUE; ELSE #EnqueueOK : FALSE; // 队列满报警 END_IF;出队逻辑相反从头指针取取完 Head 前移Count 减一。参数说明Head 和 Tail 是 Int范围 1~20Count 是当前数量CargoQueue 是Array[1..20] of typCargo。注意数组下标从 1 开始所以判断20后回绕到 1。入队前要检查 Count防止覆盖未取数据。实际项目中还要加队列溢出报警让视觉暂停发送。这个结构比用 M 点数组清晰得多机器人取件时只需要读CargoQueue[Head]。4. 视觉标定、坐标转换与分拣精度调参4.1 手眼标定相机像素坐标到机器人基坐标的映射视觉给的是像素坐标机器人要的是基坐标中间差一个标定矩阵。平面分拣常用九点标定在机器人工作平面上取 9 个点记录每个点的像素坐标和机器人坐标解出仿射变换。仿射变换公式x_robot a * u b * v c y_robot d * u e * v f其中 (u,v) 是像素坐标(x_robot,y_robot) 是机器人坐标。a、b、c、d、e、f 六个参数通过最小二乘解出。如果相机有镜头畸变先做畸变校正否则边缘点误差会到几毫米。标定板要覆盖整个分拣区域不要只取中间一小块。在 S7-1215C 里做浮点矩阵运算不是强项我一般把标定参数算好后下载到 DBPLC 只做一次线性计算// 像素坐标转机器人坐标参数存在 CalibDB 中 #x_robot : CalibDB.a * #u CalibDB.b * #v CalibDB.c; #y_robot : CalibDB.d * #u CalibDB.e * #v CalibDB.f;参数说明a、b、c、d、e、f 都是 REALu、v 来自视觉解析后的像素坐标x_robot、y_robot 写入 typCargo。注意如果传送带在动还要加编码器补偿x_robot 要减去传送带位移。这个补偿值可以用高速计数器读编码器每毫秒更新。4.2 九点标定与仿射变换在 PLC 中的实现九点标定的数据采集可以在 HMI 上做机器人依次走到 9 个点视觉记录像素PLC 记录机器人坐标。然后在上位机用 Python 算最小二乘把结果写回 PLC。下面是一段 Python 计算示例import numpy as np # 9 组像素坐标和机器人坐标 pixel np.array([[100,200],[300,200],[500,200], [100,400],[300,400],[500,400], [100,600],[300,600],[500,600]], dtypefloat) robot np.array([[10.0,20.0],[110.0,20.0],[210.0,20.0], [10.0,120.0],[110.0,120.0],[210.0,120.0], [10.0,220.0],[110.0,220.0],[210.0,220.0]]) # 构造 A 矩阵解仿射参数 A np.hstack([pixel, np.ones((9,1))]) coeff_x, _, _, _ np.linalg.lstsq(A, robot[:,0], rcondNone) coeff_y, _, _, _ np.linalg.lstsq(A, robot[:,1], rcondNone) print(a,b,c , coeff_x) print(d,e,f , coeff_y)逻辑说明np.linalg.lstsq解超定方程得到 6 个参数。参数说明pixel 是视觉输出的像素坐标robot 是机器人示教器上读到的基坐标A 矩阵每行是[u, v, 1]。算完后把 6 个数填到博途的 CalibDB。注意如果机器人坐标系和相机坐标系有旋转仿射变换能吸收旋转但前提是九点覆盖范围够大。4.3 影响分拣精度的 4 个参数与调试顺序分拣精度不是单一因素按影响大小排标定质量、触发延时、传送带速度、光源稳定性。调试顺序建议先静态后动态静态下放一个工件看视觉坐标和机器人取件点差多少调整标定参数然后开传送带低速看动态偏差最后升到生产速度调触发延时补偿。参数典型值影响调整方法标定残差 0.5 mm整体偏移重新采九点检查标定板触发延时20~80 ms动态 X 偏差用编码器补偿或调相机延时传送带速度100~300 mm/s节拍和偏差低速验证后逐步提高光源亮度70%~85%识别率固定光源避免环境光变化注意如果视觉识别率突然下降先看光源和镜头不要先改 PLC 程序。分拣精度调好后把标定参数和补偿参数保存在 DB 中断电保持换产线时重新标定。5. 分拣系统节拍优化与故障排查从博途资源监视到通讯超时处理5.1 用博途资源监视定位 PLC 扫描周期瓶颈S7-1215C 的扫描周期在博途里可以实时看。打开“在线与诊断”里的“循环时间”如果扫描周期从 2 ms 涨到 10 ms先看程序里有没有大数组循环搬运。视觉解析如果用 FOR 循环逐字节处理 256 字节每周期都跑就会拖慢。常见做法是把解析放到接收完成中断里或者用NDR触发只跑一次。另一个检查点是通讯指令的背景 DBTCON、TRCV 如果每周期都调用且 EN_R 一直为真会占用扫描时间。我一般把 TRCV 放在循环中断 OB30 里周期 5 ms避免主程序被拖慢。博途的“资源”标签页可以看内存占用队列数组不要开太大20 个 typCargo 大约几百字节没问题如果开 1000 个M 区会紧张。5.2 视觉通讯超时与丢帧的排查清单通讯超时先分三层查物理层、协议层、应用层。物理层看网口灯和交换机S7-1215C 的 PROFINET 口和视觉 PC 要在同一网段不要经过路由器。协议层用 Wireshark 抓包看视觉有没有发帧、PLC 有没有 ACK。如果视觉发了但 PLC 的 RCVD_LEN 一直是 0检查 TCON 的本地端口是否被占用或者防火墙。应用层看帧头 AA55 有没有对齐粘包时 TRCV 可能一次收到两帧解析函数要循环找帧头直到剩余长度不足一帧。丢帧的另一个原因是视觉触发太快PLC 队列满后拒绝入队视觉没有收到确认还在发。可以在协议里加一个 ACK 字节PLC 入队成功回 1失败回 0视觉收到 0 就暂停 100 ms。最后如果机器人取件节拍是 2 秒视觉每 200 ms 给一个坐标队列很快满这时候要么降低视觉频率要么让机器人一次取多个。节拍匹配比单点优化更重要。本文还有配套的精品资源点击获取