尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

IGH+EtherCAT实时电机控制:从编译到伺服使能全解析

IGH+EtherCAT实时电机控制:从编译到伺服使能全解析 简介适用于IGH EtherCAT与Xenomai实时控制电机的小型工程面向工业控制、机器人及运动控制开发者。资源包含完整编译环境与运行代码下载解压后只需修改main.c中的电机ID即可快速驱动电机。包内共307个文件以h头文件为主另有编译生成的ko驱动模块、so动态库、a静态库、la库文件及ethercat相关配置脚本等覆盖依赖库、驱动和工具链整体压缩包约9.97MB结构紧凑便于查阅。目前已有3160人学习。随资源附带B站视频演示与作者CSDN专栏的搭建教程链接可对照完成IGH环境搭建、实时性配置与电机调试尤其适合正在学习EtherCAT主站与Xenomai实时系统联动、需要现成工程参考的开发者。该工程能显著缩短环境部署和踩坑时间帮助读者聚焦控制逻辑与参数整定。1. IGH实时控制电机这个小项目的出发点与运行链路一套真实的电机控制项目远远不是写几个位操作就能让伺服转起来那么简单。IGHIgH EtherCAT Master配合 Xenomai 3 实时扩展把 Linux 变成一个硬实时主站EtherCAT 从站侧只需要一个支持 CoECANopen over EtherCAT协议的伺服驱动器就能在微秒级抖动下完成位置同步。这个项目把从编译环境到驱动代码的完整链路收在一个压缩包里解压后你需要动手的地方很少打开那个名为mian.c的文件——这不是笔误作者就这么起的——把从站编号改成你实际接线的那台电机。它适合两类人一类是刚拿到伺服和 EtherCAT 耦合器、想快速验证主站能不能跑通的新手另一类是已经在用 PLC 做主站、想评估 IGH 实时性能的嵌入式工程师。整条运行链路值得拆开看应用层任务绑定到 Xenomai RT 线程通过 IGH 用户态接口写过程数据再经 RTDM 驱动发出帧每一步都有它的设计意图。2. 编译环境与库依赖从libcobalt到libethercat_rtdm2.1 Xenomai 3 与 IGH 的版本匹配关系IGH 作为 Linux 用户态主站底层有两个关键载体Xenomai 的实时调度核Cobalt和 RTDM 实时驱动模型。从解压后出现的libcobalt.so.2.0.0、libcopperplate.so.0.0.0可以判断这套环境是基于 Xenomai 3 构建的而不是老旧的 Xenomai 2。这一点很重要因为 IGH 从 1.5 版本才开始原生支持 Xenomai 3 的--with-xenomai配置路径且 Xenomai 3 的库不再像旧版那样只提供单个libxenomai而是拆分成一组按功能区分的库文件。下面这张表把你在项目目录里看到的库文件对应角色说清楚库文件角色使用场景libcobalt.so.2.0.0Xenomai 3 实时内核核心库RT 任务调度、互斥锁、信号量libcopperplate.so.0.0.0多 API 同步层让 Alchemy/VxWorks/PSOS 等 API 共存libalchemy.so.0.0.0原生 C 语言实时 APIRT 任务创建、周期定时器libvxworks.so.0.0.0VxWorks 兼容层迁移老代码用libethercat.so.1.1.0IGH 用户态主站库提供 ecrt_* 主站控制接口libethercat_rtdm.so.1.1.0IGH 的 RTDM 映射库支持在 Xenomai RT 线程内直接收发帧需要注意libethercat.so.1.1.0与libethercat_rtdm.so.1.1.0是 IGH 编译时分别开启用户态和 RTDM 模式产生的。非实时场景下调用前者而实时线程内由于中断屏蔽、调度延迟问题必须依赖后者才能稳定送达。2.2 编译 IGH 的完整命令与参数含义常规做法是先编译安装 Xenomai 3再把 IGH 指向它的安装前缀。我这里给出最常见的配置命令网卡驱动按通用型处理cd /usr/src/etherlab ./configure \ --with-xenomai/usr/xenomai \ --enable-rtdm \ --enable-generic \ --disable-8139too make -j$(nproc) sudo make install sudo ldconfig配置参数说明--with-xenomai/usr/xenomai指定 Xenomai 3 安装前缀configure 会在这个目录下查找cobalt.h和xenomai/config.h。如果路径填错编译时会出现找不到cobalt/kernel.h的错误。--enable-rtdm让 IGH 生成libethercat_rtdm并把主站设备绑定到 RTDM 协议栈。这一步是决定你的控制线程能否在 RT 周期里稳定发送的关键。--enable-generic使用通用网卡驱动。对于 Intel 82574L、Realtek 8111 这类常见网卡通用驱动比专门为某个驱动打补丁更省心。--disable-8139too显式关闭老旧的 8139 网卡驱动避免自动探测干扰实时链路。编译完成后libethercat.so.1.1.0会安装到/usr/local/liblibethercat_rtdm.so.1.1.0则是在主站内核模块加载后才被动态链接。而libcopperplate.so.0是指向libcopperplate.so.0.0.0的符号链接缺少这个链接时动态加载器会直接报cannot open shared object file。2.3 环境变量与运行前检查运行编译出的main可执行文件之前至少确认三件事# 检查 IGH 主站内核模块是否已加载 lsmod | grep ec_master # 检查 RTDM 设备节点是否生成 ls -l /dev/ethercat* # 检查 Xenomai 库能否被动态链接器找到 ldd ./main | grep -E cobalt|ethercat如果lsmod没有输出先执行sudo modprobe ec_master如果/dev/ethercat0不存在检查 udev 规则或者手动sudo mknod /dev/ethercat0 c 240 0。ldd的结果里如果缺失libcobalt.so.2.0.0说明/usr/xenomai/lib不在动态库搜索路径中需要把该路径追加进/etc/ld.so.conf后执行ldconfig。这一步不做后面即使编译通过也会在启动阶段报“无法加载共享库”。3. 修改mian.c把电机ID换成你的从站地址3.1 先看懂主站如何识别从站IGH 主站启动后会扫描 EtherCAT 总线上所有从站得到每个从站的vendor_id和product_code。主站程序里必须为每个从站创建一个ec_slave_config_t配置对象而识别方式有两种一是位置索引即从站在总线上的物理顺序二是设备 ID即厂商 ID 加产品码。mian.c里要改的“电机 ID”并不是伺服驱动器外壳上印的那个编号而是程序里从站配置数组的匹配键。这里有一个常见误区有人以为只要改station_address就能跳线实际上 IGH 是通过ecrt_master_slave_config传入的 vendor/product 组合来匹配物理从站的匹配不上时 API 会返回 NULL控制线程根本起不来。3.2 找到需要改的那一行打开mian.c大概率会看到类似下面的配置块static ec_slave_config_t *servo1 NULL; /* 例如实际从站是总线上的第3个设备索引从0开始 */ servo1 ecrt_master_slave_config( master, /* 已请求的主站对象 */ 2, /* 从站在总线上的位置 */ 0x000004d2, /* 你的驱动器的Vendor ID */ 0x01000000 /* 产品码按手册修改 */ ); if (!servo1) { fprintf(stderr, 从站配置失败检查位置和ID\n); return -1; }这段代码的逻辑说明ecrt_master_slave_config返回的指针如果为空意味着主站扫描到的从站中没有任何一个同时满足“位置索引2、Vendor ID0x000004d2、Product Code0x01000000”这三个条件。如果总线上只有一台电机并且直接接在主站网口的第一个口就把第二个参数改成0如果前面还接了 IO 耦合器或其他从站则按实际顺序递增。3.3 从命令行读取真实 IDmian.c里的 Vendor ID 和 Product Code 不能照抄必须用 IGH 自带工具读实际值# 查看总线上所有从站的详细信息 sudo ethercat slaves -v命令输出的每一行都会列出类似0x000004d2:0x01000000这样的组合前面是厂商 ID后面是产品码。把这两个十六进制值填回代码里的结构体。很多国产伺服从站会采用兼容别人的厂商 ID比如某些台达、汇川驱动器返回的是 0x000004d2但产品码不同不核对就运行结果必然是配置失败。同样的道理也适用于位置索引先数清楚总线上有几个从站再决定索引值。3.4 加一段启动自检代码在调用ecrt_master_activate(master)之前可以插入一段打印确认主站看到的从站信息ec_slave_info_t info; if (!ecrt_master_get_slave(master, 2, info)) { printf(从站2: vendor0x%08x, product0x%08x\n, info.vendor_id, info.product_code); }ecrt_master_get_slave的第一个参数是主站指针第二个参数是位置索引。如果这行打印出来的值和你在ecrt_master_slave_config里填的不一致程序会在后面的空指针判断处退出。这时不要着急调参数回到上一节重新读取真实 ID。还有一种常见现象如果电机通电后没有进入 OP 状态IGH 也扫不到它。规范操作是先给驱动器上电等它完成自检并进入 Ready 状态后再启动主站程序顺序反了就会看到总线扫描结果里少一个设备。3.5 使用从站别名固定设备位置在带多个设备的产线上物理接线一旦调整位置索引就会变化。IGH 支持向从站 SIIEEPROM写入别名地址sudo ethercat alias -p 2 -n 0x0011-p 2指定位置索引为 2 的从站-n 0x0011是要写入的别名。写入后主站代码里可以把位置参数换成别名对应的逻辑位置。这个操作会写入从站的 EEPROM属于一次性的。有些伺服驱动器不允许外部写 SII写入会报错遇到这种情况直接沿用位置索引即可不写别名也能运行。4. 实时控制参数周期、PDO映射和使能指令怎么配4.1 实时任务周期与优先级怎么设IGH 主站本身不产生同步时钟实时性完全靠 Xenomai 的任务周期来保证。mian.c里通常会构造一个周期任务周期单位是纳秒。1ms 起步最稳链路稳定后再缩到 250us。盲目追求小周期没有意义因为帧间隔还要看网卡中断延迟和 RTDM 驱动质量。创建实时任务时优先级通常设成 90 到 99 之间但要注意不能超过 IGH 主站内部线程的优先级否则你的控制逻辑会抢占主站发帧的时机导致总线超时。#define CYCLE_TIME_NS 1000000 /* 1ms */ RT_TASK rt_task; rt_task_create(rt_task, ecat_cycle, 0, 90, 0); rt_task_start(rt_task, cycle_function, NULL);参数说明rt_task_create的第三个参数是栈大小填 0 表示使用默认值第四个参数90是优先级最后一个 0 表示不设置特殊模式。在cycle_function里用rt_task_set_periodic绑定周期rt_task_set_periodic(rt_task, TM_NOW, CYCLE_TIME_NS);TM_NOW表示从现在开始计时。这样每次循环结尾调用rt_task_wait_period就会阻塞到下一个周期点。4.2 PDO 映射决定你发什么和读什么伺服驱动器默认支持 DS402 对象字典但 IGH 不会自动把对象字典映射到过程数据。需要手动定义 PDO 条目常见的位置模式映射如下ec_pdo_entry_info_t servo1_pdo_entries[] { {0x6040, 0x00, 16}, /* 控制字 */ {0x607A, 0x00, 32}, /* 目标位置 */ {0x6041, 0x00, 16}, /* 状态字 */ {0x6064, 0x00, 32}, /* 实际位置 */ };每行花括号里的三个数字分别是对象索引、子索引、位宽。控制字和状态字必须是 16 位目标位置和实际位置通常是 32 位。有些驱动器要求映射条目按顺序排列控制字在前、目标值在后顺序错了会一直卡在 SAFEOP 状态。IGH 对 PDO 总长度有 64 字节上限且建议 4 字节对齐否则ecrt_domain_reg_pdo_entry_list会返回对齐错误。4.3 伺服使能状态机与代码实现DS402 规定伺服从上电到可运动要经过状态机切换先发 0x06禁用电压再发 0x07准备上电最后发 0x0F使能运行。下面这段循环实现了完整切换uint16_t cw 0x0000; for (int i 0; i 3; i) { switch (i) { case 0: cw 0x06; break; case 1: cw 0x07; break; case 2: cw 0x0F; break; } /* ctrl_offset 是控制字在过程数据域中的偏移 */ *(uint16_t *)(domain_data ctrl_offset) cw; ecrt_domain_process(domain); ecrt_master_send(master); rt_task_sleep(CYCLE_TIME_NS); }逻辑说明每次写控制字之后都要先调用ecrt_domain_process更新输出数据再用ecrt_master_send把帧发出去。ctrl_offset是在ecrt_domain_reg_pdo_entry_list注册 PDO 时返回的必须在代码里保存下来。如果跳过了 0x06 或 0x07直接发 0x0F绝大多数驱动器会忽略命令状态字永远停在 0x00。使能成功后状态字一般会变成 0x23 或 0x27可以打印出来做确认。4.4 周期抖动与参数调节的参考表不同网卡和驱动组合下抖动范围差异很大。根据经验可参考下面的对照周期设定抖动范围实际效果1ms±50us大部分伺服不会报警250us±20us需要性能较好的网卡和 RTDM 驱动125us±10us抖动超出设计值容易触发同步错误如果抖动明显大于表中范围优先检查网卡是否被正确绑定到ec_master以及 BIOS 里有没有关闭 C-States 和 SpeedStep 电源管理。另外Xenomai 的miss计数是一个硬指标在实时循环里或通过/proc/xenomai/sched查看如果 miss 数持续增长说明任务周期被高优先级中断打断需要考虑中断绑核。5. 验证与排错从dmesg到SYNC信号观测5.1 dmesg 先扫一遍启动主站程序后第一件事是看内核日志sudo dmesg | grep -i ethercat如果看到Master: ... activated说明主站正常激活如果看到Link not up则是网线或网卡驱动问题。IGH 绑定网卡时要确保该网卡没有被其他驱动占用否则会出现Device busy。这时可以先sudo ip link set eth0 down再重新加载模块。5.2 用 ethercat 命令验证从站状态sudo ethercat states -p 2输出中的从站状态应为OP。如果显示PREOP或SAFEOP说明 PDO 配置不完整或初始化未成功。此时运行sudo ethercat slaves -v核对 Vendor ID 与 Product Code 是否一致。状态字卡在0x01时通常是控制字没有按 DS402 顺序发送回到第 4 章的使能序列重新检查。5.3 示波器观测 SYNC 信号验证实时性最直观的方法不是看程序打印而是拿示波器接伺服驱动器的 SYNC 输出引脚。开启 DC 同步后驱动器会输出周期脉冲。把示波器时基调到与周期一致观察脉冲间隔是否均匀。我一般还会在实时循环里翻转一个 GPIO用第二通道同时测量主站软件周期和驱动器硬同步周期的偏差。如果 SYNC 抖动明显而 dmesg 无异常运行下面的命令查看 RT 任务状态watch -n 1 cat /proc/xenomai/sched观察ec_master线程的miss计数。如果 miss 持续增加说明 IGH 主站线程被抢占考虑把网卡中断绑定到另一个 CPU 核或者使用--enable-rtdm编译的 RDTM 驱动重新构建主站。本文还有配套的精品资源点击获取
返回列表