跳到主要内容

主站对象字典 (Master OD)

符合 ETG.1510 标准的主站对象字典,提供主站身份信息、从站配置/状态/诊断数据,供外部诊断工具和 HMI 通过标准 SDO 接口访问。

通过 master.MasterOD() 访问。​

ETG.1510 标准

主站对象字典按照 ETG.1510 规范实现,使用标准 CoE 索引约定。与从站 CoE 对象字典不同,这里是主站自身暴露的诊断对象。配合邮箱网关使用,可实现远程诊断工具对主站的标准访问。

对象索引总览​

类别索引名称子索引数读写说明
身份0x1000Device Type0只读0x00001389(EtherCAT Master)
身份0x1008Device Name0只读"Darra EtherCAT Master"
身份0x1009Hardware Version0只读"1.0"
身份0x100ASoftware Version0只读SDK 版本号
身份0x1018Identity Object4只读主站身份信息(见下方子索引表)
配置0x8nnnConfiguration Data5只读第 n 个从站的身份数据(厂商、产品、修订、序列号、组号)
检测0x9nnnInformation Data3只读第 n 个从站的运行信息(状态、AL Status Code、链路质量)
诊断0xAnnnDiagnosis Data19只读第 n 个从站的诊断数据(AL Status、错误计数等;仅部分子索引有真值源)
检测0xF002Detect Modules从站数量只读从站数量与各从站的 VendorId + ProductCode(禁止外部写入)
诊断0xF120Master Diag Data3只读主站诊断数据(从站数量、期望 WKC、链路状态)
控制0xF200Diag Interface Control1读写诊断接口控制(诊断采样开关)
备注

nnn = 从站编号(1-based),索引根据 master.SlaveCount() 动态生成。例如 3 个从站时,0x8001 ~ 0x8003、0x9001 ~ 0x9003、0xA001 ~ 0xA003 均可访问。

0x1018 — 主站身份 (Identity Object)​

子索引名称类型值说明
0Number of Entriesbyte4固定
1Vendor IDint0x00001164ETG 分配,固定值
2Product Codeint0x00000001固定值
3Revision Numberint0x00000001固定常量(实现内写死,不随 DLL 版本变化)
4Serial Numberint0固定返回 0

0x8nnn — 从站配置数据​

每个从站对应一个 0x8nnn 对象(nnn = 从站编号),包含从站身份数据。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 5
1Vendor IDint只读厂商 ID(GetSlaveIdentity()[0])
2Product Codeint只读产品代码(GetSlaveIdentity()[1])
3Revision Numberint只读修订号(GetSlaveIdentity()[2])
4Serial Numberint只读序列号(GetSlaveIdentity()[3])
5Groupbyte只读从站所属组号(单字节)

0x9nnn — 从站检测信息​

每个从站对应一个 0x9nnn 对象,包含运行时检测到的实际信息。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 3
1Statebyte只读当前 EtherCAT 状态(EcState 数值)
2AL Status Codeshort只读当前 AL 状态码(slave.ErrorCode().value,枚举见 EtherCATTypes.EcALState)
3Link Qualityshort只读链路质量;DLL 未暴露,恒返回 0xFFFF(未知)

0xAnnn — 从站诊断数据​

每个从站对应一个 0xAnnn 对象,包含实时诊断数据。每次读取时自动更新。

