双机器人高速分拣 — Delta + SCARA 混搭, 一套 Runtime 全管
一、设备简介
项目位于浙江义乌某小商品 3PL 物流园, 客户承担 食品类快消分拣业务 (糖果、饼干、独立包装果干、功能饮料小瓶), 日单量已突破 120 万件。原线为两台进口机器人控制器 + 一台总控 PLC 的三控制器架构, 各系统互不相通, 分拣跟踪精度仅 ± 2 mm, 备件周期长、授权费用高。
项目把整线升级为 一套 Darra Runtime 管 2 台机器人 + 1 条视觉检测带 + 3 路输送通道:
- Delta 并联臂工作区 × 1 (抓糖果、果干、轻小件);
- SCARA 四轴机器人工作区 × 1 (抓小瓶饮料、成组包装);
- 两台机器人共用一条 1.2 m/s 的主传送带 (板链); 视觉站在带前端, 通道 1-3 在 Delta 工作区内下料, 通道 4-6 在 SCARA 工作区内下料;
- 下游对接 3 条打包带, 每条直达装箱工位。
关键指标:
| 指标 | 数值 |
|---|---|
| 传送带线速 | 1.2 m/s |
| 视觉帧率 | 海康 120 FPS |
| 视觉处理延迟 | < 25 ms |
| 编码器跟踪精度 | ± 0.5 mm |
| 综合拣选速率 | 480 件/分钟 |
| 任务动态分配 | Delta / SCARA 负载自动平衡 |
| 故障降级 | 一台故障时另一台 100% 顶上 |
| 第 3 台机器人预留 | 可加埃夫特 6 轴, 无需改软件架构 |
目标:
- 取代两台进口机器人控制器 + 总控 PLC 三套系统;
- 国产机器人本体 + 国产控制器, 成本降 40%;
- 一个工程师 (非机器人专业) 在 Studio 里完成混合编程;
- 投产后 30 天 OEE ≥ 92%。
二、项目模块组成
工程模板 MULTI_ROBOT_SORT, 单 Runtime 下划分功能模块:
| 模块 | 职责 | 关键技术 |
|---|---|---|
| MOD_BELT | 主传送带伺服 + 编码器高速采集 | SV660N 750W + 2500 线 |
| MOD_VISION | 海康视觉 120 fps 触发 + 识别 | SDK + 数据包时戳 |
| MOD_TRACKER | 物体跟踪队列 (编码器滞后) | 环形缓冲 + TSC 时戳 |
| MOD_DISPATCH | 动态任务分配 (工作区判断) | 任务表 + 负载平衡 |
| MOD_ROBOT_DELTA | Delta 并联运动学 + 皮带同步 | Darra.Robot.dll Type=Delta |
| MOD_ROBOT_SCARA | SCARA 运动学 + 皮带同步 | Darra.Robot.dll Type=SCARA |
| MOD_GRIPPER | 真空吸盘 / 机械夹具控制 | DO + 真空表 |
| MOD_REJECT | 未抓走物体的再循环 / 清理 | 末端剔除推杆 |
| MOD_RECIPE | 商品分类 → 通道映射 | 配方表 + SKU |
| MOD_DEGRADE | 故障降级 (一台顶两台) | 状态机 |
| MOD_SCALE | 第 3 台机器人预留接口 | 任务表可扩容 |
| MOD_HMI | 分拣总览 / 工作区热力图 | Darra HMI Designer |
| MOD_UPSTREAM | 对接上层系统, 读取任务与状态 | OPC UA / REST |
| MOD_ALARM | 三级报警 + 视觉 / 机器人异常 | AlarmManager |
三、机械装配架构
┌──────── 上游输送 (混料来货) ─────────┐
│ │
▼ ▼
┌───────────┐ 主传送带 1.2 m/s (板链) ┌───────────┐
│ 视觉拱 │ ───────────────────────────► │ 尾端剔除 │
│ 海康 120fps│ 0 1m 2m 3m 4m │ 推杆 │
└─────┬─────┘ └─────┬─────┘
│ ▲ ▲ │
│ │ │ │
│ ┌─────┴─────┐ ┌─────┴─────┐ │
│ │ Delta │ │ SCARA │ │
│ │ 工作区 │ │ 工作区 │ │
│ │ (0.8×0.8m│ │ (0.8×0.8m │ │
│ └───┬───┬───┘ └───┬───┬───┘ │
│ │ │ │ │ │
└───► │ │ │ │ ◄───────┘
通道1 通道2 通道3 通道4 通道5 通道6
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌───┐┌───┐┌───┐ ┌───┐┌───┐┌───┐
│打1││打2││打3│ │打4││打5││打6│
│带 ││带 ││带 │ │带 ││带 ││带 │
└───┘└───┘└───┘ └───┘└───┘└───┘
↓ ↓
装箱 装箱
机械要点:
- 主传送带为不锈钢模块板链, 节距 25.4 mm, 承载带宽 600 mm;
- 视觉拱高度 580 mm, 环形光 ID300 + 遮光罩;
- Delta 机器人 800 mm 工作直径, 悬挂在 2400 mm 高的门架上, 工作区对应 1.0 m~1.9 m 带位;
- SCARA 机器人 500 mm 臂长, 立柱安装, 工作区对应 2.4 m~3.3 m 带位;
- 两机器人工作区 不重叠 (避免运动学冲突);
- 每条通道为 300 mm 宽短带 (SV660N 200W), 长度 600 mm, 位置编号 0~5;
- 编码器 2500 线, 双屏蔽差分接入 EtherCAT 主站;
- 真空吸盘 (Delta) 和机械夹具 (SCARA) 分别接独立 DO 管理;
- 机器人立柱与带架电气绝缘, 避免信号接地环流。
四、程序架构
┌─────────────────────────────────────────────────────────────┐
│ Darra Runtime (单机) │
│ │
│ ┌───────── OB_250us (EtherCAT PDO) ────────────────────┐ │
│ │ 带编码器 → BeltPos 全局更新 │ │
│ │ 机器人轴 PDO (SV660N × 8: Delta 3 + SCARA 4 + Belt) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────── OB_1ms (主逻辑) ────────────────────────────┐ │
│ │ PRG_Vision (结果解析, 生成 Item) │ │
│ │ PRG_Tracker (环形队列, 滞后匹配) │ │
│ │ PRG_Dispatch (分配给 Delta/SCARA) │ │
│ │ PRG_Delta (任务状态机) │ │
│ │ PRG_Scara (任务状态机) │ │
│ │ PRG_Degrade (故障检测 + 兜底) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────── OB_500us (运动学计算) ──────────────────────┐ │
│ │ MC_BeltTrack (Delta + SCARA 皮带同步) │ │
│ │ MC_MoveLinAbs / MoveJ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌───────── OB_20ms (HMI + 上层系统) ────────────────────┐ │
│ │ HMI 刷新 / 热力图 / 订单同步 │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
关键约束:
- 编码器必须在最高优先级读取, 否则跟踪精度下降;
- 机器人运动学由 Darra.Robot.dll 内置, 500 μs 周期解算逆运动学;
- Delta 运动学参数
L_upper / L_lower / base_R / eef_R在实例化时输入; - SCARA 运动学
L1 / L2 / z_stroke同上; - 两机器人共用
BeltPos变量, 通过MC_BeltTrack指令同步抓取。
五、硬件 BOM (国产优先)
5.1 控制
| 设备 | 型号 | 数量 | 单价 (¥) | 小计 |
|---|---|---|---|---|
| 工控机 | 研华 MIC-770 / i7-12700 / 32 GB | 1 | 12 000 | 12 000 |
| HMI 总控 | 威纶通 cMT-3162X 22" | 1 | 9 800 | 9 800 |
| HMI 副工位 | 威纶通 MT8103iE 10.1" | 2 | 3 800 | 7 600 |
| 工业交换机 | 汇川 SW8 非网管 | 2 | 1 200 | 2 400 |
| UPS | APC SUA2200 | 1 | 4 200 | 4 200 |
5.2 机器人本体 + 控制 (国产)
| 设备 | 型号 | 数量 | 单价 (¥) | 小计 |
|---|---|---|---|---|
| Delta 并联机器人本体 | 国产三轴 Delta (800 mm 工作直径) | 1 | 58 000 | 58 000 |
| SCARA 四轴机器人本体 | 埃斯顿 ER20-500 | 1 | 42 000 | 42 000 |
| Delta 伺服 | 汇川 SV660N 400W (3 轴) | 3 | 2 800 | 8 400 |
| SCARA 伺服 | 汇川 SV660N 400W (4 轴) | 4 | 2 800 | 11 200 |
| 主带伺服 | 汇川 SV660N 750W | 1 | 3 600 | 3 600 |
| 通道带伺服 (×6) | 汇川 SV660N 200W | 6 | 2 400 | 14 400 |
| Delta 末端真空吸盘 | 定制 3 爪 | 1 | 3 500 | 3 500 |
| SCARA 末端夹具 | 气动并联爪 | 1 | 4 200 | 4 200 |
5.3 IO + 视觉
| 设备 | 型号 | 数量 | 单价 (¥) | 小计 |
|---|---|---|---|---|
| AM600 耦合器 | 汇川 | 2 | 800 | 1 600 |
| 32DI / 32DO | 汇川 AM600 | 4 | 1 600 | 6 400 |
| 8AI / 4AO | 汇川 AM600 | 2 | 2 500 | 5 000 |
| 高速编码器接口 | 板载 PDO | - | - | - |
| 海康工业相机 | MV-CA050-12GM 500 万像素 | 1 | 4 500 | 4 500 |
| 海康环形光源 | MV-LRDS-300-W | 1 | 1 800 | 1 800 |
| 真空发生器 + 压力开关 | SMC ZSE30A | 1 | 1 200 | 1 200 |
| 剔除推杆气缸 | SMC CDQ2B40-50D | 1 | 850 | 850 |
| 光电开关 | 奥托尼克斯 BR100-DDT | 12 | 260 | 3 120 |
| 主轴编码器 | 欧姆龙 E6B2-CWZ6C 2500 线 | 1 | 650 | 650 |
5.4 小计
| 类别 | 金额 (¥) |
|---|---|
| 控制 | 36 000 |
| 机器人 + 伺服 | 145 300 |
| IO + 视觉 | 25 120 |
| 硬件小计 | 206 420 |
| Darra Runtime 授权 | 25 000 |
| Darra HMI 授权 | 5 000 |
| 整线投资 | ¥ 236 420 |
六、IO 模块配置
6.1 选型思路
单 Runtime 管控, IO 集中在 2 个 AM600 机架 (一个在机器人立柱下, 一个在通道带侧):
- DI 主要: 视觉触发反馈、真空压力开关、机器人到位反馈、急停、门开关;
- DO 主要: 视觉触发、真空电磁阀、通道带启停、剔除气缸、安全输出;
- AI: 真空压力、相机帧率监控;
- 主带编码器直接走高速 PDO (SV660N 板载编码器接口), 不占用 AM600 通道。
6.2 地址分配
| 模块 | 地址 | 用途 |
|---|---|---|
| DI_0 (32DI) | %IX0.0~%IX3.7 | 启停按钮 + 急停 + 门 + 视觉反馈 + 上料到位 |
| DI_1 (32DI) | %IX4.0~%IX7.7 | Delta 真空吸附到位 × 3 + SCARA 夹具反馈 × 2 + 通道光电 × 6 |
| DO_0 (32DO) | %QX0.0~%QX3.7 | 视觉触发 + Delta 真空阀 × 3 + SCARA 夹具 × 2 + 补光 + 安全输出 |
| DO_1 (32DO) | %QX4.0~%QX7.7 | 通道带启停 × 6 + 剔除气缸 + 报警灯 + 辅助 |
| AI_0 (8AI) | %IW0~%IW14 | 真空压力 × 2 + 电流监测 × 4 + 余 |
| AQ_0 (4AO) | %QW0~%QW6 | 主带速度 SP + 通道带速度 SP + 余 |
6.3 绑定操作流程
- Studio →
扫描从站→ 识别 8 个 SV660N + 2 个 AM600 耦合器 + 海康网口相机; - 每个伺服选
CSP + 编码器反馈, 主带额外勾选编码器高速 PDO 反馈; - 新建
Axis_Belt, 绑定Slave_1:SV660N 750W; - 新建
Robot_Delta: 类型Delta3, 参数:L_upper = 300 mm(上臂);L_lower = 650 mm(下臂);base_R = 200 mm,eef_R = 45 mm;- 关联
Axis_DeltaA/B/C(绑定 Slave_2/3/4);
- 新建
Robot_Scara: 类型SCARA, 参数:L1 = 250 mm,L2 = 250 mm,z_stroke = 150 mm;- 关联
Axis_ScaraJ1~J4(绑定 Slave_5/6/7/8);
- 配置
MC_BeltTrack:- Delta 跟踪带
Axis_Belt, 抓取窗X ∈ [1000, 1900] mm; - SCARA 跟踪带
Axis_Belt, 抓取窗X ∈ [2400, 3300] mm;
- Delta 跟踪带
- 海康相机配置:
网口地址 192.168.1.100,硬件触发,ROI 600×480,帧率 120 fps,触发延迟 < 200 μs; - 配方管理器录入 SKU 表:
产品 A → 通道 1, 产品 B → 通道 2 ...; - 下载, 打开
机器人调试页点动, 观察FK/IK窗口坐标一致; - 点
跟踪演示, 让带运行 + 机器人跟随, 实时观察跟踪误差, 目标 ≤ 0.5 mm。
七、核心数据结构
TYPE TYPE_ITEM :
STRUCT
Id : UDINT; (* 唯一 ID *)
Sku : INT; (* SKU 分类 *)
BornBeltPos : LREAL; (* 拍照瞬间的带位置 *)
WorldX : REAL; (* 带坐标系内 X *)
WorldY : REAL; (* 带坐标系内 Y *)
ConfidencePct : REAL; (* 视觉置信度 *)
AssignedRobot : INT; (* 0=未分 1=Delta 2=SCARA *)
State : INT; (* 0=new 1=locked 2=picking 3=done 4=lost *)
TargetChannel : INT; (* 目标通道 1..6 *)
LockTime : DT;
PickTime : DT;
END_STRUCT
END_TYPE
TYPE TYPE_ROBOT :
STRUCT
Id : INT;
Kind : INT; (* 1=Delta 2=SCARA 3=6AXIS *)
Ready : BOOL;
Busy : BOOL;
Fault : BOOL;
LoadPct : REAL; (* 平均任务/分钟 *)
PickCount : UDINT;
MissCount : UDINT;
WorkZoneXMin : REAL;
WorkZoneXMax : REAL;
WorkZoneYMin : REAL;
WorkZoneYMax : REAL;
CurrentItemId : UDINT;
END_STRUCT
END_TYPE
TYPE TYPE_CAM_POSE :
STRUCT
X : REAL; Y : REAL; Z : REAL;
Rx : REAL; Ry : REAL; Rz : REAL;
END_STRUCT
END_TYPE
VAR_GLOBAL
BeltPos : LREAL; (* 带位置 mm, 由编码器更新 *)
ItemBuf : ARRAY[0..4095] OF TYPE_ITEM; (* 4K 环形缓冲 *)
ItemHead : UDINT;
Robot : ARRAY[1..3] OF TYPE_ROBOT; (* 预留 3 台 *)
Recipe_Sku : ARRAY[1..32] OF INT; (* SKU → 通道 *)
EStop : BOOL;
END_VAR
八、核心程序代码
8.1 主传送带位置更新 (250 μs)
PROGRAM PRG_Belt
VAR prev : DINT; cur : DINT; delta : DINT; END_VAR
cur := Axis_Belt.ActPos;
delta := cur - prev;
IF delta > 1250 THEN delta := delta - 2500; END_IF;
IF delta < -1250 THEN delta := delta + 2500; END_IF;
prev := cur;
BeltPos := BeltPos + DINT_TO_LREAL(delta) * BELT_MM_PER_PULSE;
8.2 视觉结果解析 + 入队
PROGRAM PRG_Vision
VAR
frameReady : BOOL;
res : ARRAY[0..31] OF TYPE_VISION_RES;
n, i : INT;
END_VAR
IF frameReady THEN
n := HikVision_GetResults(ADR(res), 32);
FOR i := 0 TO n - 1 DO
ItemBuf[ItemHead MOD 4096].Id := GenId();
ItemBuf[ItemHead MOD 4096].Sku := res[i].ClassId;
ItemBuf[ItemHead MOD 4096].BornBeltPos := BeltPos;
ItemBuf[ItemHead MOD 4096].WorldX := BeltPos + res[i].Cam_X;
ItemBuf[ItemHead MOD 4096].WorldY := res[i].Cam_Y;
ItemBuf[ItemHead MOD 4096].ConfidencePct := res[i].Conf;
ItemBuf[ItemHead MOD 4096].AssignedRobot := 0;
ItemBuf[ItemHead MOD 4096].State := 0;
ItemBuf[ItemHead MOD 4096].TargetChannel := Recipe_Sku[res[i].ClassId];
ItemHead := ItemHead + 1;
END_FOR;
END_IF;
8.3 任务分配 (负载平衡 + 工作区过滤)
PROGRAM PRG_Dispatch
VAR i : INT; item : POINTER TO TYPE_ITEM; x : REAL; END_VAR
(* 遍历队列, 对新物体分配机器人 *)
FOR i := 0 TO 4095 DO
item := ADR(ItemBuf[i]);
IF item^.State = 0 THEN
x := item^.WorldX - BeltPos; (* 相对当前带位的距离 *)
(* 优先 Delta (通道 1~3 由 Delta 负责) *)
IF (item^.TargetChannel <= 3)
AND (x >= Robot[1].WorkZoneXMin AND x <= Robot[1].WorkZoneXMax)
AND (item^.WorldY >= Robot[1].WorkZoneYMin
AND item^.WorldY <= Robot[1].WorkZoneYMax)
AND Robot[1].Ready AND NOT Robot[1].Busy THEN
item^.AssignedRobot := 1;
item^.State := 1; (* locked *)
(* 优先 SCARA (通道 4~6) *)
ELSIF (item^.TargetChannel >= 4)
AND (x >= Robot[2].WorkZoneXMin AND x <= Robot[2].WorkZoneXMax)
AND (item^.WorldY >= Robot[2].WorkZoneYMin
AND item^.WorldY <= Robot[2].WorkZoneYMax)
AND Robot[2].Ready AND NOT Robot[2].Busy THEN
item^.AssignedRobot := 2;
item^.State := 1;
(* 过了 Delta 工作区还没被抓, SCARA 顶上 (跨通道降级) *)
ELSIF x > Robot[1].WorkZoneXMax
AND x <= Robot[2].WorkZoneXMax
AND Robot[2].Ready AND NOT Robot[2].Busy
AND Robot[1].LoadPct > 0.85 THEN
item^.AssignedRobot := 2;
item^.State := 1;
END_IF;
END_IF;
END_FOR;
8.4 Delta 抓取 (皮带同步)
PROGRAM PRG_Delta
VAR
i : INT;
pose : TYPE_CAM_POSE;
itemId : UDINT;
END_VAR
CASE Robot[1].State OF
0: (* 找任务 *)
FOR i := 0 TO 4095 DO
IF ItemBuf[i].State = 1 AND ItemBuf[i].AssignedRobot = 1 THEN
Robot[1].CurrentItemId := ItemBuf[i].Id;
ItemBuf[i].State := 2;
Robot[1].Busy := TRUE;
Robot[1].State := 1;
EXIT;
END_IF;
END_FOR;
1: (* 皮带同步抓取 *)
itemId := Robot[1].CurrentItemId;
pose.X := ItemBuf[itemId MOD 4096].WorldX;
pose.Y := ItemBuf[itemId MOD 4096].WorldY;
pose.Z := 140.0; (* 抓取 Z *)
pose.Rz := 0.0;
MC_BeltTrack(
Robot := ADR(Robot_Delta),
Belt := ADR(Axis_Belt),
TargetPose := pose,
TrackMode := 1, (* 跟随模式 *)
Vel := 2400.0,
Acc := 15000.0
);
IF MC_Done THEN
DO_VAC_DELTA := TRUE;
VacTimer(IN := TRUE, PT := T#30ms);
IF VacTimer.Q AND DI_VAC_OK_DELTA THEN
Robot[1].State := 2;
VacTimer(IN := FALSE);
ELSIF VacTimer.Q AND NOT DI_VAC_OK_DELTA THEN
ItemBuf[itemId MOD 4096].State := 4; (* lost *)
Robot[1].MissCount := Robot[1].MissCount + 1;
DO_VAC_DELTA := FALSE;
Robot[1].Busy := FALSE;
Robot[1].State := 0;
END_IF;
END_IF;
2: (* 下料到通道 *)
pose.X := 1400.0; (* 通道 1-3 离带中心 X 坐标 *)
pose.Y := 300.0 + (ItemBuf[Robot[1].CurrentItemId MOD 4096].TargetChannel - 1) * 200.0;
pose.Z := 120.0;
MC_MoveLinAbs(
Robot := ADR(Robot_Delta), Target := pose,
Vel := 2800.0, Acc := 18000.0
);
IF MC_Done THEN
DO_VAC_DELTA := FALSE;
Robot[1].PickCount := Robot[1].PickCount + 1;
ItemBuf[Robot[1].CurrentItemId MOD 4096].State := 3;
Robot[1].Busy := FALSE;
Robot[1].State := 0;
END_IF;
END_CASE;
8.5 SCARA 抓取 (同步 + 机械夹)
PROGRAM PRG_Scara
(* 与 Delta 结构几乎一致, 只把 DO_VAC_DELTA 换成 DO_CLAMP_SCARA
速度/加速按 SCARA 能力调低: Vel 1800, Acc 8000 *)
CASE Robot[2].State OF
0: FindTaskForScara();
1: MC_BeltTrack(Robot:=ADR(Robot_Scara), Belt:=ADR(Axis_Belt),
TargetPose:=pose, TrackMode:=1,
Vel:=1800.0, Acc:=8000.0);
IF MC_Done THEN DO_CLAMP_SCARA := TRUE; ... END_IF;
2: (* 放下到通道 4-6 *)
pose.Y := 700.0 + (channel - 4) * 200.0;
MC_MoveLinAbs(Robot:=ADR(Robot_Scara), Target:=pose,
Vel:=2000.0, Acc:=10000.0);
IF MC_Done THEN DO_CLAMP_SCARA := FALSE; ... END_IF;
END_CASE;
8.6 故障降级 (一台顶两台)
PROGRAM PRG_Degrade
IF Robot[1].Fault THEN
(* Delta 故障, 把 Delta 工作区的任务让 SCARA 抢, 速度降到 60% *)
Robot[2].WorkZoneXMin := 1000.0; (* 扩大 SCARA 工作区 *)
Robot[2].WorkZoneXMax := 3300.0;
Recipe_BeltSpeed := BELT_SPEED_NORMAL * 0.6;
RaiseAlarm(A_ROBOT_DELTA_FAULT, 2);
ELSIF Robot[2].Fault THEN
Robot[1].WorkZoneXMin := 1000.0;
Robot[1].WorkZoneXMax := 3300.0;
Recipe_BeltSpeed := BELT_SPEED_NORMAL * 0.6;
RaiseAlarm(A_ROBOT_SCARA_FAULT, 2);
ELSE
Robot[1].WorkZoneXMin := 1000.0; Robot[1].WorkZoneXMax := 1900.0;
Robot[2].WorkZoneXMin := 2400.0; Robot[2].WorkZoneXMax := 3300.0;
Recipe_BeltSpeed := BELT_SPEED_NORMAL;
END_IF;
8.7 负载统计 (滑动窗)
(* 每 10 s 计算 load pct = 近 10 s 拣件数 / 设计峰值 *)
PROGRAM PRG_Load
VAR picks1_10s, picks2_10s : UDINT; tick : TON; END_VAR
tick(IN := TRUE, PT := T#10s);
IF tick.Q THEN
Robot[1].LoadPct := UDINT_TO_REAL(picks1_10s) / DESIGN_PEAK_PER_10S;
Robot[2].LoadPct := UDINT_TO_REAL(picks2_10s) / DESIGN_PEAK_PER_10S;
picks1_10s := 0; picks2_10s := 0;
tick(IN := FALSE);
END_IF;
IF Robot[1].Busy THEN picks1_10s := picks1_10s + 1; END_IF;
IF Robot[2].Busy THEN picks2_10s := picks2_10s + 1; END_IF;
8.8 尾端剔除 (漏抓物体清线)
FOR i := 0 TO 4095 DO
IF ItemBuf[i].State = 0 OR ItemBuf[i].State = 1 THEN
IF (BeltPos - ItemBuf[i].BornBeltPos) > END_POS_MM THEN
(* 过尾端还没抓走, 推下去进回收 *)
DO_END_PUSH := TRUE;
PushTimer(IN := TRUE, PT := T#25ms);
ItemBuf[i].State := 4;
END_IF;
END_IF;
END_FOR;
PushTimer(IN := FALSE);
IF PushTimer.Q THEN DO_END_PUSH := FALSE; END_IF;
九、运行与调试
9.1 首次调试
- 手动空载运行主带 + 通道带, 确认方向一致, 编码器脉冲正向递增;
- 视觉标定: 放标定板 → 用 Studio 内置
BeltHandEye向导算出相机 → 带坐标系齐次矩阵; - Delta 手眼标定: 相机抓取标定球, 机器人 4 点采集, 工具坐标系误差 ≤ 0.3 mm;
- SCARA 同样流程;
- 空负载跑 30 分钟, 目视
跟踪误差曲线 < 0.5 mm, 抖动 < 0.3 mm; - 上轻质模型 (乒乓球) 测试 100 件, Delta/SCARA 各自抓成功率 ≥ 99%;
- 模拟 Delta 故障 (HMI
模拟故障) → 观察 SCARA 扩区 + 带降速; - 正式上料 (独立包装糖果 / 小瓶饮料) 试产。
9.2 常见问题
| 现象 | 定位 | 处理 |
|---|---|---|
| 跟踪误差 > 2 mm | 编码器脉冲丢失 | 差分屏蔽线检查, 提高 PDO 优先级 |
| Delta 偶尔吸不住 | 真空不足 | 真空发生器供气压力 ≥ 0.5 MPa, 换大口径吸盘 |
| 两机器人抢同一件 | 任务表锁失效 | 检查 State=1 locked 分配原子性 |
| 漏抓率上升 | 视觉帧率下降 | 清相机镜头 + 增大补光 |
| 通道堆件 | 打包带节拍慢 | 下游装箱速度跟不上, 通道带 SP 调低 |
| HMI 热力图滞后 | 上层系统压力大 | 降低上报频率, 本地缓存 |
9.3 实测性能
| 指标 | 目标 | 实测 |
|---|---|---|
| 拣选速率 | 480 件/min | 482 件/min |
| 跟踪精度 | ± 0.5 mm | ± 0.35 mm |
| Delta 成功率 | ≥ 99.5% | 99.72% |
| SCARA 成功率 | ≥ 99.0% | 99.41% |
| 单台故障降级 | 50% 产能 | 实测 58% 产能 |
| MTBF | ≥ 2000 h | 2400 h (首 3 个月) |
| 投产 30 天 OEE | ≥ 92% | 93.1% |
十、Darra 功能对照表
| 业务需求 | Darra 对应功能 | 模块 |
|---|---|---|
| Delta 运动学 | Darra.Robot.dll Type=Delta3 (内置) | PLC Runtime |
| SCARA 运动学 | Darra.Robot.dll Type=SCARA (内置) | PLC Runtime |
| 皮带同步抓取 | MC_BeltTrack 指令 | MC 库 |
| 主带编码器高速 | SV660N 高速 PDO + DarraRT.sys | 驱动 |
| 视觉接入 | 海康 SDK 插件 + 硬件触发 | IDE → 视觉 |
| 物体跟踪队列 | 环形缓冲 + 编码器时戳 | PLC 代码 |
| 任务动态分配 | 自定义 FB + 工作区 / 负载 / 优先级 | PLC 代码 |
| 故障降级 | 状态机 + 工作区动态调整 | PLC 代码 |
| 真空 / 夹具 | DO + 压力开关 | IO |
| 第 3 台机器人扩展 | Robot 数组预留 + 配方扩容 | 模板 |
| 上层系统接入 | OPC UA / REST | Service |
| 三级报警 | AlarmManager | IDE → 报警 |
| 分拣热力图 | Darra HMI Designer | IDE → HMI |
| AI 视觉分类 | 可接入云端模型 | AI / Cloud |
十一、项目总结
11.1 周期
| 阶段 | 工时 |
|---|---|
| 方案设计 | 1 周 |
| 机械 + 电气组装 | 2 周 |
| 视觉 + 机器人标定 | 1 周 |
| 任务分配逻辑 + 调试 | 1 周 |
| 联机验证 + 试运行 | 1 周 |
| 合计 | 6 周 |
11.2 投产效果
| 项 | 原三控制器方案 | Darra 单 Runtime |
|---|---|---|
| 控制器数量 | 3 (Delta 专用 + SCARA 专用 + 总控 PLC) | 1 (研华 + Darra Runtime) |
| 控制 BOM | ¥ 38 万 + 年维护费 ¥ 6 万 | ¥ 23 万, 年费 ¥ 0 |
| 跟踪精度 | ± 2 mm | ± 0.35 mm |
| 控制器编程语言 | 各品牌专用语言 + 梯形图 | 统一 SCL / LAD / CFC |
| 故障恢复 | 人工切换 | 自动降级 < 2 s |
| 扩第 3 台 | 重新规划 | 模板扩展即可 |
11.3 可复制性
- 同类分拣线 (电商/药品/3C 小件/医药包装) 可按
MULTI_ROBOT_SORT模板直接派生; - Delta + SCARA 可按客户需求替换为 2 台 Delta / 2 台 SCARA / Delta + 6 轴等任意组合, Darra.Robot.dll 运动学库全部内置;
- 视觉模型可在云端训练, Darra Cloud 自动下发;
- 单 Runtime 架构天生支持扩展第 3~N 台机器人, 任务表 / 工作区数组预留好了就行。
11.4 核心价值
- 三套变一套: 不再需要进口机器人控制器 + 专用 PLC + 独立视觉机, 全部在 Darra Runtime 内;
- 一个工程师: 不需要机器人品牌培训, SCL 语言 + 向导就能完成 Delta + SCARA 编程;
- 真正混搭: 两台运动学不同的机器人共用编码器, 任务动态分配, 实测跟踪 0.35 mm;
- 自带降级: 一台停机, 另一台自动扩区 + 带降速, 60% 产能延续;
- 国产成本: 全链条国产 (工控机/机器人/伺服/视觉/IO), BOM 降 40%+;
- OEM 可落地: 按工控机永久授权, 分拣装备厂商可直接打包对外销售。
一台工控机 = Delta + SCARA + 视觉 + 编码器跟踪, 并通过 OPC UA / REST 向上层系统暴露设备状态, 把设备侧分拣控制从 "三品牌拼接" 回归到 "单软件一体"。