翻译soem的 tutorial.txt 文件

tutorial.txt File Reference

Detailed Description

General

The SOEM is a library that provides the user application with the means to send and receive EtherCAT frames. It is up to the application to provide means for:

  • Reading and writing process data to be sent/received by SOEM
  • Keeping local IO data synchronized with the global IOmap
  • Detecting errors reported by SOEM
  • Managing errors reported by SOEM

The following sections show some basic examples on how to get the SOEM up and running, as well as making use of the process data and checking for errors. Since all code is local to the application or global variables, it is possible to tweak and optimize when possible.

The following example shows how to add a main function that will be called by startup code. In this example main's only purpose is to spawn a new task that executes SOEM.

 

SOEM是一个库,可为用户应用程序提供发送和接收EtherCAT帧的方法。 由应用程序提供以下方法:

  • 读写由SOEM发送/接收的过程数据
  • 使本地IO数据与全局IOmap保持同步
  • 检测SOEM报告的错误
  • 管理SOEM报告的错误

以下各节展示了一些的基本示例,关于如何启动和运行SOEM以及如何使用过程数据和检查错误。 由于所有代码都是应用程序局部变量或全局变量局部变量,因此可以在可能时进行调整和优化。

 

下面的示例演示如何添加将由启动代码调用的主要功能。 在此示例中,main的唯一目的是产生一个执行SOEM的新任务。

 

int main (void)

