过程数据对象PDO
PDO一般用于实时数据更新;其分为接收PDO(RxPDO)和发送PDO(TxPDO),前者的数据流方向是主站到从站,TxPDO是从站到主站。
PDO功能支持同步周期的刷新方式,也支持非周期性的更新方式。当主站选择为分布式时钟同步模式时,PDO将同步周期更新;如果选择自由运行模式,那么PDO数据的更新是非周期性的。
过程数据可以包含多个PDO映射数据对象,COE协议使用数据对象0x1C10-0x1C2F定义相应的SM通道的PDO映射对象列表,以TxPDO为例,输出通道使用SM2通道,由对象数据0x1C12定义PDO分配,如下图所示,
PDO映射
通过PDO映射,可实现映射对象的实时传输。PDO映射内容的格式如下表,
表1 PDO映射内容的格式
位 | 31~16 | 15~8 | 7~0 |
内容 | 映射内容的索引 | 映射内容的子索引 | 位长(16进制) |
例子 | 6040h | 00h | 10h |
一款Ethercat驱动器的默认PDO映射(与XML文件一致),如下表所示,
PDO映射对象索引 | PDO映射对象子索引 | 映射内容 | 映射内容名称 |
RXPDO1 1600h | 01h | 60400010 | 控制字 |
02h | 607a0020 | 目标位置 | |
03h | 60b80020 | 探针功能 | |
RXPDO2 1601h | 01h | 60400010 | 控制字 |
02h | 60ff0020 | 目标速度 | |
03h | 60b20010 | 转矩前馈 | |
RXPDO3 1602h | 01h | 60400010 | 控制字 |
02h | 60710010 | 目标转矩 | |
03h | 60870020 | 转矩变量率 | |
RXPDO4 1603h | 01h | 60400010 | 控制字 |
02h | 60980008 | 原点方法 | |
03h | 60990120 | 原点速度(快) | |
04h | 60990220 | 原点速度(慢) | |
05h | 609a0020 | 原点加减速 | |
06h | 607c0020 | 原点偏移 | |
07h | 60600008 | 操作模式 | |
TXPDO1 1A00h | 01h | 603f0000 | 错误码 |
02h | 60410000 | 状态字 | |
03h | 60610000 | 显示操作模式 | |
04h | 60640000 | 实际位置 | |
05h | 60b90020 | 探针状态 | |
06h | 60ba0020 | 探针1上升沿位置 | |
07h | 60fd0020 | 数字输入 | |
TXPDO2 1A01h | 暂无默认映射 |
PDO动态映射设置过程
将Ethercat状态机切换到PreOP状态,此状态可以用SDO来配置PDO映射;
清除PDO指定对象的PDO映射对象,即设置0x1C12-00,与0x1C13-00为0;
PDO映射对象无效,即对0x1600-0x1603/0x1A00-0x1A01的子索引设置为0;
重新配置PDO映射内容;0x1600-01开始的是RxPDO内容,0x1A00-01开始的是TxPDO;
设置PDO映射对象总数;
写有效的PDO映射对象索引到PDO指定对象
设置PDO指定对象的总个数,即将映射对象个数写入到1C12-00h和1C13-00h
转换Ethercat状态机到安全操作以上,配置的PDO映射将有效。
下面的配置PDO映射例子代码,第一步与最后一步没有。
设置PDO映射表示例代码
static int drive_write8(uint16 slave, uint16 index, uint8 subindex, uint8 value)
{
int wkc;
wkc = ec_SDOwrite(slave, index, subindex, FALSE, sizeof(value), &value, EC_TIMEOUTRXM);
return wkc;
}
static int drive_write16(uint16 slave, uint16 index, uint8 subindex, uint16 value)
{
int wkc;
wkc = ec_SDOwrite(slave, index, subindex, FALSE, sizeof(value), &value, EC_TIMEOUTRXM);
return wkc;
}
static int drive_write32(uint16 slave, uint16 index, uint8 subindex, int32 value)
{
int wkc;
wkc = ec_SDOwrite(slave, index, subindex, FALSE, sizeof(value), &value, EC_TIMEOUTRXM);
return wkc;
}
// 该函数用于设置PDO映射表
int drive_setup(uint16 slave)
{
int wkc = 0;
printf("Drive setup\n");
wkc += drive_write16(slave, 0x1C12, 0, 0);
wkc += drive_write16(slave, 0x1C13, 0, 0);
wkc += drive_write16(slave, 0x1A00, 0, 0);
wkc += drive_write32(slave, 0x1A00, 1, 0x60410010); // Statusword
wkc += drive_write32(slave, 0x1A00, 2, 0x60640020); // Position actual value
wkc += drive_write32(slave, 0x1A00, 3, 0x606C0020); // Velocity actual value
wkc += drive_write32(slave, 0x1A00, 4, 0x60770010); // Torque actual value
wkc += drive_write32(slave, 0x1A00, 5, 0x60610008); // Modes of operation display
wkc += drive_write32(slave, 0x1A00, 6, 0x230A0020); // 2nd Pos
wkc += drive_write8(slave, 0x1A00, 0, 6);
wkc += drive_write8(slave, 0x1600, 0, 0);
wkc += drive_write32(slave, 0x1600, 1, 0x60400010); // Controlword
wkc += drive_write32(slave, 0x1600, 2, 0x60710010); // Target torque
wkc += drive_write32(slave, 0x1600, 3, 0x607A0020); // Target position
wkc += drive_write32(slave, 0x1600, 4, 0x60FF0020); // Target velocity
wkc += drive_write32(slave, 0x1600, 5, 0x60600008); // Modes of operation display
wkc += drive_write32(slave, 0x1600, 6, 0x60B20010); // Torque offset
wkc += drive_write8(slave, 0x1600, 0, 6);
wkc += drive_write16(slave, 0x1C12, 1, 0x1600);
wkc += drive_write8(slave, 0x1C12, 0, 1);
wkc += drive_write16(slave, 0x1C13, 1, 0x1A00);
wkc += drive_write8(slave, 0x1C13, 0, 1);
strncpy(ec_slave[slave].name, "Drive", EC_MAXNAME);
if (wkc != 22)
{
printf("Drive %d setup failed\nwkc: %d\n", slave, wkc);
return -1;
}
else
printf("Drive %d setup succeed.\n", slave);
return 0;
}