跳到主要内容

ENI 配置加载与保存

ENI(EtherCAT Network Information,ETG.2100)是描述整张 EtherCAT 网络的标准 XML:周期、从站列表、PDO 映射、SyncManager、DC 配置等。Darra C++ SDK 在 ethercat.hpp 中提供两个对称函数:

  • LoadENI(...) — 从磁盘加载 ENI XML 解析为 EniConfiguration 结构
  • SaveENI(...) — 把 EniConfiguration 写回 XML 文件

两者由 C++ 端通过 pugixml 直接生成 / 解析,不依赖 DLL 导出,因此即使旧版 Darra.Core.dll 没有 ENI 相关入口也可以使用。

XML 解析依赖

LoadENI / SaveENI 的实现走 pugixml。在包含 SDK 头文件之前需要:

#define ENABLE_ESI_XML
#include <pugixml.hpp>
#include "ethercat.hpp"

未启用 ENABLE_ESI_XML 宏时,LoadENI / SaveENI 不参与编译(避免强制依赖 pugixml)。

数据结构

EniMasterConfig

struct EniMasterConfig {
std::string Name; // 主站名
int CycleTimeUs = 1000; // 主周期 (微秒)
int DcCycleTimeUs = 1000; // DC 周期 (微秒)
int ExpectedSlaveCount = 0; // 期望从站数 (=Slaves.size())
};

EniSlaveConfig

struct EniSlaveConfig {
int PhysicalAddress = 0; // ESC 物理地址
int AutoIncAddress = 0; // 自动递增地址
uint32_t VendorId = 0;
uint32_t ProductCode = 0;
uint32_t RevisionNumber = 0;
std::string Name;
int DcAssignActivate = 0; // DC AssignActivate (0=不使用 DC)

// SM2 输出 / SM3 输入 偏移与长度 (字节)
int Sm2Offset = 0, Sm2Length = 0;
int Sm3Offset = 0, Sm3Length = 0;
};

EniConfiguration

struct EniConfiguration {
EniMasterConfig Master;
std::vector<EniSlaveConfig> Slaves;
std::string Version = "3.0";
};

完整 ENI 配置:主站段 + 从站列表 + 版本号。

LoadENI()

namespace darra::ethercat {

bool LoadENI(const std::string& filePath, EniConfiguration& outConfig);

}

加载 ENI XML 文件并解析为 EniConfiguration

参数:

  • filePath — ENI XML 文件路径(UTF-8)
  • outConfig — 输出配置结构(成功时填充,失败时未定义)

返回值:

  • true — 解析成功
  • false — 文件不存在 / 根节点不匹配 / XML 解析失败

行为说明:

  • 仅识别 <EtherCATConfig> 根(ETG.2100 标准)
  • 旧版 <DarraEtherCATConfiguration> 根(DENI 私有格式)不在本函数处理范围,需要使用 IDE 配置工具导出
  • 数值字段同时支持 0xABCD / #xABCD / #ABCD / 十进制四种写法
  • Master.CycleTimeUs / DcCycleTimeUs 为 0 时自动回退为 1000 (1ms)

示例:

#define ENABLE_ESI_XML
#include <pugixml.hpp>
#include "ethercat.hpp"

darra::ethercat::EniConfiguration cfg;
if (darra::ethercat::LoadENI("C:/EtherCAT/network.eni", cfg)) {
printf("主站: %s, 周期 %d us, %zu 个从站\n",
cfg.Master.Name.c_str(),
cfg.Master.CycleTimeUs,
cfg.Slaves.size());

for (auto& s : cfg.Slaves) {
printf(" [%d] %s VID=0x%08X PID=0x%08X RevID=0x%08X\n",
s.PhysicalAddress, s.Name.c_str(),
s.VendorId, s.ProductCode, s.RevisionNumber);
}
} else {
printf("ENI 加载失败\n");
}

SaveENI()

bool SaveENI(const std::string& filePath, const EniConfiguration& config);

EniConfiguration 写回 ENI XML 文件,与 LoadENI 形成对称(保存的文件可由 LoadENI 重新读回)。

参数:

  • filePath — 输出 ENI 文件路径(UTF-8)
  • config — 已填充的 ENI 配置

返回值:

  • true — 写入成功
  • false — 路径为空或写入失败

生成结构:

<?xml version="1.0" encoding="UTF-8"?>
<EtherCATConfig>
<Config>
<Master>
<Info>
<Name>...</Name>
<Source>DarraEtherCAT C++ SDK SaveENI</Source>
</Info>
<CycleTime>...</CycleTime>
<DcCycleTime>...</DcCycleTime>
</Master>
<Slave> ... </Slave>
<Slave> ... </Slave>
</Config>
</EtherCATConfig>

SaveENI 输出的 XML 还会带 DENI 扩展命名空间 http://www.darra-tech.com/schemas/eni/v3.0,承载 CycleTime / DcCycleTime / ExpectedSlaveCount 等 IDE 扩展信息(LoadENI 解析时识别)。

示例:

darra::ethercat::EniConfiguration cfg;
cfg.Master.Name = "Line-A Master";
cfg.Master.CycleTimeUs = 1000;
cfg.Master.DcCycleTimeUs = 1000;

darra::ethercat::EniSlaveConfig s;
s.PhysicalAddress = 0x03E9;
s.VendorId = 0x00000002;
s.ProductCode = 0x07D81052;
s.RevisionNumber = 0x00120000;
s.Name = "EL2008";
s.Sm2Offset = 0x1000;
s.Sm2Length = 1;
cfg.Slaves.push_back(s);

if (darra::ethercat::SaveENI("C:/EtherCAT/exported.eni", cfg)) {
printf("已写入 ENI\n");
}
ENI vs DENI
格式根节点说明
ENI<EtherCATConfig>ETG.2100 标准, 跨主站通用
DENI<DarraEtherCATConfiguration>Darra IDE 私有, 包含完整配置 + 厂家扩展

LoadENI / SaveENI 处理 ENI;master.SetENI(...) 同时接受两种格式。一般"导出给第三方主站"用 ENI,"自己 Master + IDE 闭环"用 DENI。

完整示例 (导入 → 修改 → 导出)

#define ENABLE_ESI_XML
#include <pugixml.hpp>
#include "ethercat.hpp"

using namespace darra::ethercat;

int main() {
EniConfiguration cfg;
if (!LoadENI("C:/EtherCAT/source.eni", cfg)) {
printf("加载失败\n");
return -1;
}

// 调整主周期
cfg.Master.CycleTimeUs = 500; // 500us
cfg.Master.DcCycleTimeUs = 500;

// 给所有从站统一启用 DC SYNC0
for (auto& s : cfg.Slaves) {
if (s.DcAssignActivate == 0) s.DcAssignActivate = 0x0300; // SYNC0+SYNC1
}

if (!SaveENI("C:/EtherCAT/tuned.eni", cfg)) {
printf("保存失败\n");
return -1;
}

printf("已生成 tuned.eni\n");
return 0;
}
参考

ETG.2100 EtherCAT Network Information 标准;pugixml 1.13+ 与 C++17 编译要求。