CiA 402 -- 伺服驱动器
CiA 402 (IEC 61800-7-204) 是基于 CoE 的伺服驱动器设备协议。
CiA 402 运行在 CoE (SDO) 之上,仅当从站支持 CoE 时可用。
状态枚举
typedef enum {
CIA402_NOT_READY = 0, /* 未就绪 */
CIA402_SWITCH_ON_DISABLED = 1, /* 开关禁用 */
CIA402_READY_TO_SWITCH_ON = 2, /* 准备开关 */
CIA402_SWITCHED_ON = 3, /* 已开关 */
CIA402_OPERATION_ENABLED = 4, /* 运行使能 */
CIA402_QUICK_STOP_ACTIVE = 5, /* 快速停止 */
CIA402_FAULT_REACTION = 6, /* 故障响应 */
CIA402_FAULT = 7, /* 故障 */
CIA402_UNKNOWN = 99 /* 未知 */
} cia402_state_t;
操作模式枚举
typedef enum {
CIA402_PP = 1, /* 轮廓位置模式 */
CIA402_VL = 2, /* 速度模式 */
CIA402_PV = 3, /* 轮廓速度模式 */
CIA402_PT = 4, /* 轮廓转矩模式 */
CIA402_HM = 6, /* 回零模式 */
CIA402_IP = 7, /* 插补位置模式 */
CIA402_CSP = 8, /* 周期同步位置模式 */
CIA402_CSV = 9, /* 周期同步速度模式 */
CIA402_CST = 10 /* 周期同步转矩模式 */
} cia402_mode_t;
PDO 偏移扫描
CiA 402 标准对象(ControlWord/StatusWord/PositionActual 等)在 IOmap 中的字节偏移由 advanced 层的 cia402_scan_pdo()(ethercat_advanced.h)扫描并填入 cia402_pdo_map_t。OP 状态后调用一次,后续所有 cia402_read_* / cia402_write_* 读写函数即按该偏移访问 PDO(读走输入帧快照,写走版本化整帧 Begin-patch-Commit;未映射时才退化为 SDO),0 拷贝金路径仍是进 OP 后 GetIO 一次钉页(见 PDO 输入输出)。详见下文 PDO 映射扫描。
状态控制
CiA402_Enable()
int CiA402_Enable(uint16_t master, uint16_t slave, int max_retries);
一步使能。DLL 内部自动执行完整的状态链转换(故障清除 -> Shutdown -> Switch On -> Enable Operation)。
参数:
master(uint16_t) — 主站索引slave(uint16_t) — 从站索引max_retries(int) — 最大重试次数
返回值:
int— 非 0 (TRUE) 成功,0 (FALSE) 失败(转发 BOOL 语义, 与CiA402_FaultReset/CiA402_SetMode/CiA402_WriteControlWord一致)
失能与停止
C SDK 没有独立的 Disable / QuickStop 入口,失能与停止统一通过 CiA402_WriteControlWord() 写对应控制字值实现(见 控制字命令常量):
/* 完全失能: 写 ControlWord = 0x0000 (Disable Voltage) */
CiA402_WriteControlWord(master, slave, 0x0000);
/* 仅退出 Operation Enabled 回到 Switched On (保电不输出力矩): 写 0x0007 (Switch On) */
CiA402_WriteControlWord(master, slave, 0x0007);
/* 触发 Quick Stop (Controlword Bit2=0), 按 0x605A 选项码减速停止: 写 0x0002 */
CiA402_WriteControlWord(master, slave, 0x0002);
CiA402_FaultReset()
int CiA402_FaultReset(uint16_t master, uint16_t slave);
故障复位。自动产生 ControlWord Bit 7 上升沿,确保故障清除可靠完成。
参数:
master(uint16_t) — 主站索引slave(uint16_t) — 从站索引
返回值:
int— 非 0 (TRUE) 成功,0 (FALSE) 失败
CiA402_WriteControlWord()
int CiA402_WriteControlWord(uint16_t master, uint16_t slave, uint16_t cw);
写入控制字 (0x6040)。
参数:
cw(uint16_t) — 控制字值
返回值:
int— 非 0 (TRUE) 成功,0 (FALSE) 失败
状态读取
StateDrive
由 CiA402_ParseState() 返回的当前驱动器状态枚举值(cia402_state_t)。典型流程: 读 StatusWord → ParseState → 判断当前是否处于 OPERATION_ENABLED / FAULT 等。
Statusword
通过 CiA402_ReadStatusWord() 读 0x6041 实时状态字。位含义见 状态字位掩码常量。Bit10 (TargetReached)、Bit12 (Set-point Ack / HomingAttained)、Bit13 (Following Error / HomingError) 是 PP / HM 握手关键。
Controlword
通过 CiA402_WriteControlWord() 写 0x6040 控制字。Bit4 (NewSetpoint / StartHoming)、Bit6 (PP 相对/绝对)、Bit8 (Halt) 是常用应用层位。
CiA402_ReadStatusWord()
uint16_t CiA402_ReadStatusWord(uint16_t master, uint16_t slave);
读取状态字 (0x6041)。
返回值:
uint16_t— StatusWord 值
CiA402_ParseState()
cia402_state_t CiA402_ParseState(uint16_t statusword);
从 StatusWord 解析当前驱动器状态。
参数:
statusword(uint16_t) — StatusWord 值
返回值:
cia402_state_t— 驱动器状态
CiA402_GetEnableCommand()
uint16_t CiA402_GetEnableCommand(uint16_t statusword);
根据当前 StatusWord 计算下一步使能所需的 ControlWord。
参数:
statusword(uint16_t) — StatusWord 值
返回值:
uint16_t— 应写入的 ControlWord 值
操作模式
CiA402_SetMode()
int CiA402_SetMode(uint16_t master, uint16_t slave, int8_t mode);
设置操作模式 (0x6060)。写入目标模式后会读取模式显示对象 (0x6061) 确认设备已跟随,设备未跟随时返回失败。
参数:
mode(int8_t) — 操作模式 (cia402_mode_t)
返回值:
int— 非 0 (TRUE) 成功,0 (FALSE) 失败
CiA402_GetMode()
int8_t CiA402_GetMode(uint16_t master, uint16_t slave);
读取当前操作模式 (0x6061)。
返回值:
int8_t— 操作模式 (cia402_mode_t)
PDO 映射扫描 (ethercat_advanced.h)
cia402_pdo_map_t
typedef struct {
int controlword; /* 0x6040 RxPDO 字节偏移 (-1=未映射) */
int target_position; /* 0x607A */
int target_velocity; /* 0x60FF */
int target_torque; /* 0x6071 */
int modes_of_operation; /* 0x6060 */
int statusword; /* 0x6041 TxPDO 字节偏移 (-1=未映射) */
int position_actual; /* 0x6064 */
int velocity_actual; /* 0x606C */
int torque_actual; /* 0x6077 */
int modes_display; /* 0x6061 */
} cia402_pdo_map_t;
cia402_scan_pdo()
int cia402_scan_pdo(uint16_t master, uint16_t slave,
cia402_pdo_map_t* map);
扫描 CiA 402 PDO 映射,自动定位各对象在 IOmap 中的字节偏移。
参数:
master(uint16_t) — 主站索引slave(uint16_t) — 从站索引map(cia402_pdo_map_t*) — 输出映射信息
返回值:
int— 0 成功,非 0 失败
PDO 映射读写
int cia402_read_statusword(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, uint16_t* out);
int cia402_write_controlword(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, uint16_t val);
int cia402_read_position(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t* out);
int cia402_write_target_position(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t val);
int cia402_read_velocity(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t* out);
int cia402_write_target_velocity(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int32_t val);
int cia402_read_torque(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int16_t* out);
int cia402_write_target_torque(uint16_t master, uint16_t slave,
const cia402_pdo_map_t* map, int16_t val);
所有函数返回 0 成功,非 0 失败。
示例:
#include "ethercat_advanced.h"
/* 扫描 PDO 映射 */
cia402_pdo_map_t map;
if (cia402_scan_pdo(master, 1, &map) == 0) {
printf("StatusWord 偏移: %d\n", map.statusword);
printf("ControlWord 偏移: %d\n", map.controlword);
printf("实际位置偏移: %d\n", map.position_actual);
printf("目标位置偏移: %d\n", map.target_position);
/* 通过映射读取状态字 */
uint16_t sw;
cia402_read_statusword(master, 1, &map, &sw);
printf("StatusWord: 0x%04X\n", sw);
/* 写入目标位置 */
cia402_write_target_position(master, 1, &map, 100000);
}
运动参数 (SDO 访问)
以下参数通过 SDO 读写,适合参数配置。高频控制请使用 PDO 映射。SDO 读写接口见 CoE — dx_sdo_read / dx_sdo_write。
| 对象 | 访问 | 类型 | 说明 |
|---|---|---|---|
| 0x6064 | 读 (dx_sdo_read) | int32 | 实际位置 |
| 0x606C | 读 (dx_sdo_read) | int32 | 实际速度 |
| 0x6077 | 读 (dx_sdo_read) | int16 | 实际转矩(千分之额定) |
| 0x607A | 写 (dx_sdo_write) | int32 | 目标位置 |
| 0x60FF | 写 (dx_sdo_write) | int32 | 目标速度 |
| 0x6071 | 写 (dx_sdo_write) | int16 | 目标转矩 |
| 0x6081 | 写 (dx_sdo_write) | uint32 | 轮廓速度 |
| 0x6083 | 写 (dx_sdo_write) | uint32 | 轮廓加速度 |
| 0x6084 | 写 (dx_sdo_write) | uint32 | 轮廓减速度 |
| 0x6085 | 写 (dx_sdo_write) | uint32 | 快速停止减速度 |
| 0x607E | 写 (dx_sdo_write) | uint8 | 极性(Bit6=速度反转, Bit7=位置反转) |
| 0x6086 | 写 (dx_sdo_write) | int16 | 运动轮廓类型(0=梯形, 1=S形) |
| 0x605A | 读写 (dx_sdo_read / dx_sdo_write) | int16 | 快速停止选项码(读失败哨兵见选项码与错误码) |
| 0x6072 | 写 (dx_sdo_write) | uint16 | 最大转矩(千分之额定) |
| 0x6076 | 写 (dx_sdo_write) | uint32 | 电机额定转矩(mNm) |
| 0x60B0 | 写 (dx_sdo_write) | int32 | 位置偏移(CSP 模式叠加) |
| 0x60B1 | 写 (dx_sdo_write) | int32 | 速度偏移(CSV 模式叠加) |
| 0x60C2:01 | 写 (dx_sdo_write) | uint8 | 插补时间周期值 |
| 0x60C2:02 | 写 (dx_sdo_write) | int8 | 插补时间周期指数(周期 = 值 × 10^指数 秒) |
| 0x60E0 | 写 (dx_sdo_write) | uint16 | 正方向力矩限制(千分之额定) |
| 0x60E1 | 写 (dx_sdo_write) | uint16 | 负方向力矩限制(千分之额定) |
dx_sdo_write(mi, si, index, sub, BOOL CA, uint8_t* bytes, int length),dx_sdo_read(mi, si, index, sub, BOOL CA, int* out_byte_size) — 注意 C SDK 的 SDO 接口没有单独的超时参数(超时由 DLL 内部按 ETG 兜底)。完整说明见 CoE 页面。
选项码与错误码 (0x605A–0x605E / 0x603F)
五类驱动器选项码决定各状态转换时的减速/停止行为;错误码反映驱动器当前故障。下列接口直读直写对象字典(薄壳直接导出, 无同名 inline 转发, 按 DarraEcat_ 名调用):
| 类别 | 接口 | 类型 | 读写 | 返回值 |
|---|---|---|---|---|
| 选项码 | DarraEcat_CiA402_GetQuickStopOption(master, slave) | int16 | 只读 | 正常 = 真值;读失败 = -32768 (INT16_MIN) |
| 选项码 | DarraEcat_CiA402_SetQuickStopOption(master, slave, value) | BOOL | 只写 | 成功 = TRUE |
| 选项码 | DarraEcat_CiA402_GetShutdownOption(master, slave) | int16 | 只读 | 正常 = 真值;读失败 = -32768 (INT16_MIN) |
| 选项码 | DarraEcat_CiA402_SetShutdownOption(master, slave, value) | BOOL | 只写 | 成功 = TRUE |
| 选项码 | DarraEcat_CiA402_GetDisableOperationOption(master, slave) | int16 | 只读 | 正常 = 真值;读失败 = -32768 (INT16_MIN) |
| 选项码 | DarraEcat_CiA402_SetDisableOperationOption(master, slave, value) | BOOL | 只写 | 成功 = TRUE |
| 选项码 | DarraEcat_CiA402_GetHaltOption(master, slave) | int16 | 只读 | 正常 = 真值;读失败 = -32768 (INT16_MIN) |
| 选项码 | DarraEcat_CiA402_SetHaltOption(master, slave, value) | BOOL | 只写 | 成功 = TRUE |
| 选项码 | DarraEcat_CiA402_GetFaultReactionOption(master, slave) | int16 | 只读 | 正常 = 真值;读失败 = -32768 (INT16_MIN) |
| 选项码 | DarraEcat_CiA402_SetFaultReactionOption(master, slave, value) | BOOL | 只写 | 成功 = TRUE |
| 错误 | DarraEcat_CiA402_GetErrorCode(master, slave) | uint16 | 只读 | 正常 = 真值;读失败 = 0xFFFF |
读失败哨兵:三档返回类型各有一个专用哨兵常量,均非合法取值(合法选项码为小值含 0;错误码 0x0000 表无错误)。
DARRA_READ_FAIL_I16= -32768 (INT16_MIN) — 有符号 16 位选项码 Get* (0x605A-0x605E) 读失败DARRA_READ_FAIL_U16= 0xFFFF — 无符号 16 位DarraEcat_CiA402_GetErrorCode(0x603F) 读失败DARRA_READ_FAIL_INT= -1 — 返回int的计数形读取接口(DarraEcat_CiA402_GetErrorHistory/DarraEcat_CiA402_GetSupportedHomingMethods等)读失败整体返回 -1(fail-closed)
判别宏:DARRA_IS_READ_FAIL_I16(v) / DARRA_IS_READ_FAIL_U16(v) / DARRA_IS_READ_FAIL_INT(v)。
哨兵值请勿当作真实数值使用,一律按读取失败处理。int8 方法编号(0x60E3 列表项,-128..-1 为厂商自定义方法)是真实取值,不属哨兵,请勿用判别宏判别。
哨兵成因三态:真值 / 读失败 / 入口缺失,三者互斥。本 SDK 的 C 封装层按序号绑定入口,入口未绑定时按返回类型给兜底值,其中 16 位无符号兜底是 0xFFFF,与 0x603F 的读失败哨兵逐字节相同——单看返回值分不出是「入口没绑到」还是「Core 读失败」。要判成因请先取绑定基线再调 raw 入口,用 CiA402_ReadErrorCode 拿到 darraecat_sentinel_cause_t(真值 / 读失败 / 入口缺失);判定顺序是先看绑定状态,再看值。DARRA_IS_READ_FAIL_* 只认「值等于哨兵」,两种成因会被并成一种,不要拿它单独下结论。
示例:
int16_t qs = DarraEcat_CiA402_GetQuickStopOption(m, 1);
if (DARRA_IS_READ_FAIL_I16(qs)) {
/* 读失败哨兵, 不是真实选项码 */
} else {
/* qs 为真实选项码 */
}
uint16_t ec = DarraEcat_CiA402_GetErrorCode(m, 1);
if (DARRA_IS_READ_FAIL_U16(ec)) {
/* 读失败哨兵, 不是真实错误码 */
}
回零参数
| 对象 | 类型 | 说明 |
|---|---|---|
| 0x6098 | int8 | 回零方法 |
| 0x607C | int32 | 回零偏移 |
| 0x6099:01 | uint32 | 回零搜索速度 |
| 0x6099:02 | uint32 | 回零爬行速度 |
| 0x609A | uint32 | 回零加速度 |
触探功能 (Touch Probe)
配置 Touch Probe
/* 通过 SDO 写 0x60B8 配置 Touch Probe 功能字 */
uint16_t fn = 0x0001; /* Bit0=启用探针1, Bit1=边沿选择 */
dx_sdo_write(master, slave, 0x60B8, 0, FALSE, (uint8_t*)&fn, sizeof(fn));
- 0x60B8 (uint16) — Touch Probe 功能控制(Bit0=启用, Bit1=边沿选择)
- 0x60B9 (uint16) — Touch Probe 状态(只读)
- 0x60BA (int32) — 正边沿捕获位置(只读)
- 0x60BB (int32) — 负边沿捕获位置(只读)
数字 IO
| 对象 | 类型 | 说明 |
|---|---|---|
| 0x60FD | uint32 | 数字输入(只读,32 位位图) |
| 0x60FE:01 | uint32 | 数字输出(读写,32 位位图) |
软件位置限制
| 对象 | 类型 | 说明 |
|---|---|---|
| 0x607D:01 | int32 | 最小位置限制 |
| 0x607D:02 | int32 | 最大位置限制 |
快速运动控制
NewSetpoint(控制字位)
PP 模式发送新定位命令: 写 0x607A 目标位置 + 触发 Controlword Bit4 (NewSetpoint)。relative=TRUE 时同时设置 Bit6 (Relative)。
ClearNewSetpoint(控制字位)
PP 模式清除 NewSetpoint 标志(Controlword Bit4=0)。在 TargetReached (Statusword Bit10=1) 后调用,完成 Set-point Ack 握手。
StartHoming(控制字位)
HM 模式启动回零: 通过 SDO 配置 0x6098 (HomingMethod) / 0x607C (HomeOffset) 后, Controlword Bit4=1 启动。HomingAttained (Statusword Bit12) 表示完成, HomingError (Bit13) 表示错误。
PP / HM 握手由应用通过 PDO/SDO 操作 Controlword 完成,典型流程:
/* PP 模式发送新设定点 */
uint16_t cw = 0x000F; /* Operation Enable */
cw |= 0x0010; /* Bit4: New Setpoint */
if (relative) cw |= 0x0040; /* Bit6: Relative */
CiA402_WriteControlWord(master, slave, cw);
/* TargetReached 后清 Bit4: */
CiA402_WriteControlWord(master, slave, cw & ~0x0010);
/* HM 启动: 通过 SDO 配置 0x6098/0x607C 后, Controlword Bit4=1 启动 */
回零相关参数:
0x6098(int8) — 回零方法 (HomingMethod)0x607C(int32) — 回零偏移 (HomeOffset)
回零状态位 (Statusword):
- Bit 12 — HomingAttained
- Bit 13 — HomingError
驱动器信息
SupportedDriveModes
通过 SDO 0x6502 (uint32) 读取支持的驱动模式位掩码: 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。也可直接调 DarraEcat_CiA402_GetSupportedDriveModes(master, slave)(返回 uint32 掩码)。
IsModeSupported
(SupportedDriveModes >> bit) & 1 即可判断指定模式是否可用;也可直接调 DarraEcat_CiA402_IsModeSupported(master, slave, mode)(返回 BOOL)。
SupportedHomingMethods
int DarraEcat_CiA402_GetSupportedHomingMethods(uint16_t master, uint16_t slave, int8_t* out_methods, int max_count);
通过 SDO 0x60E3 (int8 数组) 读取驱动器支持的回零方法编号列表。subindex 0 为列表长度, 1..N 为各方法编号。
参数:
master(uint16_t) — 主站索引slave(uint16_t) — 从站索引out_methods(int8_t*) — 输出缓冲区,写入方法编号max_count(int) — 输出缓冲区容量,最大写入条目数
返回值:
int— 成功时为实际写入的条目数(0..max_count),失败返回 -1
条目为 int8:-128..-1 为厂商自定义方法,0 为未选,1..35 与 37 为 ETG.6010 标准方法。
三种情形各返什么:
- 失败(SDO 超时 / 通讯异常 / 其它 abort)— 返
-1 - 空集(SI0=0 且读成功,从站真返回 0 条)— 返
0 - 不支持(从站无 0x60E3 或 0x60E3:00,SDO abort 0x06020000 对象不存在 / 0x06090011 子索引不存在)— 返
-1,与失败同档
失败与不支持都按失败处理,禁止当成「支持 0 种回零方法」。本导出读失败整体返回 -1(fail-closed),空集返回 0,两者可分辨,请用 DARRA_IS_READ_FAIL_INT 判别。
示例:
int8_t methods[32];
int n = DarraEcat_CiA402_GetSupportedHomingMethods(master, slave, methods, 32);
if (DARRA_IS_READ_FAIL_INT(n)) {
/* 失败或不支持 0x60E3, 都按失败处理, 不是「支持 0 种」 */
} else if (n == 0) {
/* 空集: 读成功但从站真返回 0 条 */
} else {
printf("支持 %d 种回零方法\n", n);
for (int i = 0; i < n; i++) {
printf(" 方法编号: %d\n", methods[i]);
}
}
TxPDO 数据有效性
通过 SDO 读取 0x603E 判断 TxPDO 数据是否有效。非零表示驱动器 TxPDO 数据不可信,例如编码器未就绪时位置值无意义。
int sz = 0;
char* p = dx_sdo_read(master, slave, 0x603E, 0, FALSE, &sz);
if (p && sz >= 1 && *(uint8_t*)p == 0) {
/* TxPDO 数据有效,可安全使用 */
int32_t pos;
cia402_read_position(master, slave, &map, &pos);
}
if (p) FreeMemory(p);
驱动器信息表
0x6502(uint32) — 支持的驱动模式位掩码(Bit0=PP, Bit7=CSP, Bit8=CSV, Bit9=CST)0x60E3(int8[]) — 支持的回零方法列表0x603E(uint8) — TxPDO 数据有效性(非零=数据无效)
同步功能
| 对象 | 类型 | 访问 | 说明 |
|---|---|---|---|
| 0x60D9:01 | uint16 | 读写 | 同步设置 (SynchronizationSettings),同步使能位掩码 |
| 0x60DA | uint16 | 只读 | 驱动同步状态 (DriveSyncStatus),指示驱动器是否已同步到主站时钟 |
/* 读取驱动器同步状态 */
int sz = 0;
char* p = dx_sdo_read(master, slave, 0x60DA, 0, FALSE, &sz);
if (p && sz >= 2) {
uint16_t sync_status = *(uint16_t*)p;
printf("同步状态: 0x%04X\n", sync_status);
}
if (p) FreeMemory(p);
控制字命令常量
| 常量值 | 说明 |
|---|---|
| 0x0006 | Shutdown — 关机 |
| 0x0007 | Switch On — 开启 |
| 0x000F | Enable Operation — 使能运行 |
| 0x0000 | Disable Voltage — 禁用电压 |
| 0x0002 | Quick Stop — 快速停止 |
| 0x0080 | Fault Reset — 故障复位 |
状态字位掩码常量
| Bit | 掩码 | 说明 |
|---|---|---|
| Bit 0 | 0x0001 | Ready to Switch On |
| Bit 1 | 0x0002 | Switched On |
| Bit 2 | 0x0004 | Operation Enabled |
| Bit 3 | 0x0008 | Fault |
| Bit 4 | 0x0010 | Voltage Enabled |
| Bit 5 | 0x0020 | Quick Stop |
| Bit 7 | 0x0080 | Warning |
| Bit 9 | 0x0200 | Remote |
| Bit 10 | 0x0400 | Target Reached |
| Bit 12 | 0x1000 | Homing Attained / Set-point Ack |
| Bit 13 | 0x2000 | Homing Error / Following Error |
完整示例
#include "ethercat.h"
#include "ethercat_advanced.h"
#include <stdio.h>
int main(int argc, char* argv[])
{
uint16_t master = Initialize();
SetNetwork(master, argv[1], "");
SetStateSequence(master, EC_STATE_OPERATIONAL, 15000);
Start(master);
uint16_t slave = 1;
/* 检查初始状态 */
uint16_t sw = CiA402_ReadStatusWord(master, slave);
cia402_state_t state = CiA402_ParseState(sw);
printf("当前状态: %d (SW=0x%04X)\n", state, sw);
/* 故障复位 */
if (state == CIA402_FAULT) {
CiA402_FaultReset(master, slave);
}
/* 设置 CSP 模式 */
CiA402_SetMode(master, slave, CIA402_CSP);
printf("操作模式: %d\n", CiA402_GetMode(master, slave));
/* 一步使能 */
if (CiA402_Enable(master, slave, 50) != 0) {
printf("驱动使能成功\n");
/* 扫描 PDO 映射 */
cia402_pdo_map_t map;
if (cia402_scan_pdo(master, slave, &map) == 0) {
/* 读取实际位置 */
int32_t actual;
cia402_read_position(master, slave, &map, &actual);
printf("实际位置: %d\n", actual);
/* 写入目标位置 */
cia402_write_target_position(master, slave, &map, actual + 1000);
}
}
getchar();
Stop(master);
Dispose(master);
return 0;
}
PP 模式 — 轮廓位置控制
#include "ethercat.h"
#include "ethercat_advanced.h"
int main(int argc, char* argv[])
{
uint16_t master = Initialize();
SetNetwork(master, argv[1], "");
SetStateSequence(master, EC_STATE_OPERATIONAL, 15000);
Start(master);
uint16_t slave = 1;
/* 设置 PP 模式 */
CiA402_SetMode(master, slave, CIA402_PP);
/* 配置轮廓参数 (SDO) */
uint32_t vel = 10000, acc = 50000, dec = 50000;
dx_sdo_write(master, slave, 0x6081, 0, FALSE, (uint8_t*)&vel, sizeof(vel));
dx_sdo_write(master, slave, 0x6083, 0, FALSE, (uint8_t*)&acc, sizeof(acc));
dx_sdo_write(master, slave, 0x6084, 0, FALSE, (uint8_t*)&dec, sizeof(dec));
/* 使能 */
if (CiA402_Enable(master, slave, 50) != 0) {
printf("驱动使能成功\n");
/* 发送定位命令: 写目标位置 0x607A, 然后 Controlword Bit4=NewSetpoint */
int32_t target = 100000;
dx_sdo_write(master, slave, 0x607A, 0, FALSE, (uint8_t*)&target, sizeof(target));
uint16_t cw = 0x001F; /* Operation Enable + NewSetpoint */
CiA402_WriteControlWord(master, slave, cw);
/* 等待到达 */
uint16_t sw;
do {
sw = CiA402_ReadStatusWord(master, slave);
} while ((sw & 0x0400) == 0); /* 等待 TargetReached (Bit 10) */
printf("目标已到达\n");
CiA402_WriteControlWord(master, slave, cw & ~0x0010); /* 清 NewSetpoint */
}
getchar();
Stop(master);
Dispose(master);
return 0;
}
HM 模式 — 回零
#include "ethercat.h"
int main(int argc, char* argv[])
{
uint16_t master = Initialize();
SetNetwork(master, argv[1], "");
SetStateSequence(master, EC_STATE_OPERATIONAL, 15000);
Start(master);
uint16_t slave = 1;
/* 设置 HM 模式 */
CiA402_SetMode(master, slave, CIA402_HM);
/* 设置回零参数 */
int8_t method = 35; /* 当前位置回零 */
int32_t offset = 0;
uint32_t search_speed = 5000, zero_speed = 500, homing_acc = 10000;
dx_sdo_write(master, slave, 0x6098, 0, FALSE, (uint8_t*)&method, sizeof(method));
dx_sdo_write(master, slave, 0x607C, 0, FALSE, (uint8_t*)&offset, sizeof(offset));
dx_sdo_write(master, slave, 0x6099, 1, FALSE, (uint8_t*)&search_speed, sizeof(search_speed));
dx_sdo_write(master, slave, 0x6099, 2, FALSE, (uint8_t*)&zero_speed, sizeof(zero_speed));
dx_sdo_write(master, slave, 0x609A, 0, FALSE, (uint8_t*)&homing_acc, sizeof(homing_acc));
/* 使能 */
if (CiA402_Enable(master, slave, 50) != 0) {
printf("驱动使能成功,开始回零...\n");
/* 启动回零: Controlword Bit4=Start Homing */
CiA402_WriteControlWord(master, slave, 0x001F);
/* 等待回零完成 */
uint16_t sw;
do {
sw = CiA402_ReadStatusWord(master, slave);
if (sw & 0x2000) { /* Bit 13: HomingError */
printf("回零错误!\n");
break;
}
} while ((sw & 0x1000) == 0); /* Bit 12: HomingAttained */
if (sw & 0x1000) {
printf("回零完成\n");
}
}
getchar();
Stop(master);
Dispose(master);
return 0;
}