桑福生物科技网站开发,网站怎么做会被收录,做公司官网需要什么条件,自学ui设计一般学多久手边有一套正点原子linux开发板imax6ul#xff0c;一直在吃灰#xff0c;周末业余时间无聊#xff0c;把EtherCAT的开源IGH主站移植到开发板上玩玩儿#xff0c;搞点事情做。顺便学习研究下EtherCAT总线协议及其对伺服驱动器的运动控制过程。实验很有意思#xff0c;这里总… 手边有一套正点原子linux开发板imax6ul一直在吃灰周末业余时间无聊把EtherCAT的开源IGH主站移植到开发板上玩玩儿搞点事情做。顺便学习研究下EtherCAT总线协议及其对伺服驱动器的运动控制过程。实验很有意思这里总结下实验过程分享给有需要的小伙伴。 前言
igh EtherCAT Master是一个用于控制EtherCAT网络的软件模块它提供了主站功能。主站负责与从站进行通信和同步控制从站的操作。igh EtherCAT Master具有丰富的功能和灵活的配置选项可以满足不同应用场景的需求。它提供了一系列的API和工具使得开发者可以方便地进行EtherCAT网络的开发和调试。
igh EtherCAT Master是用的最多且实时性最好的 EtherCAT 开源主站。很多公司项目软件主站都是用的它有很多软件专利可以挖掘。一些公司的机器人主控四肢电机驱动器通信和运动板卡采用的也是IgH 。基于IgH作产品开发基本能满足大部分使用场景。
关于EtherCAT主站协议栈目前有两大主流开源代码为SOEM即支持Linux又支持windows 和IgH EtherCAT Master只支持Linux 。
本文以IgH最新稳定版本1.6来移植简单记录下IgH EtherCAT Master在嵌入式系统中的移植过程及主从站伺服驱动器通信测试。 [Linux 内核版本Linux-4.1.15] 。
IgH官方介绍
EtherCAT-Master | EtherLab
整个交叉编译过程很顺利没遇到一点儿报错。本次移植仅是测试简单起见使用通用的网卡驱动性能上肯定不是最好。要想高性能一方面需要给内核打实时性补丁一方面还需对特定的网卡驱动进行优化适配。源码里自带了一些网卡驱动如8139和e1000网卡驱动IgbIntel Gigabit 以太网驱动程序。
8139和e1000是两种常见的网卡芯片分别由Realtek和Intel生产。Realtek 8139也称为RTL8139是Realtek生产的一款常用的乙太网网卡芯片广泛应用于早期的计算机和嵌入式系统中。Intel e1000系列是Intel生产的一组高性能千兆位乙太网控制器芯片包括e1000、e1000e和82574等型号适用于桌面计算机、服务器和嵌入式系统。这两种网卡芯片均具有集成的MACMedia Access Control功能用于管理数据链路层的访问和控制以及PHYPhysical Layer功能用于处理物理层的信号传输和解调。它们同时具备MAC和PHY功能。 移植准备
IGH最新稳定版1.6源码下载地址
https://gitlab.com/etherlab.org/ethercat/-/archive/stable-1.6/ethercat-stable-1.6.tar.gz
准备Linux-4.1.15内核源码编译驱动模块需要) 我的路径
/root/test/imax6ul/linux
开发板提供的gcc交叉编译工具链
/opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
如果还想要给内核打上实时性补丁包可以在这找到Index of /pub/linux/kernel/projects/rt/4.14/
#为内核源码打上实时补丁
cd linux
patch -p 1 -i ../patch-4.10.199-rt97.patch
至此准备工作完成。
源码编译过程
先加载编译环境变量直接执行以下指令即可。
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
执行完成后 arm-poky-linux-gnueabi-gcc已经加入到环境变量中了。可以在命令行输出echo $CC试试看输出了arm-poky-linux-gnueabi-gcc说明环境已经生效了。 编译主站程序和协议栈
# EtherCAT 源码存放目录为/root/test/ethercat/ethercat-stable-1.6
# Linux-4.1.15 源码存放目录为/root/test/imax6ul/linux/ linux-4.1.15tar -zxvf ethercat-stable-1.6.tar.gz # 解压源码 /root/test/ethercat/ethercat-stable-1.6
cd ethercat-stable-1.6# --prefix是指定你下面make install时的安装目录--with-linux-dir是指定你的linux内核目录
./configure --prefix/root/test/ethercat/output --with-linux-dir/root/test/imax6ul/linux --enable-8139toono --enable-genericyes --hostarm-poky-linux-gnueabimake # 编译主站和协议栈源码make install #安装到指定目录 经过上面的交叉编译只是编译出了主站协议栈库和自带主站工具及程序但是这还不算完。
ethercat可执行程序是用于配置和管理 EtherCAT 主站IGH 主站的命令行工具。
ethercatctl是一个用于控制 EtherCAT Master 运行状态的命令行工具。它提供了启动、停止、重启 EtherCAT Master 等操作的命令用于管理 EtherCAT Master 的运行。
经过上面的编译编译出来的内容如下图所示 库和头文件 linux内核驱动模块还没出来所以直接是运行不起来的还需要编译出内核网络驱动模块。
编译内核驱动模块
#编译网卡驱动模块
# 指定交叉编译工具编译modules
make ARCHarm CROSS_COMPILEarm-poky-linux-gnueabi- modules # 编译通过会对应生成ethercat-stable-1.6/devices/ec_generic.ko和ethercat-stable-1.6/master/ec_master.ko
sudo make install # 在该目录下生成output目录成功编译出了ec_master.ko 和 ec_generic.ko的linux驱动模块。
ec_master.ko用于支持 EtherCAT 主站运行的 Linux 内核模块。它实现了 EtherCAT 主站协议栈允许在 Linux 系统上与 EtherCAT 从站设备进行实时通信和数据交换。主要负责存储一些ethercat从站信息管理domains域管理从站配置等有关于ethercat系统的资源,在/etc/sysconfig/ethercat中配置的MASTER0_DEVICE会作为该模块参数传入主站模块最终成为主站模块的mac使用网络地址即master-macs
ec_generic.ko经由系统网络栈利用标准以太网 (Ethernet) 的网络驱动程序。
ec_generic这个通用的驱动文件是在TCP/IP协议栈接口之上进行调用的所以会走TCP/IP协议栈会影响实时性。正式用应优化网卡驱动在网卡驱动上直接支持IgH接口。 放到板子上运行
复制ec_generic.ko和ec_master.ko到/lib/modules/内核版本号复制ethercat到usr/local/bin目录下。安装通用网卡驱动配置rules,创建设备号。
操作步骤
# 在/root/test/ethercat目录下创建modules文件夹并复制ec_generic.ko和ec_master.ko到modules下
mkdir -p output/modules
cp devices/ec_generic.ko output/modules/
cp master/ec_master.ko output/modules/# 将output文件夹打包传输到开发板nfs/tftp/scp
tar -cjf output.tar.bz2 output/-------------------------------------------------------------------------------------------------------------------------------------
# 开发板上执行
tar -jxvf output.tar.bz2cp output/modules/ec_generic.ko /lib/modules/4.1.15
# 复制ec_master.ko到/lib/modules/内核版本号/
cp output/modules/ec_master.ko /lib/modules/4.1.15 # 内核版本可以通过uname -r 查看depmodln -fs output/etc/init.d/ethercat /etc/init.d/ # 创建链接相比于复制节省内存空间
ln -fs output/bin/ethercat /usr/local/bin/mkdir /etc/sysconfig
ln -fs output/etc/sysconfig/ethercat /etc/sysconfig/# 配置rules,创建设备号
echo KERNEL\EtherCAT[0-9]*\, MODE\0664\ /etc/udev/rules.d/99-EtherCAT.rules# 获取板子MAC地址
ifconfig
# eth2 Link encap:以太网 硬件地址 00:0c:29:01:69:aa-------------------------------------------------------------------------------------------------------------------------------------
# 启动EtherCAT
# 配置主站的MAC地址
modprobe ec_master main_devices1E:ED:19:27:1A:B3 # 启动ethercat
/etc/init.d/ethercat start# 安装通用网卡驱动
insmod output/modules/ec_generic.ko# 通过ethercat查看信息
Ethercat --help运行测试
通过网线直连ethercat主从站从站启动完成后启动ethercat。
/etc/init.d/ethercat start
下面就可以使用 ethercat 工具来进行一些操作了。
sudo ethercat cstruct
ethercat 命令行
EtherCAT 命令行在 《EtherCAT IGH 1.52.pdf》中的 7.1 Command-line Tool 也有很详细的一个介绍。在编译和安装IGH的时候如果不修改默认的编译参数那么就是会提供 EtherCAT 命令行工具的。每个主站的实例都有生成一个字符设备名字为/dev/EtherCATx, 其中 x ∈ {0 . . . n}为主站实例的索引。
常用命令介绍
ethercat master
该命令行用来显示主站和以太网设备信息。
列出主站状态
ethercat slaves
列出连接的从站
ethercat cstruct
ethercat sdos
该命令行用来输出当前驱动器支持的所有的SDO信息。
举例
:~$ ethercat upload 0x2001 0x0000
0x03e8 1000解析读取从站0中索引号为 0x200116位子索引号为008位的SDO条目。返回的参数值为 1000。
注意必须有从站连接才能使用此命令不运行应用程序也可以使用。 ethercat download
该命令行用以向指定的从站 SDO 中的子索引中写入相应的参数值。
例子:
向从站0的索引号为0x606016位子索引号为008位的地址写入参数值0x08。
:~$ sudo ethercat download -t int16 -p 0 0x6060 00 08有的SDO 可能是由于厂家的限制不能写入参数。
:~$ sudo ethercat download -t uint16 0x2008 0x0000 0x000f
SDO transfer aborted with code 0x08000021: Data cannot be transferred or stored to the application because of local control
注意必须有从站连接才能使用此命令不运行应用程序也可以使用。
:~$ ethercat sdos
SDO 0x1000, Device type0x1000:00, r-r-r-, uint32, 32 bit, Device type
SDO 0x1001, Error register0x1001:00, r-r-r-, uint8, 8 bit, Error register
SDO 0x1008, Device name0x1008:00, r-r-r-, string, 72 bit, Device name
SDO 0x1009, Hardware version0x1009:00, r-r-r-, string, 24 bit, Hardware version
SDO 0x100a, Software version0x100a:00, r-r-r-, string, 32 bit, Software version
SDO 0x1010, store parameters0x1010:00, r-r-r-, uint8, 8 bit, SubIndex 0000x1010:01, rwrwrw, uint32, 32 bit, save all parameters0x1010:02, rwrwrw, uint32, 32 bit, save communication parameters0x1010:03, rwrwrw, uint32, 32 bit, save application parameters0x1010:04, rwrwrw, uint32, 32 bit, save manufacturer defined parameters
..............
SDO 0x6007, Abort_connection_option_code0x6007:00, rwrwrw, int16, 16 bit, Abort_connection_option_code
SDO 0x603f, errorcode0x603f:00, r-r-r-, uint16, 16 bit, errorcode
SDO 0x6040, controlword0x6040:00, rwrwrw, uint16, 16 bit, controlword
SDO 0x6041, statusword0x6041:00, r-r-r-, uint16, 16 bit, statusword
..............ethercat pdos
该命令行用来显示出同步管理器的参数和PDO分配和映射信息。
ethercat upload
该命令行用以读取指定从站相应PDO设定的参数值。
其他一些命令参考EtherCAT IGH 命令行介绍_igh ethercat-CSDN博客
:~$ ethercat --helpalias Write alias addresses.config Show slave configurations.crc CRC error register diagnosis.cstruct Generate slave PDO information in C language.data Output binary domain process data.debug Set the masters debug level.domains Show configured domains.download Write an SDO entry to a slave.eoe Display Ethernet over EtherCAT statictics.foe_read Read a file from a slave via FoE.foe_write Store a file on a slave via FoE.graph Output the bus topology as a graph.ip Set EoE IP parameters.master Show master and Ethernet device information.pdos List Sync managers, PDO assignment and mapping.reg_read Output a slaves register contents.reg_write Write data to a slaves registers.rescan Rescan the bus.sdos List SDO dictionaries.sii_read Output a slaves SII contents.sii_write Write SII contents to a slave.slaves Display slaves on the bus.soe_read Read an SoE IDN from a slave.soe_write Write an SoE IDN to a slave.states Request application-layer states.upload Read an SDO entry from a slave.version Show version information.xml Generate slave information XML.Global options:--master -m master Comma separated list of mastersto select, ranges are allowed.Examples: 1,3, 5-7,9, -3.Default: - (all).--force -f Force a command.--quiet -q Output less information.--verbose -v Output more information.--help -h Show this help.Numerical values can be specified either with decimal (no
prefix), octal (prefix 0) or hexadecimal (prefix 0x) base.Call ethercat COMMAND --help for command-specific help.测试效果
网上有一组测试效果连接五个从站主站单次收发数据的平均耗时以及实时性。测试主站单次收发数据的平均耗时的程序每隔 100 μs 发送并接收一次过程数据如此每循环 10000 次记录一下当前时间相邻两次记录的时间间隔减去其间空闲时间 100 μs × 10000 1 s 再除以收发次数 10000 便得到单次收发数据的平均耗时使用三种不同的网卡驱动三种情形下的大致结果如下表 主站测试代码
#include errno.h
#include signal.h
#include stdio.h
#include string.h
#include sys/resource.h
#include sys/time.h
#include sys/types.h
#include unistd.h/****************************************************************************/#include ecrt.h/****************************************************************************/// Application parameters
#define FREQUENCY 100
#define PRIORITY 1// Optional features
#define CONFIGURE_PDOS 1/****************************************************************************/// EtherCAT
static ec_master_t *master NULL;
static ec_master_state_t master_state {};static ec_domain_t *domain1 NULL;
static ec_domain_state_t domain1_state {};
static ec_domain_t *domain2 NULL;
static ec_domain_state_t domain2_state {};static ec_slave_config_t *sc;
static ec_slave_config_state_t sc_ana_in_state {};// Timer
static unsigned int sig_alarms 0;
static unsigned int user_alarms 0;/****************************************************************************/// process data
static uint8_t *domain1_pd NULL;
static uint8_t *domain2_pd NULL;#define BusCouplerPos 0, 0#define TI_AM3359ICE 0xE000059D, 0x54490001// offsets for PDO entries
static unsigned int off_dig_out2;
static unsigned int off_dig_in2;static unsigned int counter 0;
static unsigned int blink 0x00;/*****************************************************************************/#if CONFIGURE_PDOS
ec_pdo_entry_info_t slave_0_pdo_entries[] {{0x7010, 0x00, 32},{0x6000, 0x00, 4*8},
};
ec_pdo_info_t slave_0_pdos[] {{0x1601, 1, slave_0_pdo_entries 0},{0x1a00, 1, slave_0_pdo_entries 1},
};
static ec_sync_info_t slave_0_pdo_syncs[] {{2, EC_DIR_OUTPUT, 1, slave_0_pdos 0},{3, EC_DIR_INPUT, 1, slave_0_pdos 1},{0xff}
};#endif/*****************************************************************************/void check_domain1_state(void)
{ec_domain_state_t ds;ecrt_domain_state(domain1, ds);if (ds.working_counter ! domain1_state.working_counter)printf(Domain1: WC %u.\n, ds.working_counter);if (ds.wc_state ! domain1_state.wc_state)printf(Domain1: State %u.\n, ds.wc_state);domain1_state ds;
}/*****************************************************************************/
void check_domain2_state(void)
{ec_domain_state_t ds;ecrt_domain_state(domain2, ds);if (ds.working_counter ! domain2_state.working_counter)printf(Domain2: WC %u.\n, ds.working_counter);if (ds.wc_state ! domain2_state.wc_state)printf(Domain2: State %u.\n, ds.wc_state);domain2_state ds;
}/*****************************************************************************/void check_master_state(void)
{ec_master_state_t ms;ecrt_master_state(master, ms);if (ms.slaves_responding ! master_state.slaves_responding)printf(%u slave(s).\n, ms.slaves_responding);if (ms.al_states ! master_state.al_states)printf(AL states: 0x%02X.\n, ms.al_states);if (ms.link_up ! master_state.link_up)printf(Link is %s.\n, ms.link_up ? up : down);master_state ms;
}/*****************************************************************************/void check_slave_config_states(void)
{ec_slave_config_state_t s;ecrt_slave_config_state(sc, s);if (s.al_state ! sc_ana_in_state.al_state)printf(AnaIn: State 0x%02X.\n, s.al_state);if (s.online ! sc_ana_in_state.online)printf(AnaIn: %s.\n, s.online ? online : offline);if (s.operational ! sc_ana_in_state.operational)printf(AnaIn: %soperational.\n,s.operational ? : Not );sc_ana_in_state s;
}/*****************************************************************************/void cyclic_task()
{// receive process dataecrt_master_receive(master);ecrt_domain_process(domain1);ecrt_domain_process(domain2);// check process data state (optional)check_domain1_state();check_domain2_state();// if (counter) {
// counter--;
// } else { // do this at 1 Hzcounter FREQUENCY;// calculate new process datablink ;// check for master state (optional)check_master_state();// check for islave configuration state(s) (optional)check_slave_config_states();// printf(AnaIn: value0x%x\n, EC_READ_U32(domain2_pd off_dig_in2));printf(AnaIn: value0x%x\n, EC_READ_U32(domain2_pd off_dig_in2));
//printf(AnaIn: value0x%x\n, EC_READ_U32(domain2_pd off_dig_in2 4));EC_WRITE_U32(domain1_pd off_dig_out2, blink);
// printf(AnaIn: value0x%x\n, EC_READ_U32(domain1_pd off_dig_out2));
// }// send process dataecrt_domain_queue(domain1);ecrt_domain_queue(domain2);ecrt_master_send(master);
}/****************************************************************************/void signal_handler(int signum) {switch (signum) {case SIGALRM:sig_alarms;break;}
}/****************************************************************************/int main(int argc, char **argv)
{struct sigaction sa;struct itimerval tv;master ecrt_request_master(0);if (!master)return -1;domain1 ecrt_master_create_domain(master);if (!domain1)return -1;domain2 ecrt_master_create_domain(master);if (!domain2)return -1;#if CONFIGURE_PDOSif (!(sc ecrt_master_slave_config(master, BusCouplerPos, TI_AM3359ICE))) {fprintf(stderr, Failed to get slave configuration.\n);return -1;}if (ecrt_slave_config_pdos(sc, EC_END, slave_0_pdo_syncs)) {fprintf(stderr, Failed to configure PDOs.\n);return -1;}printf(Configuring PDOs...\n);// Create configuration for bus coupleroff_dig_out2 ecrt_slave_config_reg_pdo_entry(sc,0x7010, 0, domain1, NULL);if (off_dig_out2 0)return -1;off_dig_in2 ecrt_slave_config_reg_pdo_entry(sc,0x6000, 0, domain2, NULL);if (off_dig_in2 0)return -1;
#endifprintf(Activating master...\n);if (ecrt_master_activate(master))return -1;if (!(domain1_pd ecrt_domain_data(domain1))) {return -1;}if (!(domain2_pd ecrt_domain_data(domain2))) {return -1;}sa.sa_handler signal_handler;sigemptyset(sa.sa_mask);sa.sa_flags 0;if (sigaction(SIGALRM, sa, 0)) {fprintf(stderr, Failed to install signal handler!\n);return -1;}printf(Starting timer...\n);tv.it_interval.tv_sec 0;tv.it_interval.tv_usec 1000000 / FREQUENCY;tv.it_value.tv_sec 0;tv.it_value.tv_usec 2000;if (setitimer(ITIMER_REAL, tv, NULL)) {fprintf(stderr, Failed to start timer: %s\n, strerror(errno));return 1;}printf(Started.\n);while (1) {pause();while (sig_alarms ! user_alarms) {cyclic_task();user_alarms;}}return 0;
}/****************************************************************************//***********IGH demo编译*****************/
arm-linux-gnueabi-gcc main.c -o ethercat_test -I../../ethercat/include/ -L../..ethercat/lib -lethercat
IGH在Linux应用空间的其他使用
参考EtherCAT源码下的example。
git clone https://gitee.com/wllw7176/MyEthercat-IGH-1.5.2.git 参考EtherCAT二次开发的源代码
其他资源
EtherCAT使用与解析-ethercat系统内核模块加载与初始化操作_ec_generic.ko-CSDN博客
https://www.cnblogs.com/wujingcqu/p/16295570.html
https://blog.51cto.com/u_15858333/6406909
IgH详解 一、概述-CSDN博客
EtherCAT设备协议详解二、EtherCAT状态机及配置流程-CSDN博客
在x86-64和arm64 Linux上调试IgH EtherCAT主站软件以及实现星形走线连接多从站 - 知乎
ethercatpack/mytest/test_ethercat.c · wllw7176_gitee/MyEthercat-IGH 1.5.2 - Gitee.com
https://pwl999.blog.csdn.net/article/details/109397917
IgH EtherCAT主站开发案例分享——基于NXP i.MX 8M Mini - 知乎
开源工业以太网现场总线协议栈汇总_soes从站模拟器-CSDN博客
raspberry pi RT-Linux平台搭建IgH环境_一种用于igh的网络驱动系统及方法与流程-CSDN博客
EtherCAT主站IgH解析(一)--主站初始化、状态机与EtherCAT报文_igh ethercat-CSDN博客
EtherCAT IGH 命令行介绍_igh ethercat-CSDN博客
LinuxCNC搭配Igh EtherCat Master开源Ethercat主站通讯控制测试_linuxcnc igh-CSDN博客
【虹科干货】使用Profishark进行EtherCAT主站性能测试 – 宏网络安全信息门户网站2
基于Zynq平台的igh EtherCAT主站的配置和使用方法包括Preempt RT和Xenomai两种实时内核的介绍和配置示例_ethercat1.5.2中文-CSDN博客
https://www.cnblogs.com/tdyizhen1314/p/17628400.html