Appearance
概念介绍
在EtherCAT(以太网控制自动化技术)中,设备的状态管理通过不同的操作状态来实现,主要包括Pre-Operational(PreOp)、Safe-Operational(SafeOp)和Operational(Op)三种状态。
具体而言,存在以下的转换:
PreOp → SafeOp: 当设备完成初始化和配置后,主站可以将其状态从 PreOp 切换到 SafeOp,以进行安全相关的数据交换。
SafeOp → Op: 当系统确认安全条件满足后,主站可以将设备状态从 SafeOp 切换到 Op,进入全功能操作状态。
Op → SafeOp/PreOp: 在需要重新配置或出现故障时,主站可以将设备状态从 Op 切换回 SafeOp 或 PreOp。
C++
开源主机方案: SOEM,需要指出的是SOEM的运行需要ROOT权限
bash
git clone https://github.com/OpenEtherCATsociety/SOEM.git
cd SOEM
mkdir build
cd build
cmake ..
make
cd test/linux/simple_test
./simple_test eth0 # 填主站连接的网卡名
Python
SOEM有一个python封装库,可以用python实现ethercat通信
bash
# 安装
pip install pysoem
函数介绍
其核心的类方法介绍如下:
python
import pysoem
master = pysoem.Master() # 创建一个master对象
master.open('eth0') # 打开指定网卡开始通信
master.config_init() # 返回找到的从站数量
master.config_dc() # 定位DC从机,测量传播延迟,返回值为bool型,表示是否找到了DC从机
master.config_map() # 配置所有从站的PDO映射. PREOP -> SAFEOP - each slave's config_func is called. returns IO map size (sum of all PDO in an out data)
master.state_check(pysoem.SAFEOP_STATE, 50000) # 检查从站是否进入 SAFEOP 状态
master.state = pysoem.OP_STATE # 将主站state属性设置为Op
master.write_state() # Write all slaves state
master.state_check(pysoem.OP_STATE, 50000) # 检查从站是否进入 OP 状态. returns Requested state, or found state after timeout
master.read_state() # 读取所有从站的状态,返回发现的最低状态
master.send_processdata() # 发送过程数据到从站
master.receive_processdata(2000) # 从从站接收过程数据。
master.slaves() # Gets a list of the slaves found during config_init. The slave instances are of type CdefSlave.
slave = master.slaves[slave_pos] # 获取索引为slave_pos的从站对象
slave.sdo_write(index, subindex, data, ca=False) # Write to a CoE object.
slave.id # Product Code of the slave, read out from the slaves SII during config_init.
slave.man # Vendor ID of the slave, read out from the slaves SII during config_init.
slave.config_func # Slaves callback function that is called during config_map. When the state changes from Pre-Operational state to Operational state.
master.close() # 关闭通信
代码展示
基础代码展示
python
import pysoem
master = pysoem.Master()
master.open('eth0')
master.config_dc()
if master.config_init() > 0:
master.config_map()
for slave in master.slaves:
print(f"slave name is {slave.name}")
print(f"slave state is {slave.state}")
print(f"slave id is {slave.id}")
master.state_check(pysoem.SAFEOP_STATE, 50000)
master.state_check(pysoem.OP_STATE, 50000)
master.write_state()
master.send_processdata()
master.receive_processdata(2000)
slave = master.slaves[0]
# print(slave.input)
else:
print("No slaves found")
master.state = pysoem.INIT_STATE
master.write_state()
master.close()
实操案例
以下是一个16通道EtherCAT变送器的代码展示
python
import pysoem
import time
import csv
from datetime import datetime
master = pysoem.Master()
master.open('eth0')
master.config_dc()
if master.config_init() > 0:
master.config_map()
for slave in master.slaves:
print(f"slave name is {slave.name}")
print(f"slave state is {slave.state}")
print(f"slave id is {slave.id}")
master.state_check(pysoem.SAFEOP_STATE, 50000)
master.state_check(pysoem.OP_STATE, 50000)
master.write_state()
master.in_op = True
with open('output.csv', 'w', newline='') as csvfile:
csvwriter = csv.writer(csvfile)
# 写入 CSV 文件的表头
csvwriter.writerow(['Timestamp'] + [f'NET_{i}' for i in range(1, 17)])
try:
while True:
master.send_processdata()
master.receive_processdata(2000)
# 读取 TxPDO 数据
slave = master.slaves[0]
# 假设 NET_1 到 NET_16 每个数据占用 4 字节 (32 位)
data_offset = 0
data_length = 4
# 获取当前时间戳
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
row_data = [timestamp]
for i in range(1, 17):
data_end = data_offset + data_length
value = int.from_bytes(slave.input[data_offset:data_end], byteorder='little', signed=True)
print(f"NET_{i}: {value}")
row_data.append(value)
data_offset += data_length
csvwriter.writerow(row_data)
# 添加一个小延迟以避免 CPU 占用过高
time.sleep(0.01)
except KeyboardInterrupt:
print("KeyboardInterrupt")
# print(slave.input)
finally:
master.state = pysoem.INIT_STATE
master.write_state()
master.close()