跳到主要内容

MDP — 模块化设备

Modular Device Profile (MDP) 是 EtherCAT 中描述模块化设备的标准协议(ETG.5001)。

通过 slave.MDP() 访问。子对象延迟创建,始终返回实例(不会为 null);从站是否支持 MDP 用 slave.HasMDP() 判断。

自动处理

内部会自动处理 MDP 设备的模块检测和 PDO 配置。 绝大多数场景下,用户无需直接操作 MDP。

2.5.x 自动编排

2.5.x 起,主站在进入 OP 时会自动检测并配置模块化设备(GCAN-8200 等)。 启用 enableAutoStartup() 后,SDK 自动读取已检测模块并下发对应启动参数,无需手动操作 MDP。

关于热插拔

SDK 支持 MDP 模块热插拔再配置自修复。 但生产环境中几乎不会出现 MDP 模块热插拔的使用场景。 EtherCAT 从站的模块配置在设备上电后即固定,运行期间不会动态变更。 部署 MDP 模块化设备推荐使用 DENI; 如需自动配置,请先导入对应的 ESI 文件,再调用 enableAutoStartup()

属性

ConfiguredModules()

public List<MDP.MdpSlotInfo> ConfiguredModules()

已配置模块列表(0xF030)。每次调用实时通过 CoE 读取,非可用状态自动切换。

返回值:

  • List<MDP.MdpSlotInfo> — 已配置模块列表

相关结构:

public static class MdpSlotInfo {
public int SlotIndex; // 槽位索引(从 1 开始)
public int ModuleIdent; // 模块标识码(32 位)
public String ModuleName; // 模块名称
public int ModuleType; // 模块设备类型码
public String Status; // 状态("已配置" / "已检测")
public short ObjectDictionaryIndex; // 对象字典基地址
public String ModuleIOType; // I/O 类型(Input / Output / I/O / Unknown)
}
ModuleIOType 判定逻辑

优先从 ESI 文件的模块定义中读取 TxPdo / RxPdo 配置:

  • 仅有 TxPdo → "Input"(从站发送到主站)
  • 仅有 RxPdo → "Output"(主站发送到从站)
  • 两者都有 → "I/O"

ESI 无法判断时回退到模块名称关键字匹配。

示例:

for (MDP.MdpSlotInfo slot : slave.MDP().ConfiguredModules()) {
System.out.printf("Slot %d: %s (0x%08X)%n",
slot.SlotIndex, slot.ModuleName, slot.ModuleIdent);
}

DetectedModules()

public List<MDP.MdpSlotInfo> DetectedModules()

已检测模块列表(0xF050),反映物理上实际插入的模块。每次调用实时通过 CoE 读取。

返回值:

  • List<MDP.MdpSlotInfo> — 已检测模块列表(结构同 ConfiguredModules

示例:

for (MDP.MdpSlotInfo slot : slave.MDP().DetectedModules()) {
System.out.printf("Slot %d: %s%n", slot.SlotIndex, slot.ModuleName);
}

AvailableModules()

public List<MDP.MdpAvailableModule> AvailableModules()

ESI 中声明的可选模块列表。

当前能力边界

"ESI 中声明的可选模块" 需 managed 端解析 ESI <Modules> XML 节点,Java SDK 当前未实装该解析能力,本方法诚实返回空列表(不臆造数据、不抛异常)。 查询已检测模块请用 DetectedModules(),查询已配置模块请用 ConfiguredModules() — 这两者走真实导出的 native 接口。

返回值:

  • List<MDP.MdpAvailableModule> — 可选模块列表(当前恒为空列表)

相关结构:

public static class MdpAvailableModule {
public int ModuleIdent; // 模块标识码
public int ModuleType; // 模块设备类型码
public String ModuleName; // 模块名称
public String Description; // 模块描述
}

方法

ConfigModuleIdents() / DetectedModuleIdents()

public int[] ConfigModuleIdents()
public int[] DetectedModuleIdents()

直读 0xF030(已配置)/ 0xF050(已检测)的 ModuleIdent 原始数组。ConfiguredModules() / DetectedModules() 即基于此组装。

返回值:

  • int[] — 模块标识码数组,无模块或失败返回空数组

CheckModuleMatch()

public int CheckModuleMatch()

校验已配置模块列表(0xF030)与已检测模块列表(0xF050)是否一致。

返回值:

  • int1 表示完全匹配;0 表示不匹配(ETG.5001 AL 0x0035 ModuleIdListMismatch 语义);-1 表示从站不支持 MDP 或读取失败

GetModulePdoLayout()

public List<MDP.MdpModulePdoInfo> GetModulePdoLayout()

获取各模块在从站 IOmap 中的 PDO 布局。通过 CoE SDORead 读取 PDO Assignment (0x1C12/0x1C13) 和 PDO Mapping 条目,累积计算各模块的字节偏移。

备注

需要从站已完成 DENI 配置(ConfigMap 后可用),不依赖 ESI 文件。CoE 不可用或未检测到模块时返回 null

返回值:

  • List<MDP.MdpModulePdoInfo> — 各模块的 PDO 布局信息,无法获取时返回 null

相关结构:

public static class MdpModulePdoInfo {
public int SlotIndex; // 槽位索引
public int InputOffset; // 输入 PDO 偏移(相对于 slave Ioffset)
public short InputSize; // 输入 PDO 字节数
public int OutputOffset; // 输出 PDO 偏移(相对于 slave Ooffset)
public short OutputSize; // 输出 PDO 字节数
}

示例:

List<MDP.MdpModulePdoInfo> layout = slave.MDP().GetModulePdoLayout();
if (layout != null) {
for (MDP.MdpModulePdoInfo mod : layout) {
System.out.printf("Slot %d: In=%dB @%d, Out=%dB @%d%n",
mod.SlotIndex, mod.InputSize, mod.InputOffset,
mod.OutputSize, mod.OutputOffset);
}
}

自动配置

MDP 设备的自动配置需要先导入对应的 ESI 文件,由以下方法完成:

  • 导入 ESI(主站)setEsiFile() / setEsiFiles()
  • 自动编排(主站)enableAutoStartup():进入 OP 时自动检测并配置模块化设备
  • 重新扫描(从站)slave.MDP().Rescan() 重新读取并清缓存
  • 清缓存(从站)slave.MDP().InvalidateStaticCache() 清除 ModuleIndexDistance / MaxModuleCount 缓存

示例:

EtherCATMaster.BuildResult r = EtherCATMaster.create()
.setEsiFiles("C:/EtherCAT/Esi") // 导入 ESI 目录
.enableAutoStartup() // 进 OP 时自动编排 MDP 模块
.setENI("C:/EtherCAT/MyProject.deni")
.build();