初始化
强烈建议使用 Darra 配置工具导出的 DENI 文件进行初始化。
DENI 文件包含完整的网络配置(网口、从站、PDO 映射、DC 设置等),可确保配置的一致性和正确性。
使用 DENI 文件管理设备硬件设施将获得更好的兼容性与通用性。
构造函数
DarraEtherCAT()
public DarraEtherCAT()
无参构造函数,流式 API 入口。必须通过 SetENI() 或 SetNetwork() 设置配置,然后调用 Build() 初始化。
示例:
var master = new DarraEtherCAT()
.SetENI(@"C:\EtherCAT\MyProject.xml")
.Build();
if (master == null)
{
Console.WriteLine("初始化失败");
return;
}
master.State = EcState.OP;
流式配置
SetENI(string eniPath)
public DarraEtherCAT SetENI(string eniPath)
加载 DENI/ENI 配置文件(延迟配置,Build 时生效)。
参数:
eniPath(string) — DENI 或 ENI 配置文件路径
示例:
var master = new DarraEtherCAT()
.SetENI(@"C:\EtherCAT\MyProject.xml");
SetNetwork(NetworkInfo primary, NetworkInfo? redundant = null)
public DarraEtherCAT SetNetwork(NetworkInfo primary, NetworkInfo? redundant = null)
通过网口信息对象设置主网口和可选的冗余网口(延迟配置,Build 时生效)。
参数:
primary(NetworkInfo) — 主网口信息redundant(NetworkInfo?) — 冗余网口信息(可选)
SetNetwork(string primaryName, string? redundantName = null)
public DarraEtherCAT SetNetwork(string primaryName, string? redundantName = null)
通过网口名称设置主网口和可选的冗余网口(延迟配置,Build 时解析)。
参数:
primaryName(string) — 主网口名称或描述redundantName(string?) — 冗余网口名称或描述(可选)
示例:
var master = new DarraEtherCAT()
.SetNetwork("以太网 1");
SetEsiFile(string filePath)
public DarraEtherCAT SetEsiFile(string filePath)
加载单个 ESI 文件(延迟配置,Build 时生效)。可多次调用。
如果使用 DENI 文件,通常不需要单独加载 ESI。
SetEsiFiles(string path)
public DarraEtherCAT SetEsiFiles(string path)
加载 ESI 文件目录(延迟配置,Build 时生效)。可多次调用。
EnableAutoStartup()
public DarraEtherCAT EnableAutoStartup()
标记需要自动配置从站(Build 时执行)。
如果使用 ENI/DENI 文件,通常不需要调用此方法。已有启动参数的从站会被完整跳过,不会被覆盖或补充。此方法仅对未配置的从站生效(自动从 ESI/MDP/SM 生成 PDO/DC/启动参数)。
链式调用覆盖规则
SetENI 和 SetNetwork 都可以设置网口。当两者同时使用时,后调用的方法覆盖前面的冲突配置:
// SetENI 在后 → 使用 ENI 文件中的网口配置
var master = new DarraEtherCAT()
.SetNetwork("以太网 1")
.SetENI(@"C:\config.xml") // ← ENI 中的网口覆盖 SetNetwork
.Build();
// SetNetwork 在后 → SetNetwork 的网口覆盖 ENI
var master = new DarraEtherCAT()
.SetENI(@"C:\config.xml")
.SetNetwork("以太网 1") // ← 覆盖 ENI 中的网口
.Build();
ENI/DENI 文件中的从站配置、PDO 映射、DC 设置等始终保留,仅网口配置受覆盖规则影响。
EnableAutoStartup() 仅对未配置的从站生效,ENI/DENI 已配置的从站会被完整跳过。
Build
Build()
public BuildResult Build()
构建并初始化主站(终结方法)。BuildResult 支持隐式转换为 DarraEtherCAT?(成功为实例,失败为 null),也支持元组解构 (success, message)。失败时实例已自动释放。
建议用法 — 直接链式调用,用 null 判断是否成功:
var master = new DarraEtherCAT()
.SetENI(@"C:\EtherCAT\config.xml")
.Build();
if (master == null) return; // 初始化失败
master.State = EcState.OP;
扩展用法 — 需要获取详细错误消息时,使用元组解构:
var master = new DarraEtherCAT()
.SetENI(@"C:\EtherCAT\config.xml");
var (success, message) = master.Build();
if (!success)
{
Console.WriteLine($"初始化失败: {message}");
return;
}
Console.WriteLine(message); // "主站初始化成功,扫描到 N 个从站"
资源释放
Close()
public void Close()
关闭并清空内存,停止主站和数据采集线程。
Dispose()
public void Dispose()
释放主站资源,关闭网络连接。实现 IDisposable 接口。
网络扫描
DarraEtherCAT.GetNetworkInfo(bool IsRedundant = false, bool NeedSlavesNum = false)
public static List<NetworkInfo> GetNetworkInfo(bool IsRedundant = false, bool NeedSlavesNum = false)
获取系统中可用的网络适配器列表。
参数:
IsRedundant(bool) — 是否筛选冗余网络适配器,默认falseNeedSlavesNum(bool) — 是否检测每个网卡上的从站数量(需扫描,较慢),默认false
返回值:
List<NetworkInfo>— 网络适配器信息列表
相关结构:
public class NetworkInfo
{
public string Name { get; } // 适配器系统名称(用于 SetNetwork)
public string Desc { get; } // 适配器描述(用户可读)
public int? SlaveNum { get; } // 从站数量(需 NeedSlavesNum=true)
public int? RedundantSlaveNum { get; } // 受冗余保护的从站数量
}
示例:
var adapters = DarraEtherCAT.GetNetworkInfo(NeedSlavesNum: true);
foreach (var adapter in adapters)
{
Console.WriteLine($"{adapter.Desc}: {adapter.SlaveNum ?? 0} 个从站");
}
DarraEtherCAT.QuickSlaveCount(string adapterName)
public static int QuickSlaveCount(string adapterName)
快速从站计数(不读取 EEPROM,仅使用广播读取)。比 ScanSlaves() 更快,适合快速检测从站数量。
参数:
adapterName(string) — 网络适配器名称
返回值:
int— 检测到的从站数量
DarraEtherCAT.QuickSlaveCountRedundant(string primaryAdapter, string secondaryAdapter)
public static int QuickSlaveCountRedundant(string primaryAdapter, string secondaryAdapter)
冗余模式快速从站计数(不读取 EEPROM,仅使用广播读取)。
参数:
primaryAdapter(string) — 主网络适配器名称secondaryAdapter(string) — 冗余网络适配器名称
返回值:
int— 检测到的从站数量
DarraEtherCAT.GetRingSlaveCount()
public static int GetRingSlaveCount()
获取上一次冗余扫描中环形路径上的从站数。
返回值:
int— 环形路径上的从站数量
DarraEtherCAT.ScanSlaves(string adapterName, string? secondaryAdapter = null)
public static List<ScannedSlaveInfo> ScanSlaves(string adapterName, string? secondaryAdapter = null)
一键扫描从站并返回详细信息列表。传入 secondaryAdapter 时自动使用冗余模式扫描。
参数:
adapterName(string) — 主网络适配器名称secondaryAdapter(string?) — 冗余网络适配器名称(可选,用于环形拓扑)
返回值:
List<ScannedSlaveInfo>— 从站详细信息列表
相关结构:
public class ScannedSlaveInfo
{
// 基本标识
public int Index { get; } // 从站索引(1-based)
public string Name { get; } // 设备名称
public uint VendorID { get; } // 厂商 ID
public uint ProductCode { get; } // 产品代码
public uint RevisionNumber { get; } // 修订版本号
public uint SerialNumber { get; } // 序列号
// 地址
public ushort ConfigAddr { get; } // 配置地址
public ushort AliasAddr { get; } // 别名地址
// 拓扑信息
public ushort ParentIndex { get; } // 父从站索引(0=主站是父节点)
public byte Topology { get; } // 拓扑类型 (0~4)
public byte ActivePorts { get; } // 活动端口位图
public byte EntryPort { get; } // 入口端口
public byte ParentPort { get; } // 父从站上的端口号
public byte PhysicalType { get; } // 物理端口类型
// 计算属性
public bool IsCoupler { get; } // 是否为耦合器
public string DeviceType { get; } // "Coupler"/"Terminal"/"Box"/"Extension"/"Device"
public int Depth { get; } // 拓扑深度
// 格式化显示
public string VendorIDHex { get; } // "0x..."
public string ProductCodeHex { get; } // "0x..."
}
示例:
var slaves = DarraEtherCAT.ScanSlaves(@"\Device\NPF_{...}");
foreach (var s in slaves)
{
var indent = new string(' ', s.Depth * 2);
Console.WriteLine($"{indent}[{s.Index}] {s.Name} ({s.DeviceType})");
}
其他
DarraEtherCAT.GetSerialNumber()
public static string GetSerialNumber()
获取当前设备的序列号(用于授权验证)。
返回值:
string— 设备序列号,获取失败时返回空字符串
完整示例
使用 DENI 文件(推荐)
var master = new DarraEtherCAT()
.SetENI(@"C:\EtherCAT\MyProject.xml")
.Build();
if (master == null) return;
var (ok, stateMsg) = master.SetState(EcState.OP);
Console.WriteLine(ok ? "运行中" : $"失败: {stateMsg}");
动态扫描网口
var adapters = DarraEtherCAT.GetNetworkInfo(NeedSlavesNum: true);
var target = adapters.FirstOrDefault(a => a.SlaveNum > 0);
if (target == null) return;
var master = new DarraEtherCAT()
.SetNetwork(target)
.SetEsiFiles(@"C:\ESI")
.EnableAutoStartup()
.Build();
if (master == null) return;
冗余模式
var adapters = DarraEtherCAT.GetNetworkInfo(IsRedundant: true, NeedSlavesNum: true);
var master = new DarraEtherCAT()
.SetNetwork(adapters[0], adapters[1])
.SetENI(@"C:\config.xml")
.Build();
if (master == null) return;
多实例(多网卡独立总线)
每个主站实例管理一条独立的 EtherCAT 总线,使用不同的网卡。创建新实例无需重启,即时生效。
- 每个实例必须使用不同的网卡 — 同一网卡不能被多个实例同时使用,SDK 会自动检测并阻止重复绑定
- CPU 核心自动分配 — 每个实例自动占用不同的 CPU 核心,无需手动设置
- Mailbox Gateway 端口自动偏移 — 每个实例自动分配不同的端口号
- 授权与日志共享 — 所有实例共享同一授权状态和日志系统,无冲突
// 获取所有有从站的网卡
var adapters = DarraEtherCAT.GetNetworkInfo(NeedSlavesNum: true)
.Where(a => a.SlaveNum > 0).ToList();
// 实例 1 — 绑定第一张网卡
var master1 = new DarraEtherCAT()
.SetNetwork(adapters[0])
.EnableAutoStartup()
.Build();
// 实例 2 — 绑定第二张网卡(即时生效,无需重启)
var master2 = new DarraEtherCAT()
.SetNetwork(adapters[1])
.EnableAutoStartup()
.Build();
if (master1 != null) master1.State = EcState.OP;
if (master2 != null) master2.State = EcState.OP;
// 各实例独立运行,互不干扰
master1.Events.ProcessDataCyclicAsync += (idx) => { /* 总线 1 的 PDO 处理 */ };
master2.Events.ProcessDataCyclicAsync += (idx) => { /* 总线 2 的 PDO 处理 */ };
// 查询活跃实例数
Console.WriteLine($"活跃主站数: {DarraEtherCAT.ActiveInstanceCount}");
// 释放时自动归还网卡和端口
master2.Close(); // 释放后 adapters[1] 可被新实例使用
多实例资源分配:
- 网卡 — 每个实例使用不同的网卡
- CPU 核心 — 每个实例自动分配不同的专用核心
- Mailbox 端口 — 每个实例自动分配递增的端口号
- 工作线程 — 各实例独立