如何在EtherCAT从站上增加模拟量输入AI变量

chy123 财来富往 2026-03-12 4737

“工控有得聊”是机械工业出版社“机工工控”“机工通信”品牌旗下专业资讯和服务平台,致力于帮助读者在电气通信、自动化领域里,紧跟前沿资讯,掌握核心技术,快速提升专业素养。点击蓝色微信名可快速关注我们。

工业自动化项目中,你是否曾因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所示。 97631fba-1c8a-11f1-90a1-92fbcf53809c.png

图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所示。

9822fd94-1c8a-11f1-90a1-92fbcf53809c.png

图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。

typedefstructOBJ_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 TSDOINFOENTRYDESCOBJMEM 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。

typedefstructOBJ_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)中给自定义的变量赋值

voidAPPL_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主站

voidAPPL_InputMapping(UINT16* pData)
{
 UINT16j =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)数据通信的方法

推荐阅读:

人民币一度跌破7.31 多空博弈悄然升级

【风口研报】“车路云”试点城市名单公布 产业链有望持续升温

主力复盘:近5亿狂拉北汽蓝谷 任子行20CM涨停

【12315投诉公示】地素时尚新增2件投诉公示,涉及其他质量问题等

证监会、公安部、财政部等六部委出手 打击资本市场财务造假

一周牛熊股 | 沪指守住2900点,本周最牛股五天翻倍