扫码加入

  • 正文
  • 相关推荐
申请入驻 产业图谱

EtherCAT从站AI通道不够用?手把手教你扩容模拟量输入!

03/19 10:08
233
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

在工业自动化项目中,你是否曾因EtherCAT从站的模拟量输入(AI)通道不足而头疼?想要灵活扩展,却苦于官方手册语焉不详?

本文将为你揭秘从站设备添加AI变量的完整流程——

要在EtherCAT从站增加模拟量输入AI变量,首先需更新从站设备程序,定义新的AI变量并初始化。然后,在PDO映射配置中添加该变量,以便主站读取。接着,在从站驱动程序中更新数据处理逻辑,包括对AI变量的采集和处理。最后,在主站程序中更新对该AI变量的读取逻辑,实现数据交换。通过这些步骤,可以成功在EtherCAT从站上增加模拟量输入AI变量,并实现与主站的数据通信和控制。

修改XML文件有关模拟量输入AI的部分

模拟量输入AI的EtherCAT数据通信需要8个AI对象,打开XML文件,点击第二个“TxPdo”,可以看到其Name是AI Inputs并且其下拥有7个Entry,在其后增加8个自定义的AI变量。具体添加过程如下。

(1)增加变量对应于输入映射索引0x1a02

增加变量对应于输入映射索引0x1a02的,需要修改DT1A02数据类型以增加8个变量。

① 修改DT1A02数据类型

利用XMLNotePad打开要修改的XML文件,之后依次点击节点:

“EtherCATInfo”→“Descriptions”→“Devices”→“Device”→“Profile”→“Dictionary”→“DataTypes”,依次点击子节点“DataType”,直至找到DT1A02所在的位置,在最后的“SubItem”右键“Duplicate”复制8个新的SubItem。之后,修改新建的SubItem的SubIdx,Name和Type等信息。

SubIdx按顺序递增,Name等根据需求定义,BitOffs是上一个SubItem的BitSize和BitOffs的和。因为添加了新的SubItem,所以DT1A02的BitSize要随之更新,它的值是最后一个SubItem的BitSize和BitOffs的和。XML文件中DT1A02的修改如图1所示。

图1 XML文件中DT1A02的修改

② 修改DT1A02对象

在XMLNotePad中点击“Dictionary”的子节点“Objects”,依次点击“Object”,找到0x1a02所在的位置,修改BitSize即可。这个BitSize值与上面DataType中DT1A02的BitSize要保持一致。本例中修改了0x1a02数据对象(输出映射表),增加8个SubItem,XML文件中0x1a02修改如图2所示。

图2 XML文件中0x1a02的修改

(2)修改0x6020数据类型及对象

由于索引0x1a02将输出过程数据映射到0x6020中,需要修改0x6020数据类型和对象。

① 修改DT6020数据类型

利用XMLNotePad打开要修改的XML文件,之后依次点击节点:

“EtherCATInfo”→“Descriptions”→“Devices”→“Device”→“Profile”→“Dictionary”→“DataTypes”,依次点击子节点“DataType”,直至找到DT6020所在的位置,新增8个SubItem。之后,修改新建的SubItem的SubIdx,Name和Type等信息。

SubIdx按顺序递增,Name等根据需求定义,BitOffs是上一个SubItem的BitSize和BitOffs的和。同时因为添加了新的SubItem,所以DT6020的BitSize要随之更新,它的值是最后一个SubItem的BitSize和BitOffs的和。XML文件中DT6020的修改如图3所示。

图3 XML文件中DT6020的修改

② 修改DT6020对象

在XMLNotePad中点击“Dictionary”的子节点“Objects”,依次点击“Object”,找到0x6020所在的位置,修改BitSize即可。这个BitSize值与上面DataType中DT6020的BitSize要保持一致。同时增加8个SubItem并进行命名。XML文件中0x6020的修改如图4所示。

图4 XML文件中0x6020的修改

修改STM32程序有关模拟量输入AI的部分

(1)在el9800appl.h文件中修改索引0x1a02的本地存储变量等相关信息

① 修改0x1a02的本地存储

修改TOBJ1A02对应的结构体typedef struct OBJ_STRUCT_PACKED_START。

typedef struct OBJ_STRUCT_PACKED_START
{
     UINT16   u16SubIndex0; /* SubIndex 0*/
     UINT32   aEntries[16]; /* Entry buffer*/  
} OBJ_STRUCT_PACKED_END
TOBJ1A02    

