跳到主要内容

错误处理

EtherCAT 通信中的错误处理策略和常见故障排查。

错误类型

类型来源处理方式
AL Status Code从站状态转换失败通过 GetSlaveALStatusCode() 读取,使用 diagnostics_classify_al_error() 分类
SDO ErrorCoE 读写失败SDOread() 返回 NULL,错误码见 SDO Abort
PDO 丢帧通信异常通过 PDOFrameLoss 回调 监控
Emergency从站硬件/固件错误通过 Emergency 回调 接收
状态降级从站异常回退通过 StateChanged 回调 监控

错误类型枚举:

typedef enum {
EC_ERROR_FRAME_LOST = 0, /* 帧丢失 */
EC_ERROR_OUT_OF_ORDER = 1, /* 帧顺序错误 */
EC_ERROR_CHECKSUM = 2, /* 校验和错误 */
EC_ERROR_TIMEOUT = 3, /* 超时 */
EC_ERROR_WKC_MISMATCH = 4, /* 工作计数器不匹配 */
EC_ERROR_LINK_LOST = 5 /* 链路丢失 */
} ec_error_type_t;

状态转换错误

检测方式

if (!dll.SetStateSequence(master, EC_STATE_OPERATIONAL, 10000)) {
printf("状态转换失败\n");
for (uint16_t i = 1; i <= slave_count; i++) {
uint16_t al = dll.GetSlaveALStatusCode(master, i);
uint8_t st = dll.GetSlaveState(master, i);
if (al != 0)
printf("从站 %d: 状态=0x%02X, 错误码=0x%04X\n", i, st, al);
}
}

错误分类

使用 diagnostics_classify_al_error() 快速判断处理策略:

DarraAlErrorClass cat = diagnostics_classify_al_error(al_code);
switch (cat) {
case AL_ERROR_TRANSIENT:
/* 重试状态转换 */
break;
case AL_ERROR_CONFIGURATION:
/* 检查 PDO 映射、SM 配置 */
break;
case AL_ERROR_HARDWARE:
/* 检查从站设备、线缆、电源 */
break;
}
详细分类

完整的 AL 错误分类和常见错误码请参考 主站诊断 - AL 错误分类

常见 AL Status Code

  • 0x001E 无效输入映射 — 检查 PDO 映射配置是否与从站支持的映射一致
  • 0x001D 无效输出映射 — 检查 PDO 输出映射配置
  • 0x0017 无效 SM 配置 — 检查 SyncManager 配置(大小、方向)
  • 0x001B SM 看门狗超时 — PDO 周期过慢或通信中断
  • 0x002D 同步错误 — DC 同步配置问题,检查 SYNC0 周期
  • 0x0032 DC 同步超时 — DC 启动时间配置问题
  • 0x0003 无效设备设置 — 耦合器无物理模块,或模块配置不匹配

事件驱动的异常处理

推荐通过事件监控异常,而非轮询:

static void on_state_change(uint16_t mi, uint16_t si, int old_s, int new_s) {
if (new_s < old_s) printf("从站 %d 状态降级: %d -> %d\n", si, old_s, new_s);
}
static void on_discovery(uint16_t mi, uint16_t si, BOOL is_found) {
printf("从站 %d %s\n", si, is_found ? "上线" : "离线");
}
static void on_frame_loss(uint16_t mi, uint8_t grp, uint32_t cons, uint32_t total) {
if (cons > 10) printf("组 %d 严重丢帧: 连续 %u 帧\n", grp, cons);
}
static void on_emergency(uint16_t mi, uint16_t si,
uint16_t err, uint16_t reg, uint8_t b1, uint16_t w1, uint16_t w2) {
printf("从站 %d 紧急消息: 0x%04X\n", si, err);
}

dll.RegisterStateChangeSync(on_state_change);
dll.RegisterDiscoverySync(on_discovery);
dll.RegisterPDOFrameLoss(on_frame_loss);
dll.RegisterEmergency(on_emergency);
自动日志

所有事件(PDO 周期回调除外)触发时系统均自动记录日志,无论是否订阅。详见 事件

常见故障排查

初始化失败

  • 管理员权限不足 → 以管理员身份运行
  • 网卡名称不匹配 → 检查 GetNetworkInfo() 返回的网口列表
  • 无从站响应 → 检查网线连接和从站供电

从站无法进入 OP

  • PDO 映射不匹配 → 检查 GetSlaveALStatusCode(),常见 0x001E/0x001D
  • ESI 版本不匹配 → 使用与固件版本对应的 ESI 文件
  • DC 同步失败 → 检查 DC 配置,确认 SYNC0 周期合理
  • SM 配置错误 → 检查 SyncManager 大小和方向
  • 缺少启动参数 → 使用 AddStartupParameter() 添加

通信不稳定

  • 丢帧率高 → 检查网线质量、交换机端口、EMI 干扰
  • 抖动大 → 安装 DarraRT 驱动,隔离 CPU 核心
  • 偶尔超时 → 检查系统负载,关闭不必要的后台进程
  • DC 同步偏差大 → 使用 DarraRT 驱动降低抖动

日志系统

static void on_log(int category, const char* message) {
const char* level[] = {"ERROR", "WARN", "INFO", "MBX", "PDO", "DEBUG"};
printf("[%s] %s\n", level[category], message);
}

dll.SetLogCallback(on_log);
dll.SetDebugLogging(TRUE);
dll.SetMailboxLogging(TRUE);
dll.SetPDOLogging(TRUE);

日志类别 (category):

名称默认说明
0ERROR始终输出致命错误 / 状态转换失败 / 不可恢复故障
1WARN始终输出重试 / 单帧丢失 / 配置问题等可恢复警告
2INFO始终输出状态变化 / 启动参数应用 / 主流程消息
3MBXSetMailboxLogging 控制CoE/SoE/FoE 邮箱收发追踪
4PDOSetPDOLogging 控制PDO 周期级别详细日志 (高频)
5DEBUGSetDebugLogging 控制调试与诊断输出
PDO 日志开销

启用 PDO 日志后每周期均会调用日志回调 (1ms 周期下约 1000 次/秒), 仅在排障时短时开启, 完成后立即关闭。

日志详情

日志系统详见 日志

协议错误码参考

CoE SDO Abort 码 (主要):

含义
0x05030000Toggle bit 不一致
0x05040000SDO 协议超时
0x06010000不支持的访问
0x06010002对只读对象执行写
0x06020000对象不存在
0x06070010数据类型/长度不匹配
0x06090011子索引不存在
0x06090030数值超出范围
0x08000022当前设备状态不允许传输

FoE 错误码:

含义
0x00008001无效操作码 / 未实现
0x00008002文件未找到
0x00008003非法文件名
0x00008005磁盘空间不足
0x00008006校验失败

SoE 错误码 (ETG.1020):

含义
0x1001无效命令
0x1009IDN 不存在
0x3002无效数据大小
0x4001元素属性不可写
0x6001数据超出范围
0x7002写入失败

异步任务错误码:

常量说明
ASYNC_OK0操作成功
ASYNC_ERR_PARAM-1参数非法
ASYNC_ERR_OOM-2内存分配失败
ASYNC_ERR_OS-3底层 OS 调用失败
ASYNC_ERR_TIMEOUT-4等待超时, 可重试
ASYNC_ERR_DETACHED-5已 detach 的句柄不能再 join
ASYNC_ERR_NOT_RUN-6任务未启动或已 join