{

rprintp("SOEM (Simple Open EtherCAT Master)\nSimple test\n");

task_spawn ("simpletest", simpletest, 9, 8192, NULL);

Configuration

Followed by start of the application we need to set up the NIC to be used as EtherCAT Ethernet interface. In a simple setup we call ec_init(ifname) and if SOEM comes with support for cable redundancy we call ec_init_redundant that will open a second port as backup. You can send NULL as ifname if you have a dedicated NIC selected in the nicdrv.c. It returns >0 if succeeded.

在启动应用程序之后,我们需要设置NIC用作EtherCAT以太网接口。 在简单的设置中,我们调用ec_init(ifname),如果SOEM附带对电缆冗余的支持,我们将调用ec_init_redundant,它将打开第二个端口作为备份。 如果您在nicdrv.c中选择了专用的NIC,则可以将ifname作为NULL发送。 如果成功,则返回> 0。

/* initialise SOEM, bind socket to ifname */

if (ec_init(ifname) > 0)

 

SOEM is a light weight ethercat master library used in embedded systems, It supports only runtime configuration. It requests a BRD (Broad Cast Read) of address 0, all fully functional slaves in the network will respond to this request, and therefore we will get a working counter equal to the number of slaves in the network. ec_config_init also sets up the mailboxes for slaves that support it. When ec_config_init finishes it will have requested all slaves to state PRE_OP. All data read and configured are stored in a global array which acts as a placeholder for key values, consult ec_slave for detailed information.

SOEM是嵌入式系统中使用的轻量级ethercat主机库,它仅支持运行时配置。 它请求地址为0的BRD(广播类型读取),网络中所有功能完备的从站都将对此请求做出响应,因此我们将获得一个与网络中的从站数量相等的工作计数器( 从站数量 == 工作计数器)。 ec_config_init还会为支持它的从站设置邮箱。 当ec_config_init完成时,它将请求所有从站声明PRE_OP。 读取和配置的所有数据都存储在全局数组中,该数组充当键值的占位符,有关详细信息,请参阅ec_slave。

/* find and auto-config slaves */

if ( ec_config_init(FALSE) > 0 )

{

rprintp("%d slaves found and configured.\n",ec_slavecount);

 

SOEM has now discovered and configured the network it is connected to. Now we can verify that all slaves are present as expected. These definitions could be generated by an external tool in an offline .h file. The definitions could be replaced by a struct keeping slave number.

现在,SOEM已发现并配置了与其连接的网络。 现在,我们可以验证所有从站都按预期存在。 这些定义可以由外部工具在 offline.h文件中生成。 可以用保留从站号的结构代替定义。

#define EK1100_1 1

#define EL4001_1 2

...

#define EL2622_3 8

#define EL2622_4 9

#define NUMBER_OF_SLAVES 9

snippet

...

uint32 network_configuration(void)

{

/* Do we got expected number of slaves from config */

if (ec_slavecount < NUMBER_OF_SLAVES)

return 0;

/* Verify slave by slave that it is correct*/

if (strcmp(ec_slave[EK1100_1].name,"EK1100"))

return 0;

else if (strcmp(ec_slave[EL4001_1].name,"EL4001"))

return 0;

...

else if (strcmp(ec_slave[EL2622_4].name,"EL2622"))

return 0;

return 1;

}

simpletest

...

if (network_configuration())

...

else

rprintp("Mismatch of network units!\n");

 

We now have the network up and configured. Mailboxes are up for slaves that support it. Next we will create an IOmap and configure the SyncManager's and FMMU's to link the EtherCAT master and the slaves. The IO mapping is done automatically, SOEM strives to keep the logical process image as compact as possible. It is done by trying to fit Bit oriented slaves together in single bytes. Below is an example of 8 slaves and how they are ordered. During mapping SOEM also calculates an expected WKC for the IO mapped together. That is the primary key to detect errors.

  • Outputs are placed together in the beginning of the IOmap
  • Inputs follow

When the mapping is done SOEM requests slaves to enter SAFE_OP.

现在,我们已经建立并配置了网络。 邮箱用于支持它的从机。 接下来,我们将创建一个IOmap并配置SyncManager和FMMU来链接EtherCAT主站和从站。 IO映射是自动完成的,SOEM努力使逻辑过程映像保持尽可能的紧凑。 通过尝试将面向位的从站装配到单个字节中来完成此操作。 以下是8个从站的例子及他们是如何排序的。 在映射期间,SOEM还为映射在一起的IO计算预期的WKC。 这是检测错误的主要关键。

  • 输出放置在IOmap的开头
  • 输入紧跟输出(也就是:先输出,然后再输入)

映射完成后,SOEM请求从站输入SAFE_OP。

char IOmap[128];

int usedmem;

...

usedmem = ec_config_map(&IOmap);

if (usedmem <= sizeof(IOmap))

...

memory layout, mapping between physical and logical

 

To enter state OP we need to send valid data to outputs. The EtherCAT frame handling is split into ec_send_processdata and ec_receive_processdata.

  • ec_send_processdata sends the frame on the NIC and saves the frame on the stack for receive to fetch.
  • ec_receive_processdata(EC_TIMEOUTRET) tries to fetch the frames on the stack. We send an argument for how long we will try to fetch the frame. ec_receive_processdata returns the working counter.

为了进入状态OP,我们需要将有效数据发送到输出。 EtherCAT帧处理分为ec_send_processdata和ec_receive_processdata。

  • ec_send_processdata 在NIC上发送该帧,并将该帧保存在堆栈中,以供接收和提取。
  • ec_receive_processdata(EC_TIMEOUTRET)尝试获取堆栈上的帧。 我们发送一个参数说明将尝试获取帧多长时间。 ec_receive_processdata 返回工作计数器。

/* send one valid process data to make outputs in slaves happy*/

ec_send_processdata();

wkc = ec_receive_processdata(EC_TIMEOUTRET);

...

ec_writestate(0);

/* wait for all slaves to reach OP state */

ec_statecheck(0, EC_STATE_OPERATIONAL, EC_TIMEOUTSTATE);

 

  • Now we have a system up and running, all slaves are in state operational.
  • 现在我们的系统已启动并正在运行,所有从站都处于运行状态。

 

Custom Configuration(自定义配置)

PDO Assign and PDO Config(PDO分配和PDO配置)

Do custom configuration with PDO Assign or PDO Config. SOEM support custom configuration during start via a PreOP to SafeOP configuration hook. It can be done per slave and should be set before calling the configuration and mapping of process data, e.g. the call to ec_config_map. Setting the configuration hook ensure that the custom configuration will be applied when calling recover and re-configuration of a slave, as described below.

使用PDO Assign或PDO Config进行自定义配置。 SOEM在启动过程中通过从PreOP到SafeOP配置挂钩支持自定义配置。 可以针对每个从站完成此操作,应在调用过程数据的配置和映射之前进行设置,例如 调用ec_config_map。 设置配置挂钩可确保在调用从站的恢复和重新配置时将应用自定义配置,如下所述。

int EL7031setup(uint16 slave)

{

int retval;

uint16 u16val;

retval = 0;

/* Map velocity PDO assignment via Complete Access*/

uint16 map_1c12[4] = {0x0003, 0x1601, 0x1602, 0x1604};

uint16 map_1c13[3] = {0x0002, 0x1a01, 0x1a03};

retval += ec_SDOwrite(slave, 0x1c12, 0x00, TRUE, sizeof(map_1c12), &map_1c12, EC_TIMEOUTSAFE);

retval += ec_SDOwrite(slave, 0x1c13, 0x00, TRUE, sizeof(map_1c13), &map_1c13, EC_TIMEOUTSAFE);

/* set some motor parameters, just as example */

u16val = 1200; // max motor current in mA

retval += ec_SDOwrite(slave, 0x8010, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTSAFE);

u16val = 150; // motor coil resistance in 0.01ohm

retval += ec_SDOwrite(slave, 0x8010, 0x04, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTSAFE);

/* set other necessary parameters as needed */

...

printf("EL7031 slave %d set, retval = %d\n", slave, retval);

return 1;

}

void simpletest(char *ifname)

{

...

/* Detect slave beckhoff EL7031 from vendor ID and product code */

if((ec_slave[slc].eep_man == 0x00000002) && (ec_slave[slc].eep_id == 0x1b773052))

{

printf("Found %s at position %d\n", ec_slave[slc].name, slc);

/* link slave specific setup to preop->safeop hook */

ec_slave[slc].PO2SOconfig = EL7031setup;

}

...

Legacy versus overlapping IOmap

传统与重叠IOmap

IOmap options legacy versus overlapping. Overlapping IOmap was introduced to handle the TI ESC that doesn't support RW access to non-interleaved input and output process data of multiple slaves. The difference is that legacy IOmapping will send IOmap as is on the EtherCAT network while the overlapping will re-use logic addressing per slave to replace RxPDO process data coming from the Master with TxPDO process data generated by the slave sent back to the master.

IOmap选项是传统还是重叠。 引入了IOmap重叠来处理TI ESC,该ESC不支持对多个从站的非交错输入和输出过程数据进行RW访问。 区别在于,传统IO映射将按EtherCAT网络上的原样发送IOmap,而重叠将重用每个从站的逻辑寻址,用从站发送回主站的TxPDO过程数据替换来自主站的RxPDO过程数据。

Overview of legacy pdo map

传统的PDO映射概述

Legacy IOmapping

 

Overview of overlapping pdo map

重叠pdo映射预览

Overlapping IOmapping

EtherCAT slave groups

EtherCAT从站组

Slave groups can be used to group slaves into separate logic groups within an EtherCAT network. Each group will have its own logic address space mapped to an IOmap address and make it possible to send and receive process data at different update rate.

Below is an example on how to assign a slave to a group. OBS! A slave can only be member in one group.

从站组可用于将从站分为EtherCAT网络内的单独逻辑组。 每个组都有自己的逻辑地址空间,映射到IOmap地址,并可以以不同的更新速率发送和接收过程数据。

以下是有关如何将从站分配到组的示例。 注意! 一个从站只能是一个组的成员。

for (cnt = 1; cnt <= ec_slavecount; cnt++)

{

if ( <some condition> )

{

ec_slave[cnt].group = X;

}

else

{

ec_slave[cnt].group = Y;

}

}

Alternative 1, configure all slave groups at once, call ec_config_map or ec_config_map_group with arg 0. This option will share IOmap and store the group IOmap data at offset EC_LOGGROUPOFFSET.

备选方案1,一次配置所有从站组,调用ec_config_map或ec_config_map_group函数时使用arg 0(也就是调用函数时传递的参数为0)。此选项将共享IOmap并将组IOmap数据存储在偏移EC_LOGGROUPOFFSET处。

ec_config_map_group(&IOmap, 0);

 

Alternative 2, configure the slave groups one by one, call ec_config_map or ec_config_map_group with arg X, Y. This option will use different, supplied by the user, IOmaps.

备选方案2,逐个配置从站组,并调用ec_config_map或ec_config_map_group时传递参数X,Y。此选项将使用不同的,由用户,IOmaps提供。

ec_config_map_group(&IOmap1, X);

ec_config_map_group(&IOmap2, Y);

To exchange process data for given group(s) the user must call send/recv process data per group. The send and receive stack of process data don't consider groups, so the application has to send and receive the process data for one group before sending/receiving process data for another group.

要交换给定组的过程数据,用户必须为每个组调用发送/接收过程数据。 过程数据的发送和接收堆栈不考虑组,因此应用程序必须在发送/接收另一组的过程数据之前发送和接收一个组的过程数据。

ec_send_processdata_group(X);

ec_receive_processdata_group(X, EC_TIMEOUTRET);

ec_send_processdata_group(Y);

ec_receive_processdata_group(Y, EC_TIMEOUTRET);

Application 应用

Accessing data through IOmap 通过IOmap访问数据

IOmap is the fastest mechanism for accessing slaves' IO data. Using this mechanism, the ec_slave struct keeps pointers to the start byte in the IO map on slave level together with start bit within the start byte. This way we can bit mask IO on bit level even though SOEM has combined slave data to minimize the frame size to be sent. We'll use slave 8 in the picture above as an example. From a printout from ec_slave we have the following:

IOmap是访问从站IO数据的最快机制。使用这种机制,ec_slave结构将指针保持在从设备级别的IO映射中的起始字节以及起始字节内的起始位。这样,即使SOEM已合并从机数据以最小化要发送的帧大小,我们也可以在位级别上对IO进行位掩码。我们以上图中的slave 8为例。从ec_slave的打印输出中,我们可以看到以下内容:

  • Slave:8
    • Name:EL2622
    • Output size: 2bits
    • Input size: 0bits
    • Configured address: 1008
    • Outputs address: 18cf6
    • Inputs address: 0
    • FMMU0 Ls:2 Ll: 1 Lsb:4 Leb:5 Ps:f00 Psb:0 Ty:2 Act:1

The Outputs address: 18cf6 is the pointer to slave 8's start byte. The FMMU's Lsb:4 (LogicalStartBit) = ec_slave.Ostartbit telling us how to mask for the individual bits in the combined byte. The same goes for byte addressed slaves, but byte slaves only need the byte start address since they are byte aligned, the start bit will be 0.

Some example on how to access different types of data

Set an output int 16 value when memory alignment needs to be considered, arguments is:

输出地址:18cf6是指向从站8的起始字节的指针。 FMMU的Lsb:4(LogicalStartBit)= ec_slave.Ostartbit 告诉我们如何屏蔽组合字节中的各个位。 字节寻址从设备也是如此,但是字节从设备仅需要字节起始地址,因为它们是字节对齐的,起始位将为0。

有关如何访问不同类型数据的一些示例

当需要考虑内存对齐时,设置输出int 16值,参数为:

  • slave number in ethercat network / ethercat网络中的从站号
  • module index as index internal to the slave in case more than one channel / 如果有多个通道,则将模块索引作为从站内部的索引
  • value to write / 要写的值

#define EL4001_1 2

...

void set_output_int16 (uint16 slave_no, uint8 module_index, int16 value)

{

uint8 *data_ptr;

data_ptr = ec_slave[slave_no].outputs;

/* Move pointer to correct module index*/

data_ptr += module_index * 2;

/* Read value byte by byte since all targets can't handle misaligned

* addresses

*/

*data_ptr++ = (value >> 0) & 0xFF;

*data_ptr++ = (value >> 8) & 0xFF;

}

...

set_output_int16(EL4001_1,0,slave_EL4001_1.out1);

 

Target can handle non aligned pointers to the IOmap

目标可以处理未对齐的IOmap指针

typedef struct PACKED

{

int16 outvalue1;

int16 outvalue2;

} out_EL4132t;

out_EL4132t *out_EL4132;

...

/* connect struct pointers to slave I/O pointers */

out_EL4132 = (out_EL4132t*) ec_slave[3].outputs;

out_EL4132->outvalue2 = 0x3FFF;

...

 

Identify and manage errors. The key is the Working Counter, CRC errors and errors local to the slave causing a state change can be detected by loss of Working Counter since the syncmanagers won't get updated. When returning Working Counter don't match Expected Working Counter something is wrong, then it is up to an error handler to act, locate the erroneous slave and decide what action to perform. The error may not be fatal. Some basic code from simple_test.

识别和管理错误。 关键是工作计数器,由于同步管理器不会更新,因此可以通过丢失工作计数器来检测CRC错误和从站本地导致状态更改的错误。 当返回工作计数器与预期工作计数器不匹配时,出现了问题,这取决于错误处理程序采取行动,找到错误的从属并决定要执行的操作。 该错误可能不是致命的。 一些来自simple_test的基本代码。

wkc = ec_receive_processdata(EC_TIMEOUTRET);

expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;

if( inOP && ((wkc < expectedWKC) || ec_group[currentgroup].docheckstate))

{

if (needlf)

{

needlf = FALSE;

printf("\n");

}

/* one ore more slaves are not responding */

ec_group[currentgroup].docheckstate = FALSE;

ec_readstate();

for (slave = 1; slave <= ec_slavecount; slave++)

{

if ((ec_slave[slave].group == currentgroup) && (ec_slave[slave].state != EC_STATE_OPERATIONAL))

{

ec_group[currentgroup].docheckstate = TRUE;

if (ec_slave[slave].state == (EC_STATE_SAFE_OP + EC_STATE_ERROR))

{

printf("ERROR : slave %d is in SAFE_OP + ERROR, attempting ack.\n", slave);

ec_slave[slave].state = (EC_STATE_SAFE_OP + EC_STATE_ACK);

ec_writestate(slave);

}

else if(ec_slave[slave].state == EC_STATE_SAFE_OP)

{

printf("WARNING : slave %d is in SAFE_OP, change to OPERATIONAL.\n", slave);

ec_slave[slave].state = EC_STATE_OPERATIONAL;

ec_writestate(slave);

}

else if(ec_slave[slave].state > EC_STATE_NONE)

{

if (ec_reconfig_slave(slave, EC_TIMEOUTMON))

{

ec_slave[slave].islost = FALSE;

printf("MESSAGE : slave %d reconfigured\n",slave);

}

}

else if(!ec_slave[slave].islost)

{

/* re-check state */

ec_statecheck(slave, EC_STATE_OPERATIONAL, EC_TIMEOUTRET);

if (ec_slave[slave].state == EC_STATE_NONE)

{

ec_slave[slave].islost = TRUE;

printf("ERROR : slave %d lost\n",slave);

}

}

}

if (ec_slave[slave].islost)

{

if(ec_slave[slave].state == EC_STATE_NONE)

{

if (ec_recover_slave(slave, EC_TIMEOUTMON))

{

ec_slave[slave].islost = FALSE;

printf("MESSAGE : slave %d recovered\n",slave);

}

}

else

{

ec_slave[slave].islost = FALSE;

printf("MESSAGE : slave %d found\n",slave);

}

}

}

if(!ec_group[currentgroup].docheckstate)

printf("OK : all slaves resumed OPERATIONAL.\n");

}

Accessing SDOs and PDOs 访问SDOs和PDOs

There are multiple ways a slave can communicate with the master. CANopen over EtherCAT (CoE) is a (slow but flexible) asynchronous mechanism for transferring data via mailboxes.

SOEM provides the ecx_SDOread() and ecx_SDOwrite() functions for reading and writing a CoE SDO (Service Data Object) given the corresponding index and subindex.

SOEM does not provide specific functions for accessing CoE PDOs (Process Data Objects). On most slaves, however, it is possible to use the same functions available for SDOs. In the seldom case in which the PDO object has been marked in the CoE dictionary as "PDO only", only IOmap access is allowed. Note that a list of the PDO mappings can be retrieved through the "slaveinfo <interface> -map" command.

从站可以通过多种方式与主站进行通信。 EtherCAT上的CANopen(CoE)是一种(缓慢但灵活的)异步机制,用于通过邮箱传输数据。

SOEM提供了 ecx_SDOread() 和 ecx_SDOwrite() 函数,用于在给定相应的索引和子索引的情况下读写CoE SDO(服务数据对象)。

SOEM不提供用于访问CoE PDO(过程数据对象)的特定功能。 但是,在大多数从站上,可以使用与SDO相同的功能。 在极少数情况下,在CoE词典中将PDO对象标记为“仅PDO”时,仅允许IOmap访问。 请注意,可以通过“ slaveinfo <interface> -map”命令检索PDO映射的列表。

 

原文:

https://openethercatsociety.github.io/doc/soem/tutorial_8txt.html

本人能力有限,如有翻译不当之处,请指出,谢谢!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值