子索引名称类型读写说明
0Number of Entriesbyte只读固定 19
1AL Statusshort只读当前 AL 状态
2AL Controlshort不可用读取返回 null;写入恒返回 false(本实现没有 0xAnnn 写处理器)
3Last AL Status Codeshort只读最近一次 AL 错误码(ESC 0x0134)
4Link Conn. Statusbyte不可用端口链路连接状态(当前无真值源,读取返回 null)
5Link Controlbyte不可用链路控制(当前无真值源,读取返回 null)
6Fixed Addr Conn. Port 0short不可用Port 0 连接的从站配置地址(当前无真值源,读取返回 null)
7Fixed Addr Conn. Port 1short不可用Port 1 连接的从站配置地址(当前无真值源,读取返回 null)
8Fixed Addr Conn. Port 2short不可用Port 2 连接的从站配置地址(当前无真值源,读取返回 null)
9Fixed Addr Conn. Port 3short不可用Port 3 连接的从站配置地址(当前无真值源,读取返回 null)
10Frame Error Port 0int不可用Port 0 帧错误计数(当前无真值源,读取返回 null)
11Frame Error Port 1int不可用Port 1 帧错误计数(当前无真值源,读取返回 null)
12Frame Error Port 2int不可用Port 2 帧错误计数(当前无真值源,读取返回 null)
13Frame Error Port 3int不可用Port 3 帧错误计数(当前无真值源,读取返回 null)
14Cyclic WC Error Counterint只读周期性工作计数器错误
15Slave Not Present Counterint只读从站不在线计数
16Abnormal State Change Counterint只读异常状态变化计数
17Disable Auto Link Controlbyte不可用自动链路控制禁用标志(当前无真值源,读取返回 null)
18Last CoE/SoE Protocol Errorint只读最近一次 CoE/SoE 协议错误码
19New Diag Messagesbyte不可用是否有新诊断消息(当前无真值源,读取返回 null)
0xAnnn 只有部分子索引有真值源

0xAnnn 上当前可读的只有 :1(AL Status)、:3(Last AL Status Code)、:14/:15/:16(底层未维护这三项计数,恒为 0)、:18(Last CoE/SoE Protocol Error)。其余子索引(:2、:4-:13、:17、:19)读取一律返回 null,不会拿别的字段冒充;writeObject 对 0xAnnn 恒返回 false。

0xF002 — 扫描命令​

安全保护

0xF002 禁止外部写入(writeObject 恒返回 false)。运行中执行扫描可能导致配置丢失和设备异常,因此该对象为只读。 从站扫描仅在主站初始化阶段由内部逻辑执行。 更多功能请等待未来更新。

子索引名称类型读写说明
0Slave Countbyte只读检测到的从站数量
1..NVendor ID + Product Codebyte[8]只读从站 n 的厂商 ID(前 4 字节)+ 产品代码(后 4 字节),小端

0xF120 — 主站诊断数据​

子索引名称类型读写说明
0Number of Entriesbyte只读固定 3
1Slave Countshort只读从站数量
2Expected WKCshort只读期望工作计数器
3Link Statusbyte只读链路状态(EcLinkState 数值)
本腿 0xF120 的字段口径

本腿 0xF120 子索引给的是从站数量、期望 WKC 与链路状态;ETG.1510 的周期性/非周期性丢帧计数(内核 5 秒滑动窗口值,不是百分比)、每秒周期/非周期帧数与主站状态请用 master.GetMasterDiagData()(见主站 API)。

0xF200 — 诊断接口控制​

子索引名称类型读写说明
0Number of Entriesbyte只读固定 1
1Diagnostics Enabledbyte读写读=当前诊断采样开关;写 0/非 0 关闭/开启

方法​

readObject(int index, byte subindex)​

public byte[] readObject(int index, byte subindex)

读取主站对象字典中指定索引的数据。

参数:

  • index (int) — 对象索引(如 0x1018、0x8001、0xA001)
  • subindex (byte) — 子索引

返回值:

  • byte[] — 读取的原始数据,未知对象返回 null

示例:

byte[] vid = master.MasterOD().readObject(0x8001, (byte) 1);  // 0x8001:1 = VendorId (4 字节)
int vendorId = ByteBuffer.wrap(vid).order(ByteOrder.LITTLE_ENDIAN).getInt();

writeObject(int index, byte subindex, byte[] data)​

public boolean writeObject(int index, byte subindex, byte[] data)

写入主站对象字典。仅部分对象支持写入(见上方各对象表格的读写列)。

参数:

  • index (int) — 对象索引
  • subindex (byte) — 子索引
  • data (byte[]) — 要写入的数据

返回值:

  • boolean — 写入成功返回 true

getObjectName(int index)​

public String getObjectName(int index)

