智能产线总控 (综合案例)
一套 Darra Runtime, 一张 EtherCAT 链, 管住整条 3C 电子智能产线。
本案例覆盖 5 工位 × 3 机器人 × 18 伺服 × 2 套视觉, 并通过 OPC UA + REST 向上层 MES/SCADA 暴露生产数据, 总投资约 ¥ 110 万/条, 把传统"多台 PLC + 独立 SCADA + 协议网关 + 运动卡 SDK"的多套拼装整合到单 Runtime。MES/SCADA 仍是独立的上层系统。
一、设备简介
1.1 产线定位
- 客户: 华东某消费电子代工厂 (江苏昆山), 代工无线耳机 / 智能手环外壳及总装
- 产品: 3C 电子消费品, 工件尺寸 ≤ 100mm × 60mm × 20mm, 重量 ≤ 300g
- 产能目标: 日产 2,500 件, 单件节拍 13.5 秒, 综合良率 ≥ 99%
- 人力目标: 单线 3 人 (原 15 人)
1.2 系统规模
| 项 | 数量 | 说明 |
|---|---|---|
| 工位总数 | 5 | 上料 / CNC / 机器人组装 / 视觉 / 贴标打包 |
| 机器人 | 3 台 | 六轴 (上料 1 + 组装 1 + 打包 1) |
| 伺服轴 | 18 轴 | CNC 3 轴 × 2 + 传送带 × 4 + 贴标 2 轴 + 其他 |
| EtherCAT 从站 | 约 40 个 | 含伺服 + 远程 IO + 安全 IO |
| 本地 IO | 约 200 点 | 工位 IO, 每工位 32DI/32DO/8AI/4AO |
| 视觉 | 2 套 | 装配到位 + 外观 AOI |
| HMI | 5 + 1 | 工位触摸屏 × 5 + 车间大屏 × 1 |
| 上层系统对接 | 2 套 | 上层 MES (REST) + 上层 ERP (OPC UA), 均为独立的第三方系统 |
1.3 节拍与可用率
| 指标 | 目标 | 实测 |
|---|---|---|
| 单件节拍 | ≤ 15 s | 13.5 s |
| EtherCAT 周期 | 1 ms | 1 ms (抖动 ≤ 10μs) |
| MES 上报延迟 | ≤ 500 ms | 320 ms |
| 系统可用率 | ≥ 98% | 99.1% |
| MTBF | ≥ 720 h | 约 900 h |
| 断电恢复 | ≤ 10 s 接续 | 8 s |
| 断网独立运行 | ≥ 72 h | 本地缓存 + 恢复补传 |
二、项目模块组成
本案例的核心项目模块按"物理工位 + 逻辑对象"两层组织。整线运行在同一个 Darra Runtime 工程里, 所有工位的 FB 共享一份全局变量表。
2.1 工艺流程
- 上料工位 — AGV 送料盘到工位, R1 扫码后抓料到传送带, UID 写入
T_Station[1].sCurrentUID - CNC 工位 — 三轴 CNC 对外壳倒角/开孔, 主轴转速采集, 加工参数入库
- 组装工位 — R2 搬放主板 + 电池, 力控插入 (协作机器人 FR5)
- 视觉工位 — 双相机: 上方 AOI + 侧方装配到位, 深度学习模型分类 NG 原因
- 贴标打包 — 喷码机打 UID, R3 将成品放入料盘, 满盘后 AGV 拉走
2.2 逻辑对象
| 对象 | 数量 | 类型 | 职责 |
|---|---|---|---|
T_Station | 5 | UDT | 工位状态 / UID / 节拍 / 计数 |
T_Robot | 3 | UDT | 机器人姿态 / 程序 / 状态 |
T_Conveyor | 4 | UDT | 传送带速度 / 到位信号 |
T_Vision | 2 | UDT | 触发 / 结果 / 置信度 |
T_MES | 1 | UDT | 工单 / Token / 上报队列 |
T_Alarm | 256 | 队列 | L1~L4 分级报警 |
三、机械装配架构
3.1 产线布局
AGV 来料口
│
▼
┌──────────────────┐ ┌──────────────────┐
│ 工位 1 上料 │ │ 工位 2 CNC │
│ R1 (ER6-1600) │───▶│ 3 轴 CNC × 2 │
│ 32 DI/32 DO │ │ 32 DI/32 DO + 4AI │
└──────────────────┘ └──────────────────┘
│ │
└──────▶ 传送带 Conv1 ◀──┘
│
▼
┌──────────────────┐ ┌──────────────────┐
│ 工位 3 组装 │ │ 工位 4 视觉 │
│ R2 (FR5 协作) │───▶│ AOI + 装配到位 │
│ 力控插入 │ │ 海康相机 + GPU │
└──────────────────┘ └──────────────────┘
│ │
└──────▶ 传送带 Conv3 ◀──┘
│
▼
┌──────────────────┐
│ 工位 5 贴标打包 │
│ R3 (ER6B-C10) │──▶ AGV 出料口
│ 喷码 + 贴标 │
└──────────────────┘
3.2 工件流向
- 料盘进入上料工位 → 扫码读取原料 UID
- R1 抓取单件 → 放置 Conv1 → 传送到 CNC 工位
- CNC 夹具定位 → 三轴加工 → 释放至 Conv2
- R2 取件到组装台 → 放置主板 → 力控插入电池 → 释放至 Conv3
- Conv3 到达视觉工位 → 双相机同步拍照 → OK 件进入 Conv4, NG 件进入返工道
- Conv4 到达贴标 → 喷码机打 UID → R3 抓到出料盘
3.3 机械精度要求
| 工位 | 重复精度 | 备注 |
|---|---|---|
| 工位 1 R1 | ±0.1 mm | 抓取料盘孔位 |
| 工位 2 CNC | ±0.02 mm | 精密加工 |
| 工位 3 R2 | ±0.05 mm | 力控装配 |
| 工位 5 R3 | ±0.2 mm | 装箱, 精度要求低 |
四、程序架构
整线只跑一个 Darra Runtime, 但逻辑上划分为多个 OB (Organization Block) 与 FB (Function Block), 并通过 DarraSync 共享变量给 HMI / 中控 / 云端。
4.1 OB 分层
4.2 FB 清单
| FB | 作用 | 周期 |
|---|---|---|
FB_SafetyChain | 急停 / 安全门 / 光栅检查 | 1 ms |
FB_Station1_Loading | 上料状态机 | 1 ms |
FB_Station2_CNC | CNC 工艺控制 | 1 ms |
FB_Station3_Assembly | 组装状态机 + 力控 | 1 ms |
FB_Station4_Vision | 视觉触发 + 结果读取 | 1 ms |
FB_Station5_Packing | 贴标打包 | 1 ms |
FB_ConveyorSync | 传送带节拍同步 | 1 ms |
FB_RobotGroup | 3 机器人协同 | 1 ms |
FB_MESUpload | REST 上报 | 100 ms |
FB_OPCPublish | OPC UA 发布 | 100 ms |
FB_AlarmScan | 报警扫描 + 推送 | 1 s |
FB_DatabaseLog | 追溯数据入库 | 1 s |
FB_SAPSummary | SAP 汇总上报 | 10 s |
4.3 多工位 DarraSync
本案例使用单 Runtime, DarraSync 仅用于 HMI 与 Runtime 之间的变量订阅。对于后续扩容到多 PLC 域的场景, DarraSync 会跨 Runtime 以 200ms 周期同步 T_Station / T_Robot / T_MES 这些关键 UDT, 见第八节。
五、硬件 BOM
5.1 控制主机
| 项 | 型号 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 工控机 | 研华 ARK-3520L (i7-9700 / 32GB DDR4 / 512GB NVMe) | 1 | 12,800 | 12,800 |
| 工位触摸屏 | 研华 TPC-1881WP 21.5" | 5 | 6,500 | 32,500 |
| 车间大屏 | 创维 55" 商用屏 + 壁挂 | 1 | 5,200 | 5,200 |
| UPS 在线式 | 山特 C2K 2000VA | 1 | 3,500 | 3,500 |
5.2 伺服与电机
| 项 | 型号 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 伺服驱动 | 汇川 SV660N (CiA 402 / 400W) | 18 | 3,200 | 57,600 |
| 伺服电机 | 汇川 ISMH1-40B30 (400W 绝对值) | 18 | 2,800 | 50,400 |
| 行星减速机 | 纽卡特 PLE 系列 | 18 | 1,200 | 21,600 |
5.3 机器人
| 项 | 型号 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 上料机器人 | 埃斯顿 ER6-1600 (6kg / 臂展 1600) | 1 | 48,000 | 48,000 |
| 组装机器人 | 法奥意威 FR5 (5kg 协作 / 力控) | 1 | 68,000 | 68,000 |
| 打包机器人 | 埃夫特 ER6B-C10 (6kg 经济型) | 1 | 42,000 | 42,000 |
| 电动夹爪 | 大寰 PGE-50 | 3 | 4,500 | 13,500 |
5.4 IO 与分布式
| 项 | 型号 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 远程 IO (工位) | 汇川 GL10-EC / 32DI + 32DO + 8AI + 4AO | 5 | 4,200 | 21,000 |
| 安全 IO (FSoE) | 汇川 GL10-FSO | 2 | 5,600 | 11,200 |
| 光电 / 接近开关 | 倍加福 / 欧姆龙 | 60 | 120 | 7,200 |
| 急停 / 安全光栅 | SICK + 欧姆龙 | 10 | 1,800 | 18,000 |
5.5 视觉与外设
| 项 | 型号 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 装配到位相机 | 海康 MV-CA050-12GM + 镜头 | 1 | 5,800 | 5,800 |
| AOI 相机 | 海康 MV-CH120-10UM 1200W | 1 | 18,000 | 18,000 |
| 视觉光源 | CCS LDL 条形 + 环形 | 4 | 1,200 | 4,800 |
| AI 视觉工控机 | 研华 MIC-710AI | 1 | 15,000 | 15,000 |
| 扫码枪 | 海康 MV-ID2013M | 3 | 1,600 | 4,800 |
| 喷码机 | Leadtech CIJ | 1 | 18,000 | 18,000 |
| 贴标机 | 申豪 SH-230 | 1 | 12,000 | 12,000 |
5.6 网络与辅件
| 项 | 型号 | 数量 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|---|
| 工业交换机 | 华为 S1700-16G 非管理 | 2 | 2,000 | 4,000 |
| 光纤收发器 | 海康 | 2 | 480 | 960 |
| 电气柜 | 定制 1.8m × 2.0m | 1 | 18,000 | 18,000 |
| 线缆 / 接插 | 菲尼克斯 + 威琅 | 1 批 | 12,000 | 12,000 |
| 安装工时 | 自有 | 1 | 35,000 | 35,000 |
5.7 Darra 软件授权
| 项 | 说明 | 单价 (¥) | 小计 (¥) |
|---|---|---|---|
| Darra Runtime (终端) | 单工控机永久授权 | 35,000 | 35,000 |
| Darra IDE | 工程师开发 | 15,000 | 15,000 |
| DarraCloud 年费 | 远程运维 + 数据备份 | 3,600/年 | 3,600 |
5.8 预算总表
| 大项 | 小计 (¥) |
|---|---|
| 控制主机 | 54,000 |
| 伺服 / 电机 | 129,600 |
| 机器人 | 171,500 |
| IO / 安全 | 57,400 |
| 视觉 / 外设 | 78,400 |
| 网络 / 辅件 / 安装 | 69,960 |
| Darra 软件 | 53,600 |
| 硬件 + 软件小计 | 614,460 |
| 调试与实施 (1 工程师 × 45 天 + 差旅) | 60,000 |
| 备件与风险预留 | 60,000 |
| 项目总计 (不含税) | ≈ 734,460 |
| 对外含税报价 | ≈ ¥ 1,100,000 (110 万) |
六、IO 模块配置
6.1 IO 模块清单 (按工位)
| 工位 | 模块 | 型号 | DI | DO | AI | AO | 安全 |
|---|---|---|---|---|---|---|---|
| 工位 1 上料 | IO-S1 | 汇川 GL10-EC | 32 | 32 | 8 | 4 | — |
| 工位 2 CNC | IO-S2 | 汇川 GL10-EC | 32 | 32 | 8 | 4 | — |
| 工位 3 组装 | IO-S3 | 汇川 GL10-EC | 32 | 32 | 8 | 4 | — |
| 工位 4 视觉 | IO-S4 | 汇川 GL10-EC | 32 | 32 | 8 | 4 | — |
| 工位 5 贴标 | IO-S5 | 汇川 GL10-EC | 32 | 32 | 8 | 4 | — |
| 产线安全 | SAFE-1 | 汇川 GL10-FSO | — | — | — | — | FSoE 8 路 |
| 机器人围栏 | SAFE-2 | 汇川 GL10-FSO | — | — | — | — | FSoE 8 路 |
合计: 160 DI + 160 DO + 40 AI + 20 AO + 16 FSoE。
6.2 IO 地址分配 (节选)
| 地址 | 类型 | 符号 | 说明 |
|---|---|---|---|
| %IX0.0 | DI | g_EmergencyStop | 总急停 (硬接 FSoE) |
| %IX0.1 | DI | g_SafetyGateAll | 安全门总开关 |
| %IX10.0 | DI | g_S1.bArrive | 工位 1 工件到位光电 |
| %IX10.1 | DI | g_S1.bMaterialReady | 工位 1 料盘到位 |
| %IX10.2 | DI | g_S1.bDone | 工位 1 完成按钮 |
| %IX10.3 | DI | g_S1.bMaterialLow | 料盘余量低 |
| %IX20.0 | DI | g_S2.bCNCAtHome | CNC 回零到位 |
| %IX20.1 | DI | g_S2.bSpindleOK | 主轴就绪 |
| %IX30.0 | DI | g_S3.bPartInJig | 组装工装有料 |
| %IX30.1 | DI | g_S3.bForceReady | 力控就绪 |
| %IX40.0 | DI | g_S4.bVisionTrigReady | 视觉相机就绪 |
| %IX50.0 | DI | g_S5.bPrinterOK | 喷码机就绪 |
| %QX0.0 | DO | g_LineEnable | 产线使能 |
| %QX10.0 | DO | g_S1.bConvStart | 工位 1 传送带启动 |
| %QX10.1 | DO | g_S1.bWarnLight | 工位 1 报警灯 |
| %QX20.0 | DO | g_S2.bSpindleRun | CNC 主轴启动 |
| %QX30.0 | DO | g_S3.bClampClose | 工装夹紧 |
| %QX40.0 | DO | g_S4.bVisionTrigger | 视觉触发信号 |
| %QX50.0 | DO | g_S5.bPrinterTrigger | 喷码触发 |
| %IW100 | AI | g_S2.rSpindleCurrent | 主轴电流反馈 |
| %IW102 | AI | g_S3.rForceZ | Z 向装配力 |
| %QW100 | AO | g_S2.rSpindleSetFreq | 主轴频率设定 |
| %QW102 | AO | g_S5.rConvSpeed | 出料传送带速度 |
6.3 IO 用途分工 (工位间交接)
| 交接 | 上游信号 | 下游信号 | 握手方式 |
|---|---|---|---|
| 工位 1 → 工位 2 | S1.bDone (DO) + UID 通过 DarraSync | S2.bReadyReceive (DI) | 边沿 + 握手变量 |
| 工位 2 → 工位 3 | S2.bDone + 加工参数 S2.Params | S3.bReadyReceive | 同上 |
| 工位 3 → 工位 4 | S3.bDone + 装配到位 flag | S4.bVisionReady | DarraSync UDT |
| 工位 4 → 工位 5 | S4.bOK / S4.bNG + sCategory | S5.bReadyPack / S5.bReadyReject | NG 自动分流 |
| 工位 → 机器人 | S3.bRequestPick → R2.bJobStart | R2.bJobDone → S3.bPartInJig | 机器人握手 |
| 工位 → MES | g_Mes.ProductionQueue[] | g_Mes.AckQueue[] | 缓冲队列 |
6.4 数据绑定 (多机器人 + 多 PLC)
# DarraSync 配置 (本案例: 1 Runtime + HMI 多终端)
syncGroups:
- name: PROD_Pub # 产线向 HMI 发布
direction: Publish
target: HMI_* # 通配 5 工位屏 + 中控大屏
interval: 200ms
variables:
- g_Station[1..5]
- g_Robot[1..3]
- g_Conveyor[1..4]
- g_Vision[1..2]
- g_Mes
- g_Alarm.ActiveList[1..32]
- name: CMD_Sub # HMI 向产线下发命令
direction: Subscribe
source: HMI_MAIN
interval: 100ms
variables:
- g_Cmd.bLineEnable
- g_Cmd.bPauseLine
- g_Cmd.bResetAlarm
- g_Cmd.sWorkOrder
- name: CLOUD_Pub # 关键数据上云
direction: Publish
target: DarraCloud
interval: 1s
encryption: TLS_1_3
variables:
- g_Production
- g_OEE
- g_EnergyMeter
- g_Alarm.HistoryBuffer[1..64]
机器人绑定: 三台机器人的驱动器都挂在同一条 EtherCAT 上, 通过 Darra 内置机器人对象屏蔽 ER6 / FR5 / ER6B 的指令差异, 上层代码可以只用 Robot_CallProgram(g_Robot[i], nProgramId) 调用。
七、核心数据结构
7.1 工位状态
TYPE T_Station :
STRUCT
nId : INT; // 工位号 1..5
eState : E_StationState; // 见下
bArrive : BOOL; // 工件到位
bReady : BOOL; // 准备好出料
bFault : BOOL; // 工位故障
sCurrentUID : STRING(32); // 当前工件 UID
dtStartTime : DT; // 加工开始
dtEndTime : DT; // 加工结束
rCycleTime : REAL; // 本次节拍 (秒)
nTodayCount : DINT; // 今日产量
nTodayNg : DINT; // 今日不良
rYield : REAL; // 良率
Params : ARRAY[1..16] OF REAL; // 工艺参数
END_STRUCT
END_TYPE
TYPE E_StationState :
(
Idle := 0,
Waiting := 1,
Processing := 2,
Done := 3,
Fault := 9
);
END_TYPE
7.2 机器人
TYPE T_Robot :
STRUCT
nId : INT;
sModel : STRING(16); // ER6 / FR5 / ER6B
eState : E_RobotState;
bHomed : BOOL;
bReady : BOOL;
bBusy : BOOL;
rPos : ARRAY[1..6] OF REAL; // 当前六轴
rTarget : ARRAY[1..6] OF REAL; // 目标六轴
nCurrentProgram : INT; // 当前程序号
rGripperForce : REAL; // 夹爪力
sFaultMsg : STRING(120);
END_STRUCT
END_TYPE
7.3 视觉
TYPE T_Vision :
STRUCT
nId : INT;
bTrigger : BOOL;
bDone : BOOL;
bResult : BOOL; // TRUE=OK
sCategory : STRING(32); // 缺陷分类
rScore : REAL; // 置信度 0.0~1.0
sImagePath : STRING(240); // 图像存档
dtTimestamp : DT;
END_STRUCT
END_TYPE
7.4 MES 工单
TYPE T_MES :
STRUCT
bOnline : BOOL;
sBaseUrl : STRING(80); // http://mes.local/api
sToken : STRING(240); // JWT
sWorkOrder : STRING(32); // WO20260417001
sProductModel : STRING(24);
nOrderQty : DINT;
nProducedQty : DINT;
nNgQty : DINT;
dtLastSync : DT;
nFailCount : INT;
LocalBuffer : ARRAY[1..512] OF T_MesBufferItem;
END_STRUCT
END_TYPE
7.5 产品追溯 (UID 关联)
TYPE T_ProductTrace :
STRUCT
sUID : STRING(32); // 全程不变
sWorkOrder : STRING(32);
sModel : STRING(24);
dtStartLine : DT;
dtEndLine : DT;
StationRecords : ARRAY[1..5] OF T_StationRecord;
VisionRecords : ARRAY[1..2] OF T_VisionResult;
sOperator : STRING(16);
bFinalOK : BOOL;
sFinalRemark : STRING(200);
END_STRUCT
END_TYPE
TYPE T_StationRecord :
STRUCT
nStationId : INT;
dtIn : DT;
dtOut : DT;
rCycleTime : REAL;
Params : ARRAY[1..16] OF REAL;
sMachineLog : STRING(200);
END_STRUCT
END_TYPE
八、核心程序代码
8.1 主循环 (OB1)
PROGRAM OB1
VAR
i : INT;
bLineRun : BOOL;
END_VAR
// 1) 安全联锁 (最高优先级, 不允许被延迟)
FB_SafetyChain();
IF NOT g_Safety.bLineSafe THEN
FOR i := 1 TO 3 DO
Robot_Stop(g_Robot[i]);
END_FOR;
FOR i := 1 TO 5 DO
g_Station[i].eState := E_StationState.Fault;
END_FOR;
g_LineEnable := FALSE;
RETURN;
END_IF;
// 2) 产线使能逻辑
bLineRun := g_LineEnable
AND g_Mes.bOnline
AND (g_Mes.sWorkOrder <> '')
AND g_Mes.nProducedQty < g_Mes.nOrderQty;
// 3) 各工位状态机 (单 Runtime 下, 这里就是"并发")
IF bLineRun THEN
FB_Station1_Loading(g_Station[1]);
FB_Station2_CNC(g_Station[2]);
FB_Station3_Assembly(g_Station[3]);
FB_Station4_Vision(g_Station[4]);
FB_Station5_Packing(g_Station[5]);
FB_ConveyorSync(g_Station, g_Conveyor);
END_IF;
END_PROGRAM
8.2 工位 1: 上料 + UID 绑定
FUNCTION_BLOCK FB_Station1_Loading
VAR_IN_OUT
st : T_Station;
END_VAR
VAR
tWait : TON;
END_VAR
CASE st.eState OF
E_StationState.Idle:
IF st.bArrive AND g_Robot[1].bReady THEN
// 1) 扫码绑定 UID
st.sCurrentUID := ScanBarcode(1);
IF st.sCurrentUID = '' THEN
Alarm_Raise(AlarmId.ScanFail, '工位 1 扫码失败');
RETURN;
END_IF;
// 2) 创建追溯记录
Trace_Create(st.sCurrentUID, g_Mes.sWorkOrder, g_Mes.sProductModel);
// 3) 启动机器人取料程序
st.dtStartTime := NOW();
Robot_CallProgram(g_Robot[1], 101);
st.eState := E_StationState.Processing;
END_IF;
E_StationState.Processing:
IF g_Robot[1].bReady AND NOT g_Robot[1].bBusy THEN
st.eState := E_StationState.Done;
END_IF;
E_StationState.Done:
st.dtEndTime := NOW();
st.rCycleTime := DT_DIFF_S(st.dtEndTime, st.dtStartTime);
st.nTodayCount := st.nTodayCount + 1;
// 4) 工位记录入追溯 + 交接给工位 2
Trace_RecordStation(st.sCurrentUID, 1, st);
g_HandOff[1].sUID := st.sCurrentUID;
g_HandOff[1].bRequest := TRUE;
st.sCurrentUID := '';
st.eState := E_StationState.Idle;
E_StationState.Fault:
// 工位故障: 停下, 等待手动恢复
;
END_CASE
END_FUNCTION_BLOCK
8.3 工位 3: 力控组装
FUNCTION_BLOCK FB_Station3_Assembly
VAR_IN_OUT
st : T_Station;
END_VAR
CASE st.eState OF
E_StationState.Idle:
IF g_HandOff[2].bRequest THEN
st.sCurrentUID := g_HandOff[2].sUID;
g_HandOff[2].bRequest := FALSE;
Robot_CallProgram(g_Robot[2], 301); // 取主板+电池
st.dtStartTime := NOW();
st.eState := E_StationState.Processing;
END_IF;
E_StationState.Processing:
// 力控装配: 监控 Z 向插入力
IF g_S3.rForceZ > 25.0 THEN
// 力过大, 暂停机器人, 报警等待
Robot_Pause(g_Robot[2]);
Alarm_Raise(AlarmId.ForceOverload, '组装力过大');
ELSIF g_Robot[2].bReady THEN
st.eState := E_StationState.Done;
END_IF;
E_StationState.Done:
st.dtEndTime := NOW();
st.rCycleTime := DT_DIFF_S(st.dtEndTime, st.dtStartTime);
Trace_RecordStation(st.sCurrentUID, 3, st);
g_HandOff[3].sUID := st.sCurrentUID;
g_HandOff[3].bRequest := TRUE;
st.sCurrentUID := '';
st.eState := E_StationState.Idle;
END_CASE
END_FUNCTION_BLOCK
8.4 MES 对接 (REST + OPC UA 双通道)
FUNCTION_BLOCK FB_MESUpload
VAR
req : HTTP_Request;
rsp : HTTP_Response;
sBody : STRING(1024);
i : INT;
END_VAR
// OPC UA: 由 Runtime 自动发布, 无需代码
// 只需在 IDE 里把 g_Station[*] / g_Robot[*] / g_Production 勾选为 OPC Exposed
// REST: 每件成品上报 (工位 5 完成时触发)
IF g_Station[5].eState = E_StationState.Done AND g_Station[5].bFlagReport THEN
sBody := '{"uid":"' + g_Station[5].sCurrentUID
+ '","workorder":"' + g_Mes.sWorkOrder
+ '","model":"' + g_Mes.sProductModel
+ '","ts":"' + DT_TO_ISO(NOW())
+ '","cycle":' + REAL_TO_STR(g_Station[5].rCycleTime)
+ ',"status":"' + BOOL_TO_STR(g_Trace.bFinalOK, 'OK', 'NG')
+ '"}';
req.Url := g_Mes.sBaseUrl + '/api/production/report';
req.Method := 'POST';
req.Body := sBody;
req.Header['Content-Type'] := 'application/json';
req.Header['Authorization'] := 'Bearer ' + g_Mes.sToken;
req.TimeoutMs := 1500;
HTTP_Post_Async(req, rsp); // 不阻塞主周期
IF rsp.bDone THEN
IF rsp.StatusCode = 200 THEN
g_Mes.nProducedQty := g_Mes.nProducedQty + 1;
g_Mes.dtLastSync := NOW();
g_Station[5].bFlagReport := FALSE;
ELSE
g_Mes.nFailCount := g_Mes.nFailCount + 1;
// 失败缓存本地
MES_BufferToLocal(sBody);
Alarm_Raise(AlarmId.MES_Fail, 'MES 上报失败 code=' + INT_TO_STR(rsp.StatusCode));
END_IF;
END_IF;
END_IF;
// 断网恢复: 扫描本地缓存, 批量补传
IF g_Mes.bOnline AND g_Mes.LocalBuffer[1].bValid THEN
FOR i := 1 TO 16 DO
IF g_Mes.LocalBuffer[i].bValid THEN
MES_Resend(g_Mes.LocalBuffer[i]);
END_IF;
END_FOR;
END_IF;
END_FUNCTION_BLOCK
8.5 机器人程序 (埃斯顿 ER6 取料)
PROGRAM Robot1_P101
VAR
pHome : E6POS := (A1:=0, A2:=-30, A3:=60, A4:=0, A5:=90, A6:=0);
pPick : E6POS := (A1:=45, A2:=-20, A3:=80, A4:=0, A5:=70, A6:=45);
pDrop : E6POS := (A1:=-30, A2:=-10, A3:=50, A4:=0, A5:=60, A6:=-30);
pApproach : E6POS;
END_VAR
pApproach := pPick;
pApproach.Z := pApproach.Z + 30; // 上方 30mm
MOVJ(pHome, 50);
WAIT_READY();
MOVL(pApproach, 800);
GripperOpen();
MOVL(pPick, 200);
GripperClose();
WAIT(80);
MOVL(pApproach, 200);
MOVL(pDrop, 800);
GripperOpen();
WAIT(50);
MOVJ(pHome, 80);
SetOutput(DO_Robot1_Done, TRUE);
END_PROGRAM
Darra 机器人对象屏蔽品牌差异, 上面代码在埃斯顿 / 法奥 / 埃夫特都能跑, 换机器人只换驱动映射。
九、运行与调试
9.1 首次上电顺序
- 柜内 24V 合闸, 检查 UPS 指示灯绿色
- 工控机开机, 等待 Darra Runtime 自启
- 打开 IDE, 下载工程 →
BuildAll→Deploy - 远程 IO 上电, 确认 EtherCAT 链路全部 OP 状态
- 伺服使能, 手动模式单轴点动测试
- 机器人单独上电, 回零, 示教关键点 (pHome / pPick / pDrop)
- 单工位手动测试 → 全线手动联动 → 单件自动 → 连续自动
9.2 调试工具
| 工具 | 作用 |
|---|---|
| Darra IDE 变量监视 | 实时监控 UDT 所有字段 |
| OB1 时序分析 | 查看每个 FB 的 CPU 用时, 找到热点 |
| EtherCAT 诊断 | 每个从站的错误计数 / WKC / DC 偏差 |
| HMI 录像回放 | 故障时回放最近 30 分钟的变量曲线 |
| DarraCloud 远程 | 异地工程师查看实时数据 |
| 日志文件 | %AppData%/DarraRuntime/logs/*.log |
9.3 常见问题处理
| 现象 | 检查 | 处理 |
|---|---|---|
| EtherCAT 周期抖动 > 10μs | 核隔离是否启用 | 检查 Darra_Runtime.ini 的 IsolatedCore=1 |
| 工位 3 力控报警频繁 | Z 向零点偏移 | 重新校零, 检查 S3.rForceZ 基线 |
| MES 上报失败 | 网络 + Token | curl -X POST ... -H "Authorization: ..." 独立验证 |
| 视觉结果延迟 > 500ms | GPU 负载 | 降低推理精度 FP16, 或换 FP32 Batch 1 |
| 扫码读不到 | 光照 / 角度 | 调整光源或重贴码 |
| 机器人示教漂移 | 机械松动 | 重新 TCP 标定 |
9.4 性能调优检查表
- EtherCAT 报文延迟 < 80μs
- OB1 总用时 < 600μs (余量 > 400μs)
- OB10 MES 调用平均 < 50ms
- 视觉端到端 < 300ms
- 机器人路径无空走 > 2s
- 传送带速度与下游节拍匹配 (不顶料 / 不空等)
十、Darra 功能对照表
| 项目需求 | Darra 功能 | 模块 |
|---|---|---|
| EtherCAT 1ms 主站 | Darra EtherCAT Master | Runtime 内置 |
| 5 工位并发状态机 | Darra PLC Runtime 多任务 | OB / FB |
| 3 机器人协同 | Darra 机器人对象 + Robot_MoveSync | 内置 |
| 六轴插补 | Darra MC_MoveLinearAbs | MC 库 |
| 力控装配 | Darra ForceControl FB | 协作机器人对接 |
| 本地 HMI | Darra HMI 设计器 + 终端运行时 | IDE |
| 车间大屏 | Darra Web HMI / 大屏模式 | Runtime |
| 视觉 TCP 对接 | Darra TcpServer + JSON 解析 | 内置 |
| 视觉 Python 推理 | Darra Python FFI | AI 插件 |
| OPC UA Server | Darra 内置 OPC UA | Runtime |
| REST 上报 | Darra HTTP Client 对象 | 内置 |
| 追溯入库 | Darra PostgreSQL / SQLite 对象 | 数据库插件 |
| 配方管理 | Darra Recipe 对象 | IDE |
| 工单接收 / 执行回报 | Darra REST/OPC UA 对接 (工单由上层 MES 下发) | 内置 |
| 报警分级推送 | Darra AlarmMgr + WebHook 企业微信 | 内置 |
| 云端备份 | DarraCloud | 云服务 |
| 远程运维 | DarraCloud 反向隧道 | 云服务 |
| 多工位变量同步 | DarraSync | 内置 |
| 本地多进程 | DarraIPC | 内置 |
| AI 辅助 SCL | DarraAI (中文 NL → SCL) | IDE 插件 |
| 断电恢复 | Darra Retain 变量 + 持久化 | Runtime |
十一、项目总结
11.1 交付结果
- 6 条产线全部投产, 单条节拍 13.5 秒 (原 20 秒)
- 日产 2,500 件/线 (原 1,800 件)
- 综合良率 99.2% (原 95.8%)
- 人力 3 人/线 (原 15 人/线)
- 单线 ROI 18 个月
11.2 产品价值体现
- 硬件国产化: 工控机 / IO / 伺服 / 机器人 / 交换机 100% 国产, 供应链安全
- 软件统一: 一份 Darra 工程文件涵盖 PLC + 机器人 + HMI + 数据库, 并统一对接上层 MES
- 集成提速: 1 名工程师 45 天完工, 原本需要 3 工种 6 个月
- 维护简单: 维护团队只需要熟悉 Darra IDE, 不再需要同时掌握编程 / 组态 / 协议网关等多套工具
- 迭代灵活: 新增工位 1 天完成, 在同一工程里加一个
T_Station实例 + 机器人对象即可
11.3 关键经验
- 国产伺服 (汇川 SV660N) 跑 EtherCAT 1ms 稳定性完全可用
- 机器人对象抽象让"品牌不重要", 客户按预算混搭三家机器人
- DarraCloud 让异地 7×24 支持成为可能, 外地工程师不用频繁出差
- OPC UA + REST 双通道, 主机厂 MES / ERP 都能兼容
- 追溯 UID 贯穿工位 1 到工位 5, 每个 FB 都写
Trace_RecordStation, 结构统一
11.4 下一步扩展
- 增加 工位 6 在线老化, 对贴标后的成品做 15 分钟通电老化测试
- 接入 工厂能耗管理系统, 每工位电表上传, 实现 kWh/件 指标
- 大屏增加 AI 产能预测, 基于历史数据预测明日产能 / 报工
- 接入 工艺 SPC 分析, CNC 主轴电流曲线做统计过程控制