跳到主要内容

错误处理

Rust SDK 使用 Result<T, DarraError> 进行错误处理,所有可能失败的操作均返回 Result

DarraError 枚举

use ethercat::DarraError;

#[derive(Debug, Clone)]
pub enum DarraError {
/// 主站已初始化
AlreadyInitialized,
/// 主站未初始化
NotInitialized,
/// 操作超时
Timeout,
/// 未发现从站
NoSlaves,
/// 网络配置失败 (返回码)
NetworkFailed(i32),
/// 状态切换失败 (目标状态)
StateChangeFailed(u8),
/// SDO 读取失败 (index, subindex)
SdoReadFailed { index: u16, subindex: u8 },
/// SDO 写入失败 (index, subindex)
SdoWriteFailed { index: u16, subindex: u8 },
/// SoE 操作失败 (IDN)
SoeFailed(u16),
/// FoE 操作失败 (文件名)
FoeFailed(String),
/// EoE 操作失败
EoeFailed,
/// AoE 操作失败
AoeFailed,
/// VoE 操作失败
VoeFailed,
/// 无效参数
InvalidParameter(String),
/// 配置加载失败
ConfigLoadFailed(i32),
/// 空指针 (DLL 返回 null)
NullPointer,
/// CiA 402 操作失败
CiA402Failed(String),
/// EMCY 操作失败
EmcyFailed,
/// PDO 操作失败
PdoFailed(String),
/// 拓扑操作失败
TopologyFailed,
/// 冗余操作失败
RedundancyFailed,
/// 寄存器操作失败
RegisterFailed,
/// 诊断操作失败
DiagnosticsFailed,
/// WDK 操作失败
WdkFailed(String),
/// UDP 操作失败
UdpFailed,
/// 其他错误
Other(String),
}

DarraError 实现了 Display trait,可直接用 {} 格式化输出中文错误描述。

错误类型

类型来源处理方式
AL Status Code从站状态转换失败通过 slave.error_code() 读取,使用 classify_al_error() 分类
SDO ErrorCoE 读写失败SDO 方法返回 Err(DarraError::SdoReadFailed / SdoWriteFailed)
PDO 丢帧通信异常通过 PDOFrameLoss 事件 监控
Emergency从站硬件/固件错误通过 Emergency 事件 接收
状态降级从站异常回退通过 StateChanged 事件 监控

状态转换错误

match master.set_state(EcState::Operational) {
Ok(()) => println!("状态切换成功"),
Err(e) => {
eprintln!("状态切换失败: {}", e);
for slave in master.slaves() {
let code = slave.error_code();
if code != 0 {
eprintln!(" 从站 {}: AL Status Code = 0x{:04X}", slave.index(), code);
}
}
}
}

错误分类

use ethercat::classify_al_error;

let category = classify_al_error(slave.error_code());
match category {
ALErrorCategory::Transient => {
// 瞬态错误,重试状态转换
}
ALErrorCategory::Configuration => {
// 配置错误,检查 PDO 映射、SM 配置
}
ALErrorCategory::Hardware => {
// 硬件错误,检查从站设备、线缆、电源
}
_ => {}
}

常见 AL Status Code

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

事件驱动的异常处理

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

// 状态降级检测
master.events().on_slave_state_changed(|_, _, old, new| {
if (new as u8) < (old as u8) {
println!("状态降级: {:?} -> {:?}", old, new);
}
});

// 从站离线
master.events().on_slave_offline(|slave_index| {
println!("从站 {} 离线", slave_index);
});

// PDO 丢帧
master.events().on_pdo_frame_loss(|master_index, group, consecutive, total| {
if consecutive > 10 {
println!("组 {} 严重丢帧: 连续 {} 帧", group, consecutive);
}
});

// 紧急消息
master.events().on_emergency(|_master_index, slave_index, error_code, _error_reg, _b1, _w1, _w2| {
println!("从站 {} 紧急消息: 0x{:04X}", slave_index, error_code);
});

常见故障排查

build() 返回 Err

  • 管理员权限不足 — 以管理员身份运行
  • 网卡名称/MAC 不匹配 — 检查 EtherCATMaster::get_network_info() 返回的网口列表
  • ENI/DENI 文件路径错误 — 确认文件路径存在且可读
  • 无从站响应 — 检查网线连接和从站供电

从站无法进入 OP

  • PDO 映射不匹配 — 检查 slave.error_code(),常见 0x001E/0x001D
  • DC 同步失败 — 检查 DC 配置,确认 SYNC0 周期合理
  • 缺少启动参数 — 使用 DENI 文件或 enable_auto_startup()

日志系统

use ethercat::{LogManager, LogCategory};

let log_mgr = LogManager::instance();
let view = log_mgr.default_view();
println!("日志数: {}", view.count());

// 启用详细日志(调试用)
EtherCATMaster::set_debug_logging(true);
EtherCATMaster::set_mailbox_logging(true);
日志详情

日志系统详见 日志