获取对象的名称。

参数:

  • index (int) — 对象索引

返回值:

  • String — 对象名称,未知索引返回 null

getSubindexCount(int index)​

public byte getSubindexCount(int index)

获取对象的子索引数量。

只解析已注册的固定索引

0x8nnn / 0x9nnn / 0xAnnn 前缀在这里不做解析,像 getSubindexCount(0x8001) 这类调用一律返回 0;这几个前缀的子索引数量请直接看上表(0x8nnn = 5、0x9nnn = 3、0xAnnn = 19、0xF002 随从站数量变化)。

参数:

  • index (int) — 对象索引

返回值:

  • byte — 子索引数量;未注册的索引返回 0

getSupportedObjectIndices()​

public List<Integer> getSupportedObjectIndices()

获取当前支持的所有对象索引列表(固定索引 + 按从站数量动态生成的 0x8nnn/0x9nnn/0xAnnn)。

返回值:

  • List<Integer> — 支持的索引列表

快捷方法​

MasterObjectDictionary 同时提供 ETG.1510 常用诊断字段的读取接口(内部等同于读 0xAnnn 的对应子索引):

Integer alExt    = od.ALStatusExtended(1);          // 扩展 AL 状态码(无真值源时为 null)
int alLast = od.LastALStatusCode(1); // 最近 AL 错误码
long protoErr = od.LastCoESoEProtocolError(1); // 最近 CoE/SoE 协议错误码
Long wkcErr = od.CyclicWCErrorCounter(1); // WKC 错误计数(无真值源时为 null)
Boolean hasNew = od.NewDiagMessagesAvailable(1); // 是否有新诊断消息(无真值源时为 null)
Boolean autoOff = od.DisableAutomaticLinkControl(1); // 自动链路控制禁用标志(无真值源时为 null)

完整示例​

MasterObjectDictionary od = master.MasterOD();

// 遍历所有从站的诊断数据
for (int i = 1; i <= master.SlaveCount(); i++) {
int cfgIdx = 0x8000 | i;
int diagIdx = 0xA000 | i;

// 0x8nnn 只提供身份数据(不含名称字段),名称请用从站对象
String name = master.getSlave(i).Name();

// 身份数据 (0x8nnn:1 = VendorId)
byte[] vid = od.readObject(cfgIdx, (byte) 1);
int vendorId = vid != null ? ByteBuffer.wrap(vid).order(ByteOrder.LITTLE_ENDIAN).getInt() : 0;

// 读取 AL Status 和错误码
byte[] alStatus = od.readObject(diagIdx, (byte) 1);
byte[] alCode = od.readObject(diagIdx, (byte) 3);

int alVal = (alStatus != null && alStatus.length >= 2)
? ByteBuffer.wrap(alStatus).order(ByteOrder.LITTLE_ENDIAN).getShort() & 0xFFFF : 0;
int codeVal = (alCode != null && alCode.length >= 2)
? ByteBuffer.wrap(alCode).order(ByteOrder.LITTLE_ENDIAN).getShort() & 0xFFFF : 0;

System.out.printf("从站%d [%s]: Vendor=0x%08X, AL=0x%04X, Code=0x%04X%n",
i, name, vendorId, alVal, codeVal);
}

// 端口帧错误计数 (0xAnnn:10-13) 当前无真值源: readObject 返回 null

// 诊断开关 (0xF200:1, 0=关闭 / 非 0=开启)
od.writeObject(0xF200, (byte) 1, new byte[] { 1 });

// 复位诊断计数器不在主站对象字典内, 用主站 API:
master.resetDiagnostics();

// 列出所有支持的对象
List<Integer> indices = od.getSupportedObjectIndices();
for (int idx : indices) {
String name = od.getObjectName(idx);
System.out.printf("0x%04X: %s%n", idx, name);
}

// ETG.1510 诊断快捷方法
Integer alStatus = od.ALStatusExtended(1);
Long wkcErrors = od.CyclicWCErrorCounter(1);
Boolean hasNewDiag = od.NewDiagMessagesAvailable(1);