CiA 402 — 伺服驱动器辅助
CiA 402 (IEC 61800-7-204) 是基于 CoE 的伺服驱动器设备协议。CiA402Instance 封装了驱动器状态机管理、操作模式切换和运动参数访问功能。
CiA 402 运行在 CoE (SDO) 之上。
CiA402Instance需要独立构造,不是通过slave.coe()链式访问。
两种使用方式: slave.cia402_* vs CiA402Instance
SDK 提供两套 CiA 402 接口, 按场景选择:
slave.cia402_* — 轻量直调 (SDO-only)
挂在 Slave 上的快捷方法, 不依赖 PDO 映射, 全程走 SDO. 适合单次操作 / 调试 / 非周期场景。
可用方法:
slave.cia402_state()→CiA402State— 读当前驱动器状态slave.cia402_enable()→Result<()>— 一键使能 (SDO 推进状态机)slave.cia402_set_mode(mode: i8)→Result<()>/slave.cia402_mode()→i8— 操作模式读写 (0x6060 / 0x6061)slave.cia402_status_word()→u16— 读 0x6041slave.cia402_write_control_word(cw: u16)→Result<()>— 写 0x6040slave.cia402_fault_reset()→Result<()>— 复位 0x6040 Bit 7
示例:
let slave = master.slave(1);
// 调试: 上电检查驱动器是否处于 OperationEnabled
println!("当前状态: {:?}", slave.cia402_state());
// 一次性使能 + 读状态
slave.cia402_enable()?;
println!("使能后状态字: 0x{:04X}", slave.cia402_status_word());
CiA402Instance — 高性能完整接口 (PDO + SDO)
需要先通过 Cia402PdoMap::scan() 扫描 PDO 映射, 然后构造完整实例. 0x1C12 / 0x1C13 中已映射的对象走 PDO 零拷贝, 未映射的对象自动回退 SDO. 适合周期运动控制 / 高频读写。
典型场景:
- PDO 周期内频繁读取 ActualPosition / ActualVelocity / StatusWord
- 周期内写入 TargetPosition / ControlWord, 走 PDO 不阻塞
- 需要
enable()/quick_stop()/fault_reset()等高级状态机封装
选择对比
- 调试 / 离线诊断 / 一次性操作 → 用
slave.cia402_*, 不需要扫描 PDO 映射, 接口简单 - 周期运动控制 / 实时数据流 → 用
CiA402Instance, 享受 PDO 零拷贝性能 - 混合: 启动时用
slave.cia402_enable()一键使能, 进入 OP 后切换为CiA402Instance做周期控制 (两者可在同一从站上共存)
构造方式
CiA 402 实例需要先扫描 PDO 映射表,然后独立构造:
use ethercat::{Cia402PdoMap, CiA402Instance};
// 1. 扫描 PDO 映射 (读取 0x1C12/0x1C13)
let pdo_map = Cia402PdoMap::scan(master.index(), 1)?;
// 2. 创建 CiA 402 实例
let drv = CiA402Instance::new(master.index(), 1, pdo_map);
PDO 映射扫描
Cia402PdoMap::scan()
pub fn scan(master_index: u16, slave_index: u16) -> Result<Self>
扫描从站 PDO 映射,读取 0x1C12/0x1C13 系列对象的映射参数,以及从站 IOmap 的 IO 指针,建立完整映射缓存。
映射建立后,CiA402Instance 的读写会优先通过 PDO(零拷贝),不在映射中的对象自动回退到 SDO。
示例:
let pdo_map = Cia402PdoMap::scan(master.index(), 1)?;
// 查看映射信息
for entry in pdo_map.output_entries() {
println!("RxPDO: 0x{:04X}:{:02X} {}bit @offset {}",
entry.od_index, entry.sub_index, entry.bit_length, entry.byte_offset);
}
for entry in pdo_map.input_entries() {
println!("TxPDO: 0x{:04X}:{:02X} {}bit @offset {}",
entry.od_index, entry.sub_index, entry.bit_length, entry.byte_offset);
}
状态控制
enable() 一次性推进到 OperationEnabled (内部完成完整状态链 + Fault 复位 + QuickStop 恢复 + 0x605A 选项码判断); disable / disable_operation / quick_stop / fault_reset 仅写一次 Controlword 后立即返回, 通过 state_drive() 检查结果。
enable(max_retries) / enable_default()
pub fn enable(&self, max_retries: i32) -> bool
pub fn enable_default(&self) -> bool // 等价于 enable(10)
使能驱动器: 内部按 CiA 402-2 完成 SwitchOnDisabled → ReadyToSwitchOn → SwitchedOn → OperationEnabled 全套时序、Fault 复位、QuickStop 恢复。
参数:
max_retries— 最大重试次数
返回值:
bool—true= 已使能到 OperationEnabled,false= 失败/超时
示例:
// 一次性使能 (内部完成完整状态机)
if drv.enable_default() {
drv.set_target_position(next_position);
} else {
println!("使能失败, 当前状态: {:?}", drv.state_drive());
}
disable()
pub fn disable(&self)
禁用伺服 (-> SwitchOnDisabled),完全断电。
disable_operation()
pub fn disable_operation(&self)
禁用运行 (OperationEnabled -> SwitchedOn)。
quick_stop()
pub fn quick_stop(&self)
快速停止。
fault_reset()
pub fn fault_reset(&self)
清除故障。
状态读取
state_drive()
pub fn state_drive(&self) -> StateCiA402
从 StatusWord 解析当前驱动器状态。
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StateCiA402 {
NotReadyToSwitchOn = 0, // 初始化中
SwitchOnDisabled = 1, // 驱动禁用
ReadyToSwitchOn = 2, // 准备就绪
SwitchedOn = 3, // 已开启
OperationEnabled = 4, // 运行使能
QuickStopActive = 5, // 快速停止
FaultReactionActive = 6, // 故障反应中
Fault = 7, // 故障
Unknown = 99, // 未知状态
}
statusword() / controlword()
pub fn statusword(&self) -> u16
pub fn controlword(&self) -> u16
pub fn set_controlword(&self, value: u16)
相关方法:
target_reached()-> bool — 目标已到达 (Bit 10)has_fault()-> bool — 存在故障 (Bit 3)has_warning()-> bool — 存在警告 (Bit 7)is_remote()-> bool — 远程模式 (Bit 9)
操作模式
operation_mode() / set_operation_mode()
pub fn operation_mode(&self) -> i8
pub fn set_operation_mode(&self, mode: ModeCiA402)
#[repr(i8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModeCiA402 {
PP = 1, // 轮廓位置模式
VL = 2, // 速度模式
PV = 3, // 轮廓速度模式
PT = 4, // 轮廓转矩模式
HM = 6, // 回零模式
IP = 7, // 插补位置模式
CSP = 8, // 周期同步位置模式
CSV = 9, // 周期同步速度模式
CST = 10, // 周期同步转矩模式
CSTCA = 11, // 周期同步转矩加速度模式
}
is_mode_supported()
pub fn is_mode_supported(&self, mode: ModeCiA402) -> bool
检查驱动器是否支持指定操作模式(通过 0x6502 SupportedDriveModes 判断)。
运动参数
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| position_actual() | i32 | 只读 | 实际位置 (0x6064) |
| velocity_actual() | i32 | 只读 | 实际速度 (0x606C) |
| torque_actual() | i16 | 只读 | 实际转矩 (0x6077) |
| target_position() / set_target_position() | i32 | 读写 | 目标位置 (0x607A) |
| target_velocity() / set_target_velocity() | i32 | 读写 | 目标速度 (0x60FF) |
| target_torque() / set_target_torque() | i16 | 读写 | 目标转矩 (0x6071) |
轮廓参数
| 方法 | 类型 | 说明 |
|---|---|---|
| profile_velocity() / set_profile_velocity() | u32 | 轮廓速度 (0x6081) |
| profile_acceleration() / set_profile_acceleration() | u32 | 轮廓加速度 (0x6083) |
| profile_deceleration() / set_profile_deceleration() | u32 | 轮廓减速度 (0x6084) |
| quick_stop_deceleration() / set_quick_stop_deceleration() | u32 | 快速停止减速度 (0x6085) |
极性与轮廓配置
| 方法 | 类型 | 说明 |
|---|---|---|
| polarity() / set_polarity() | u8 | 极性 (0x607E) |
| motion_profile_type() / set_motion_profile_type() | i16 | 运动轮廓类型 (0x6086) |
| quick_stop_option_code() / set_quick_stop_option_code() | i16 | 快速停止选项 (0x605A) |
触发探针 (Touch Probe)
| 方法 | 类型 | 说明 |
|---|---|---|
| configure_touch_probe(function: u16) | - | 配置探针功能 (0x60B8) |
| touch_probe_status() | u16 | 探针状态 (0x60B9) |
| touch_probe_positive_edge() | i32 | 正边沿捕获位置 (0x60BA) |
| touch_probe_negative_edge() | i32 | 负边沿捕获位置 (0x60BB) |
数字 IO
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| digital_inputs() | u32 | 只读 | 数字输入 (0x60FD),32 位位图 |
| digital_outputs() / set_digital_outputs() | u32 | 读写 | 数字输出 (0x60FE:01),32 位位图 |
示例:
// 读取数字输入
let inputs = drv.digital_inputs();
let limit_switch = (inputs & 0x01) != 0; // 位 0
// 设置数字输出
drv.set_digital_outputs(0x03); // 输出位 0 和位 1
软件位置限制
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| software_position_limit_min() / set_software_position_limit_min() | i32 | 读写 | 软件位置限位下限 (0x607D:01) |
| software_position_limit_max() / set_software_position_limit_max() | i32 | 读写 | 软件位置限位上限 (0x607D:02) |
示例:
// 设置运动范围限制
drv.set_software_position_limit_min(-1_000_000);
drv.set_software_position_limit_max(1_000_000);
扩展运动参数
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| max_torque() / set_max_torque() | u16 | 读写 | 最大转矩 (0x6072),千分之额定 |
| motor_rated_torque() / set_motor_rated_torque() | u32 | 读写 | 电机额定转矩 (0x6076),mNm |
| position_offset() / set_position_offset() | i32 | 读写 | 位置偏移 (0x60B0),CSP 模式叠加 |
| velocity_offset() / set_velocity_offset() | i32 | 读写 | 速度偏移 (0x60B1),CSV 模式叠加 |
| torque_offset() / set_torque_offset() | i16 | 读写 | 转矩偏移 (0x60B2) |
| interpolation_time_period_value() / set_interpolation_time_period_value() | u8 | 读写 | 插补时间周期值 (0x60C2:01) |
| interpolation_time_period_index() / set_interpolation_time_period_index() | i8 | 读写 | 插补时间周期指数 (0x60C2:02),周期 = Value × 10^Index 秒 |
力矩限制
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| positive_torque_limit() / set_positive_torque_limit() | u16 | 读写 | 正方向力矩限制 (0x60E0),千分之额定 |
| negative_torque_limit() / set_negative_torque_limit() | u16 | 读写 | 负方向力矩限制 (0x60E1),千分之额定 |
回零速度与加速度
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| homing_speed_search() / set_homing_speed_search() | u32 | 读写 | 回零搜索速度 (0x6099:01),快速搜索参考信号 |
| homing_speed_zero() / set_homing_speed_zero() | u32 | 读写 | 回零零位速度 (0x6099:02),慢速精确定位零位 |
| homing_acceleration() / set_homing_acceleration() | u32 | 读写 | 回零加速度 (0x609A) |
示例:
drv.set_operation_mode(ModeCiA402::HM);
drv.set_homing_method(1);
// 设置回零速度和加速度
drv.set_homing_speed_search(5000); // 搜索速度
drv.set_homing_speed_zero(500); // 零位速度
drv.set_homing_acceleration(10000); // 回零加速度
快速运动控制
new_setpoint()
pub fn new_setpoint(&self, position: i32, relative: bool)
PP 模式发送新定位命令。设置目标位置并触发 Controlword Bit 4 (New Setpoint)。
参数:
position-- 目标位置relative--true= 相对定位,false= 绝对定位
示例:
drv.set_operation_mode(ModeCiA402::PP);
drv.set_profile_velocity(10000);
drv.set_profile_acceleration(50000);
// 在 PDO 回调中: 先使能,使能后发送定位命令
if drv.state_drive() == StateCiA402::OperationEnabled {
drv.new_setpoint(100000, false); // 绝对定位到 100000
// drv.new_setpoint(5000, true); // 或相对移动 5000
}
clear_new_setpoint()
pub fn clear_new_setpoint(&self)
PP 模式清除 NewSetpoint 标志(Controlword Bit4=0)。在 target_reached() 后调用,完成 SetPointAck 握手。
示例:
if drv.target_reached() {
drv.clear_new_setpoint();
}
start_homing()
pub fn start_homing(&self)
HM 模式启动回零。需先设置 set_homing_method()。
相关方法:
homing_method() / set_homing_method()(i8) -- 回零方法 (0x6098)home_offset() / set_home_offset()(i32) -- 回零偏移 (0x607C)homing_attained()(bool) -- 回零完成 (Bit 12)homing_error()(bool) -- 回零错误 (Bit 13)
示例:
drv.set_operation_mode(ModeCiA402::HM);
drv.set_homing_method(35); // 当前位置回零
// 在 PDO 回调中:
if drv.state_drive() == StateCiA402::OperationEnabled {
drv.start_homing();
// 后续周期检查 drv.homing_attained() / drv.homing_error()
}
驱动器信息
supported_drive_modes()
pub fn supported_drive_modes(&self) -> u32
支持的驱动模式位掩码 (0x6502)。Bit 0=PP, Bit 1=VL, Bit 2=PV, Bit 3=PT, Bit 5=HM, Bit 6=IP, Bit 7=CSP, Bit 8=CSV, Bit 9=CST。
supported_homing_methods()
pub fn supported_homing_methods(&self) -> Vec<i8>
读取驱动器支持的回零方法列表 (0x60E3)。返回所有支持的回零方法编号数组。
示例:
let methods = drv.supported_homing_methods();
println!("支持 {} 种回零方法: {:?}", methods.len(), methods);
TxPDO 数据有效性
txpdo_data_invalid()
pub fn txpdo_data_invalid(&self) -> bool
TxPDO 数据是否无效 (0x603E)。非零表示驱动器 TxPDO 数据不可信(如编码器未就绪时位置值无意义)。
if !drv.txpdo_data_invalid() {
let pos = drv.position_actual(); // 数据有效
}
同步功能
| 方法 | 类型 | 访问 | 说明 |
|---|---|---|---|
| synchronization_settings() / set_synchronization_settings() | u16 | 读写 | 同步设置 (0x60D9:01) |
| drive_sync_status() | u16 | 只读 | 驱动同步状态 (0x60DA) |
完整示例
CSP 模式 — 周期同步位置控制
use ethercat::{Cia402PdoMap, CiA402Instance, ModeCiA402, StateCiA402};
let pdo_map = Cia402PdoMap::scan(master.index(), 1)?;
let drv = CiA402Instance::new(master.index(), 1, pdo_map);
// 设置操作模式
drv.set_operation_mode(ModeCiA402::CSP);
// 一次性使能 (内部完成完整状态机)
if !drv.enable_default() {
println!("使能失败: {:?}", drv.state_drive());
return Ok(());
}
// PDO 回调中每周期下发目标
let events = master.events();
events.on_pdo_cyclic_sync(move |_master_idx| {
drv.set_target_position(calculate_next_position());
});
PP 模式 — 轮廓位置控制
use ethercat::{Cia402PdoMap, CiA402Instance, ModeCiA402};
use std::sync::atomic::{AtomicBool, Ordering};
let pdo_map = Cia402PdoMap::scan(master.index(), 1)?;
let drv = CiA402Instance::new(master.index(), 1, pdo_map);
drv.set_operation_mode(ModeCiA402::PP);
drv.set_profile_velocity(10000);
drv.set_profile_acceleration(50000);
drv.set_profile_deceleration(50000);
// 一次性使能
if !drv.enable_default() {
println!("使能失败: {:?}", drv.state_drive());
return Ok(());
}
// 发送定位命令
drv.new_setpoint(100000, false); // 绝对定位
// PDO 回调等待目标到达后清标志
let homing_done = AtomicBool::new(false);
let events = master.events();
events.on_pdo_cyclic_sync(move |_| {
if !homing_done.load(Ordering::Relaxed) && drv.target_reached() {
drv.clear_new_setpoint();
homing_done.store(true, Ordering::Relaxed);
}
});
HM 模式 — 回零
use ethercat::{Cia402PdoMap, CiA402Instance, ModeCiA402};
let pdo_map = Cia402PdoMap::scan(master.index(), 1)?;
let drv = CiA402Instance::new(master.index(), 1, pdo_map);
drv.set_operation_mode(ModeCiA402::HM);
drv.set_homing_method(35); // 当前位置回零
drv.set_homing_speed_search(5000);
drv.set_homing_speed_zero(500);
drv.set_homing_acceleration(10000);
// 一次性使能
if !drv.enable_default() {
println!("使能失败: {:?}", drv.state_drive());
return Ok(());
}
// 启动回零
drv.start_homing();
let events = master.events();
events.on_pdo_cyclic_sync(move |_| {
if drv.homing_attained() {
println!("回零完成");
}
if drv.homing_error() {
println!("回零错误");
}
});
参数验证
let drv = CiA402Instance::new(master.index(), 1, pdo_map);
// 检查轮廓参数是否满足 PP/PV 模式需求
let warnings = drv.validate_profile_parameters(Some(1)); // PP 模式
for w in &warnings {
println!("警告: {}", w);
}
标准对象索引常量
可搭配 slave.sdo_read/sdo_write 使用:
| 常量 | 值 | 说明 |
|---|---|---|
| OD_CONTROLWORD | 0x6040 | 控制字 |
| OD_STATUSWORD | 0x6041 | 状态字 |
| OD_MODES_OF_OPERATION | 0x6060 | 操作模式设置 |
| OD_MODES_OF_OPERATION_DISPLAY | 0x6061 | 操作模式显示 |
| OD_TARGET_POSITION | 0x607A | 目标位置 |
| OD_POSITION_ACTUAL | 0x6064 | 实际位置 |
| OD_TARGET_VELOCITY | 0x60FF | 目标速度 |
| OD_VELOCITY_ACTUAL | 0x606C | 实际速度 |
| OD_TARGET_TORQUE | 0x6071 | 目标转矩 |
| OD_TORQUE_ACTUAL | 0x6077 | 实际转矩 |
| OD_PROFILE_VELOCITY | 0x6081 | 轮廓速度 |
| OD_PROFILE_ACCELERATION | 0x6083 | 轮廓加速度 |
| OD_PROFILE_DECELERATION | 0x6084 | 轮廓减速度 |
| OD_MAX_TORQUE | 0x6072 | 最大转矩 |
| OD_MOTOR_RATED_TORQUE | 0x6076 | 电机额定转矩 |
| OD_HOME_OFFSET | 0x607C | 回零偏移 |
| OD_SOFTWARE_POSITION_LIMIT | 0x607D | 软件位置限制 |
| OD_POLARITY | 0x607E | 极性 |
| OD_MAX_PROFILE_VELOCITY | 0x6080 | 最大轮廓速度 |
| OD_MOTION_PROFILE_TYPE | 0x6086 | 运动轮廓类型 |
| OD_HOMING_METHOD | 0x6098 | 回零方法 |
| OD_HOMING_SPEEDS | 0x6099 | 回零速度 |
| OD_HOMING_ACCELERATION | 0x609A | 回零加速度 |
| OD_POSITION_OFFSET | 0x60B0 | 位置偏移 (CSP) |
| OD_VELOCITY_OFFSET | 0x60B1 | 速度偏移 (CSV) |
| OD_TORQUE_OFFSET | 0x60B2 | 转矩偏移 |
| OD_TOUCH_PROBE_FUNCTION | 0x60B8 | Touch Probe 功能控制 |
| OD_TOUCH_PROBE_STATUS | 0x60B9 | Touch Probe 状态 |
| OD_TOUCH_PROBE_POS_EDGE | 0x60BA | Touch Probe 正边沿位置 |
| OD_TOUCH_PROBE_NEG_EDGE | 0x60BB | Touch Probe 负边沿位置 |
| OD_INTERPOLATION_TIME_PERIOD | 0x60C2 | 插补时间周期 |
| OD_DIGITAL_INPUTS | 0x60FD | 数字输入 |
| OD_DIGITAL_OUTPUTS | 0x60FE | 数字输出 |
| OD_QUICK_STOP_OPTION_CODE | 0x605A | 快速停止选项码 |
| OD_QUICK_STOP_DECELERATION | 0x6085 | 快速停止减速度 |
| OD_SUPPORTED_DRIVE_MODES | 0x6502 | 支持的驱动模式位掩码 |
控制字命令常量
| 常量 | 值 | 说明 |
|---|---|---|
| CW_SHUTDOWN | 0x06 | 关机命令 |
| CW_SWITCH_ON | 0x07 | 开启命令 |
| CW_ENABLE_OPERATION | 0x0F | 使能运行 |
| CW_DISABLE_VOLTAGE | 0x00 | 禁用电压 |
| CW_QUICK_STOP | 0x02 | 快速停止 |
| CW_FAULT_RESET | 0x80 | 故障复位 |
| CW_HALT | 0x0100 | 暂停位 (Bit 8, 暂停运动但不禁用) |
状态字位掩码常量
| 常量 | 值 | 说明 |
|---|---|---|
| SW_READY_TO_SWITCH_ON | 0x0001 (Bit 0) | 准备就绪 |
| SW_SWITCHED_ON | 0x0002 (Bit 1) | 已开启 |
| SW_OPERATION_ENABLED | 0x0004 (Bit 2) | 运行使能 |
| SW_FAULT | 0x0008 (Bit 3) | 故障 |
| SW_VOLTAGE_ENABLED | 0x0010 (Bit 4) | 电压已使能 |
| SW_QUICK_STOP | 0x0020 (Bit 5) | 快速停止 |
| SW_SWITCH_ON_DISABLED | 0x0040 (Bit 6) | 开启已禁用 |
| SW_WARNING | 0x0080 (Bit 7) | 警告 |
| SW_REMOTE | 0x0200 (Bit 9) | 远程模式 |
| SW_TARGET_REACHED | 0x0400 (Bit 10) | 目标已到达 |
| SW_INTERNAL_LIMIT | 0x0800 (Bit 11) | 内部限位激活 |
| SW_OP_MODE_SPECIFIC_1 | 0x1000 (Bit 12) | 模式相关位 1 |
| SW_OP_MODE_SPECIFIC_2 | 0x2000 (Bit 13) | 模式相关位 2 |