跳到主要内容

超高速智能分拣机

硬件配置

  • 主站: Windows 10 IoT × 1 + Intel 13600K × 1 + RTX4060 × 1
  • 耦合器: EK1100 耦合器 × 1 + EL5001 高速计数器 × 1 + EL1008 数字量输入 × 1
  • 输出模块: 定制英飞凌XMC4800 EtherCAT从站 128数字量输出 × 1 (电磁阀阀组)
  • 传送带: 变频器 × 1 + 编码器 × 1
  • 识别系统: 海康 MV-CL042-91GC 线阵相机 × 2 + RTX4060 推理

成本分析

类别型号/规格参考单价 (¥)数量小计 (¥)
耦合器EK11008001800
高速计数器EL50011,20011,200
数字量输入EL10083501350
输出模块定制 XMC4800 128路IO输出1,00011,000
变频器1,50011,500
编码器1001100
线阵相机海康 MV-CL042-91GC2,20024,400
GPURTX40602,50012,500
工控机Intel 13600K 级别4,00014,000
整线参考总计≈ ¥15,850

以上为核心部件参考价 (RMB),不含电磁阀阀组、线缆、机架等。

性能指标

  • 输送速度: 5m/秒
  • 识别准确率: ≥99.5%
  • 响应延迟: ≤50µs (驱动层实现,EK1100系统极限)

应用场景

农产品/再生资源/矿物智能分拣线。 5m/s 传送带配合 128 路电磁阀喷嘴,相机回传图像触发 AI 识别后提交吹气任务,IO 控制驱动 ≤50µs 精确触发喷射,远低于常规PLC/MCU 250µs精度,单喷嘴覆盖约 1cm² 分拣点。相机回调(应用层)与 IO 时序控制(驱动层)分层解耦。

代码说明

系统架构

关键设计:

主程序从 EtherCAT 驱动获取 PDO 缓冲区地址后,直接传给 IO 控制驱动。IO 控制驱动直接读写 PDO 内存,EtherCAT 驱动每周期自动收发,无需中间拷贝。

关键时序逻辑:

  1. PDO 缓冲区直接共享 — 主程序将编码器输入 PDO 地址和 128 路输出 PDO 地址传给 IO 控制驱动,两个驱动共享同一块内存
  2. 触发位置计算 — 相机回传图像后, AI 识别, 检测时编码器 + 相机到喷嘴距离 = 触发编码器值
  3. 位置比对触发 — IO 控制驱动直接读 PDO 编码器, ≥ 触发位置 时直接写 PDO 输出
  4. 脉冲自动关闭 — 每通道记录关闭时刻, IO 控制驱动自动复位
AI 视觉模型

本案例中的 AI 识别模型(目标检测、材质分类等)及线阵相机标定、图像拼接算法为附加服务,不包含在 EtherCAT 主站软件授权中。我们可根据实际分拣场景提供定制化 AI 模型训练与部署方案。

驱动层定制服务

驱动层高精度 IO 控制、XMC4800 定制 128 路 IO 输出模块等硬件与底层时序逻辑为定制服务。我们是专业的工业自动化技术公司,拥有多家行业专用设备制造商合作者。除软件授权外,同样提供整线方案设计、硬件选型、设备采购及技术支持等一站式服务,欢迎咨询合作。

代码示例

主程序

using System;
using System.Threading;
using Darra.EtherCAT;

/// <summary>
/// 主程序 — 启动 EtherCAT 驱动, 获取 PDO 缓冲区地址, 传给 IO 控制驱动
/// </summary>
class SortingMain
{
static unsafe void Main(string[] args)
{
// 1. 启动 EtherCAT 驱动
var master = new DarraEtherCATMaster();
master.Start("\\Device\\NPF_{网卡GUID}");

// 2. 获取 PDO 缓冲区地址 — 两个驱动直接共享, 无需中间拷贝
// encoderPtr: EL5001 高速计数器输入 PDO (EtherCAT 驱动写入, IO 控制读取)
// outputPtr: XMC4800 128路输出 PDO (IO 控制写入, EtherCAT 驱动自动发送)
int* encoderPtr = (int*)master.GetInputPdoPtr(slaveIndex: 1, offset: 0);
byte* outputPtr = (byte*)master.GetOutputPdoPtr(slaveIndex: 2, offset: 0);

// 3. 启动 IO 控制驱动
var ioCtrl = new SortingIOController(encoderPtr, outputPtr);
var ioThread = new Thread(ioCtrl.Run) { IsBackground = true, Priority = ThreadPriority.Highest };
ioThread.Start();

// 4. 注册相机回调 — 相机回传图像时触发, AI 识别, 计算吹气位置, 提交任务
// camera.OnImageReceived += (image) =>
// {
// var targets = aiModel.Detect(image);
// int encoder = *encoderPtr;
// foreach (var t in targets)
// {
// int startChannel = t.PixelStart * 128 / cameraPixelCount;
// int channelCount = Math.Max(1, t.PixelWidth * 128 / cameraPixelCount);
// int triggerEncoder = encoder + cameraToNozzle;
// ioCtrl.Submit(triggerEncoder, startChannel, channelCount);
// }
// };

Console.WriteLine("分拣系统启动, 按 Enter 退出");
Console.ReadLine();
}
}

分拣任务结构

/// <summary>
/// 分拣任务 — 由视觉系统提交, IO 控制驱动消费
/// </summary>
public struct SortingTask
{
public int TriggerEncoder; // 吹气位置 (编码器绝对值, 到达时触发)
public int StartChannel; // 起始通道 (由像素起点映射, 0-127)
public int ChannelCount; // 通道宽度 (由像素宽度映射)
}

相机回调入队示例:

// 相机回传图像事件 → AI 识别 → 计算吹气位置 → 提交到 IO 控制驱动
// IO 控制驱动直接读 PDO 编码器, 到达时直接写 PDO 输出

camera.OnImageReceived += (image) =>
{
var targets = aiModel.Detect(image); // AI 批量识别
int encoder = *encoderPtr; // 直接读 PDO 编码器

foreach (var t in targets)
{
// 像素 → 通道映射 (128 通道覆盖相机视野)
int startChannel = t.PixelStart * 128 / cameraPixelCount;
int channelCount = Math.Max(1, t.PixelWidth * 128 / cameraPixelCount);

// 吹气位置 = 检测时编码器 + 相机到喷嘴距离 (编码器脉冲)
int triggerEncoder = encoder + cameraToNozzle;

ioCtrl.Submit(triggerEncoder, startChannel, channelCount);
}
};