目前是C开发的代码,基于ethercat 1.6.x 版本使用
到现在为止没有发现 1.6.x 不兼容的情况。
明确不兼容 1.5.x
1 | //通过索引连接 ethercat主站 |
输入索引,创建域
1 | //ethercat/include/ecrt.h |
这一步其实也是获取基本信息。有几个从站,能拿到主站和从站的对象
1 | //配置从站, 这一步只是“拿到从站配置句柄”。返回值就是一个 ec_slave_config_t*,后续你再用它去做 PDO/SDO/DC 等配置 |
这里其实是创建了从站的配置.
这里开始就比较关键了。
有两种方式可以拿到从站的配置信息
1 | user@ak41-ubuntu:~$ ethercat xml -m3 -p0 |
他就会把从站的ESI信息给你,你就可以完全按照这个来操作.
但是… 这里有一个坑。
首先这是是不全的,他只是厂商的默认的。
有的厂商默认的比较好,有的厂商默认的比较差。所以光看这个是看运气的。
因为之前想要做一个通过 ESI文件自适应,让电机能直接跑的工具。
直接上了 ethercat xml 导致了后续的很多问题,目前都还没有去修改回ESI文件,因为没时间
另外就是有些电机厂商对于ESI文件分的比较细,按照我的想法,所有都允许传就行了,我遇见过最极端的分了30多个…
为什么真多个我不理解,ESI文件都给我看的脑袋疼。
所以建议还是第二种方法.
ESI文件分析
这个我已经写了一篇ESI文件简单结构和内容的文章, 需要的可以查一下
基本开发基本ok,但是需要Ethercat官方那个文件,需要边搞边查.
我就拿我其中一台来举例子了
https://blog.callmetommy.cn/2025/08/05/202507/ethercat_yundong_model/
这个是我之前写的文章
现在我列出EYOU电机的ESI部分
1 | <RxPdo Fixed="0" Sm="2"> |
一步一步来
1 | <Sm DefaultSize="20" StartAddress="#x1200" ControlByte="#x64" Enable="1">Outputs</Sm> |
这个单位是字节,所以是
RxPDO 是 160bit
TxPDO 是 112bit
第一步列出所需要的数据
1 | static ec_pdo_entry_info_t eyou_pdo_entries[] = { |
唯一需要注意的是
1 | {0x0000, 0x00, 56}, // Padding |
160 - 16 - 32 - 32 - 16 - 8 = 56.
剩下的其实是从 ESI 文件照搬下来的。
继续
1 | static ec_pdo_info_t eyou_pdos[] = { |
这里是重新组织了一下
你可以理解为最后的结果类似于
1 | eyouSyncs = [ |
ok. 我有东西了,那就告诉从站,我会怎么传数据
1 | LOG_INFO("MT电机 (从站 %zu) 配置PDO\n", i); |
讲一个特殊的
1 | else if (info[i].vendor_id == VENDOR_ID_TAISHAN && info[i].product_code == PRODUCT_CODE_TAISHAN) { |
ecrt_slave_config_sdo8 这个就是没有InitCmd的后果.
1 | //配置分布式时钟 (DC) |
1 | <OpMode> |
这里讲一下参数
1 | ecrt_slave_config_dc(sc[i], 0x0300, CYCLE_TIME_NS, 2 * CYCLE_TIME_NS / 3, 0, 0) |
这里其实是我的知识盲点
SYNC0 的相位偏移,相对于周期起点的时间偏移(可为负
1 | 时间 → |
之前的
1 | // EYOU电机PDO注册 |
其实就是按照
1 | static ec_pdo_entry_info_t eyou_pdo_entries[] = { |
去注册.
需要注册的是 &off_error_code[i], 基本都是偏移的值,后续循环的时候需要使用。
1 | ecrt_domain_reg_pdo_entry_list(domain, domain_regs) |
最后给主站注册这些地址.
1 | // 设置实时调度策略 |
这些其实主要是为了提高系统的实时性。
按需取用即可,甚至你可以不用。
1 | crt_master_activate(master) |
1 | uint8_t *domain_pd = ecrt_domain_data(domain) |
用domain_pd + 之前注册得到的偏移 off_,在实时循环里直接读/写 PDO 条目。
1 | LOG_INFO("设置初始应用时间...\n"); |
初始化时间
1 | unsigned int cycle_counter = 0; |
初始化参数
- EC_WC_ZERO:本周期“未交换任何已注册的过程数据”。常见原因:域未激活/未queue+send、PDO 注册或映射不匹配、链路/从站掉线。
- EC_WC_INCOMPLETE:本周期“只交换了部分过程数据”。常见原因:丢帧、个别从站未响应、周期超时/系统过载、拓扑或电缆问题。
- EC_WC_COMPLETE:本周期“已交换全部注册的过程数据”。理想状态。
开始循环
1 | while (keep_runing) |
然后电机就可以成功运行起来了。
其他模式或者你想怎么更细节的电机控制,比如精细的控制,控制到哪一步。
就看你具体的模式了