错误处理
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 Error | CoE 读写失败 | 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 配置(大小、方向)0x001BSM 看门狗超时 — PDO 周期过慢或通信中断0x002D同步错误 — DC 同步配置问题,检查 SYNC0 周期0x0032DC 同步超时 — 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);
日志详情
日志系统详见 日志。