跳到主要内容

Slave API

通过 master[n]master.slave(n) 访问(1-based 索引)。

快速开始

索引访问

slave = master[1]                 # 第1个从站(1-based 索引)
slave = master.slave(1) # 等效写法
count = master.slave_count # 从站总数

组访问

servo = master.groups[0][0]       # 默认组第1个从站
io = master.groups[1][2] # 组1第3个从站
group_count = len(master.groups[1]) # 组1从站数
提示

组相关属性详见 从站分组

地址访问

# 物理配置地址(自动分配)
addr = slave.config_addr # 如 0x1001

# 别名地址(EEPROM 中配置,可选)
alias = slave.alias_address

# 按地址查找
target = next((s for s in master.slaves if s.config_addr == 0x1001), None)

标识访问

name = slave.name                 # 设备名称
drive_name = slave.drive_name # 驱动名称(SDO 0x1008)
vendor_id = slave.vendor_id # 厂商 ID
product_id = slave.product_id # 产品 ID
revision = slave.rev_id # 修订号
serial = slave.serial_number # 序列号

# 按名称查找
target = next((s for s in master.slaves if s.name == "EL2008"), None)

协议访问

协议属性说明
PDOslave.pdo过程数据对象,实时 IO 数据读写
CoEslave.coeCANopen over EtherCAT,SDO 对象字典访问
CiA 402slave.cia402 / CiA402Advanced伺服驱动器协议,状态机管理与使能控制
MDPslave.mdp模块化设备协议,模块检测与自动配置
SoEslave.soeServo over EtherCAT,伺服驱动器参数
FoEslave.foeFile over EtherCAT,文件传输
EoEslave.eoeEthernet over EtherCAT,以太网隧道
AoEslave.aoeADS over EtherCAT,Beckhoff ADS 协议
VoEslave.voeVendor over EtherCAT,厂商特定协议
FSoEslave.fsoeFunctional Safety over EtherCAT,功能安全协议

PDO 数据读写

详细的 PDO 读写方式请参见 PDO 输入输出

推荐方式 — 结构体映射 (零拷贝):

import ctypes

class ServoInput(ctypes.Structure):
_pack_ = 1
_fields_ = [
("status_word", ctypes.c_uint16),
("actual_position", ctypes.c_int32),
("actual_velocity", ctypes.c_int32),
]

input_ref = slave.pdo.bind_pdo_struct(ServoInput, is_input=True)
if input_ref:
print(f"当前位置: {input_ref.actual_position}")

EMCY 紧急消息

EtherCAT 从站在检测到异常时会发送 EMCY (Emergency) 紧急消息。通过 slave.coe 访问, 详见 CoE — EMCY 紧急消息

# 获取紧急消息历史
history = slave.coe.get_emergency_history()
for msg in history:
print(f"错误码: 0x{msg.error_code:04X}, 寄存器: 0x{msg.error_register:02X}")

# 清除紧急消息历史
slave.coe.clear_emergency_history()

拓扑查询

通过从站的 children 属性获取子从站列表, 实现拓扑树的遍历。

# 获取从站的子从站
children = slave.children

# 遍历拓扑树
def print_tree(s, depth):
indent = " " * depth
print(f"{indent}[{s.slave_num}] {s.name}")
for child in s.children:
print_tree(child, depth + 1)

for s in master.slaves:
if s.topology == 1 or s.parent_station == 0:
print_tree(s, 0)