② 初始化0x1a02与XML文件对应

在图8-19中,在XML文件中对DT1A02进行修改,增加了8个SubItem,且其最大的子索引是16。在图8-20中,在XML文件中对0x1a02进行修改,增加了8个SubItem,其DefaultData表示映射索引号。故而在函数PROTO TOBJ1A02 sAITxPDOMap中进行相应修改:首元素变为16,末尾添加8个元素分别是新增的8个SubItem的相应索引号。

PROTO TOBJ1A02 sAITxPDOMap
#ifdef
 _EVALBOARD_
= {16, {0x60200101, 0x60200201, 0x60200302, 0x60200502, 0x08, 0x18020701, 0x18020901, 0x60201110, 0x60201210, 0x60201310, 0x60201410, 0x60201510, 0x60201610, 0x60201710, 0x60201810, 0x60201910}}
#endif

③ 修改0x1a02表项描述

修改结构体OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x1A02[]。

OBJCONST TSDOINFOENTRYDESC	OBJMEM asEntryDesc0x1A02[] = 
{
   {DEFTYPE_UNSIGNED8, 0x8, ACCESS_READ }, 
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},	
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
   {DEFTYPE_UNSIGNED32, 0x20, ACCESS_READ},
}

(2)在el9800appl.h文件中修改索引0x6020的本地存储变量等相关信息

① 修改0x6020的本地存储

修改TOBJ6020对应的typedef struct OBJ_STRUCT_PACKED_START。

typedef struct OBJ_STRUCT_PACKED_START 
{
   UINT16   u16SubIndex0; /* SubIndex 0*/
   BOOLEAN(bUnderrange); /* (SI1) Analog input under range*/
   BOOLEAN(bOverrange); /* (SI2) Analog input over range*/
   BIT2(b2Limit1); /* (SI3) Analog input 1st limit*/
   BIT2(b2Limit2); /* (SI5) Analog input 2nd limit*/
   ALIGN2(SubIndex006) /* 2Bit alignment*/
   ALIGN6(SubIndex007) /* 2Bit alignment*/
   BOOLEAN(bTxPDOState); /* (SI15) TxPdo state*/
   BOOLEAN(bTxPDOToggle); /* (SI16) TxPdo toggle*/
   INT16   i16Analoginput; /* (SI17) Analog input value*/
   INT16   i16AI1; /* (SI18) Analog input value*/
	   INT16   i16AI2; /* (SI19) Analog input value*/
	   INT16   i16AI3; /* (SI20) Analog input value*/
	   INT16   i16AI4; /* (SI21) Analog input value*/
	   INT16   i16AI5; /* (SI22) Analog input value*/
	   INT16   i16AI6; /* (SI23) Analog input value*/
	   INT16   i16AI7; /* (SI24) Analog input value*/
	   INT16   i16AI8; /* (SI25) Analog input value*/
} OBJ_STRUCT_PACKED_END
TOBJ6020

② 初始化0x6020与XML文件对应

在图8-21中,在XML文件中对0x6020进行了修改,增加了8个SubItem,且其最大的子索引是25。对应在函数PROTO TOBJ6020 sAIInputs中进行修改:首元素变为最大子索引25,末尾添加8个元素分别是新增的8个SubItem的初始值。

PROTO TOBJ6020 sAIInputs
#ifdef
 _EVALBOARD_
= {25, 0x00, 0x00, 0x00, 0x00, 0, 0, 0x00, 0x00, 0x7FFF, 0x0001, 0x0001, 0x0001, 0x0001, 
0x0001, 0x0001, 0x0001, 0x0001}
#endif

③ 修改0x6020表项描述

修改结构体OBJCONST TSDOINFOENTRYDESC OBJMEM asEntryDesc0x6020[]。

OBJCONST TSDOINFOENTRYDESC  OBJMEM asEntryDesc0x6020[] = {
   {DEFTYPE_UNSIGNED8, 0x8, ACCESS_READ },
   {DEFTYPE_BOOLEAN, 0x01, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_BOOLEAN, 0x01, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_BIT2, 0x02, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {0x0000, 0, 0},
   {DEFTYPE_BIT2, 0x02, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {0x0000, 0x02, 0},
   {0x0000, 0x06, 0},
   {0x0000, 0, 0},
   {0x0000, 0, 0},
   {0x0000, 0, 0},
   {0x0000, 0, 0},
   {0x0000, 0, 0},
   {0x0000, 0, 0},
   {0x0000, 0, 0},
   {DEFTYPE_BOOLEAN, 0x01, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_BOOLEAN, 0x01, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
	   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
	   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
	   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
	   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING},
   {DEFTYPE_INTEGER16, 0x10, ACCESS_READ | OBJACCESS_TXPDOMAPPING}
}      

④ 修改0x1a02和0x6020的对象描述

修改TOBJECT OBJMEM ApplicationObjDic[],需要特别注意方框中数据要与子索引最大值相对应。

TOBJECT  OBJMEM ApplicationObjDic[] = 
{  
    ……
    /* Object 0x1A02 */
    {NULL, NULL, 0x1A02, {DEFTYPE_PDOMAPPING, 16 | (OBJCODE_REC << 8)}, asEntryDesc0x1A02, aName0x1A02, &sAITxPDOMap, NULL, NULL, 0x0000 },
    ……
    /* Object 0x6020 */
    {NULL, NULL, 0x6020, {DEFTYPE_RECORD, 25 | (OBJCODE_REC << 8)}, asEntryDesc0x6020, aName0x6020, &sAIInputs, NULL, NULL, 0x0000 },
    ……
}

(3)修改el9800appl.c源文件中的有关内容

① 在函数void APPL_Application(void)中给自定义的变量赋值

void APPL_Application(void)
{
    ……
    sAIIutputs.i16AI1 = sAOOutputs.i16AO01;
		sAIIutputs.i16AI2 = sAOOutputs.i16AO02;
		sAIIutputs.i16AI3 = sAOOutputs.i16AO03;
		sAIIutputs.i16AI4 = sAOOutputs.i16AO04;
		sAIIutputs.i16AI5 = sAOOutputs.i16AO05;
		sAIIutputs.i16AI6 = sAOOutputs.i16AO06;
		sAIIutputs.i16AI7 = sAOOutputs.i16AO07;
		sAIIutputs.i16AI8 = sAOOutputs.i16AO08;
        ……
}

② 在函数void APPL_InputMapping(UINT16* pData)中将已添加的变量传给EtherCAT主站

void APPL_InputMapping(UINT16* pData)
{
   UINT16 j = 0;
   UINT16 *pTmpData = (UINT16 *)pData;
   /* we go through all entries of the TxPDO Assign object to get the assigned TxPDOs */
   for (j = 0; j < sTxPDOassign.u16SubIndex0; j++)
   {
      switch (sTxPDOassign.aEntries[j])
      {
      /* TxPDO 1 */
      case 0x1A00:
         *pTmpData++ = SWAPWORD(((UINT16 *) &sDIInputs)[1]);
         break;
      /* TxPDO 3 */
      case 0x1A02:
           *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[1]);
           *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[2]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[3]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[4]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[5]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[6]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[7]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[8]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[9]);
			   *pTmpData++ = SWAPWORD(((UINT16 *) &sAIInputs)[10]);
         break;
      }
   }
}

本文转自《EtherCAT工业以太网应用系统设计》第8章 EtherCAT从站增加模拟量输入/输出(AI/AO)数据通信的方法

推荐阅读

一本书掌握EtherCAT工业以太网应用系统设计!

全面覆盖核心原理与实战开发、硬件设计与软件调试

提供“理论+应用+代码”全链路解决方案

帮助读者快速攻克工业以太网开发难关!

▊《EtherCAT工业以太网应用系统设计》

李正军

本书全面介绍了EtherCAT工业以太网应用系统设计。书中内容丰富,体系先进,结构合理,理论与实践相结合,尤其注重工程应用技术。通过阅读本书,读者将深入了解EtherCAT技术原理、应用场景和关键设计步骤,为工业控制系统的开发和应用提供了全面的指导。本书力求所讲内容具有较强的可移植性、先进性、系统性、应用性及资料开放性,可起到举一反三的作用。本书配套程序代码、XML文件、电路文件、官方手册等数字资源。

撰 稿 人:杨健亭
责任编辑: 李馨馨
审 核 人:曹新宇

相关推荐

登录即可解锁
  • 海量技术文章
  • 设计资源下载
  • 产业链客户资源
  • 写文章/发需求
立即登录

“工控有得聊”是机械工业出版社“机工工控”“机工通信”品牌旗下专业资讯和服务平台,致力于帮助读者在电气、通信、自动化领域里,紧跟前沿资讯,掌握核心技术,快速提升专业素养。工业知识服务平台,分享热点资讯、精选深度技术文章、发布最新书讯。

微信公众号