Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

1. ECS Setup.

Necessary hardware and sotware for this training

The same like in ECS SimpleConfig Example exercise. Follow the steps 1 till 3 and use here now netX 90 - EtherCAT Slave - dynamicPDO V3.0.0.0

2. Create a new PDO like in the Training ECS CustomOD Example exercise

go to the file: AppECS_DemoObjectDictionary.h

add new Objects

Code Block
languagecpp
OBJECT_DESCRIPTION_T g_tObjects[] =
{
  ...
  {
    .usIndex = 0x1602,
    .bMaxNumOfSubObjs = ARRCNT(s_ab1601_Elements),
    .bObjectCode = ODV3_OBJCODE_RECORD,
    .usAccessFlags = 0,
    .bIndicationFlags = 0,
    .usDatatype = ECAT_OD_DTYPE_PDO_MAPPING,
    .usAccessRights = ECAT_OD_READ_ALL,
    /* no SimpleVar, therefore no ulMaxFieldUnits value */
    .pszName = "3. RxPDO",
    /* no SimpleVar, therefore no initial value */
    .ptSi00 = &g_tSiObj_1602[0],
    .ptSiBreak = &g_tSiObj_1602[ ARRCNT(g_tSiObj_1602) ],
  },
  ...
  {
    .usIndex = 0x1C12,
    .bMaxNumOfSubObjs = 3,
	...
  },
  ...
  {
    .usIndex = 0x2002,
    .bMaxNumOfSubObjs = ARRCNT(g_tSiObj_2001) - 1,
    .bObjectCode = ODV3_OBJCODE_RECORD,
    .usAccessFlags = ODV3_ACCESS_FLAGS_RXPDO_MAPPABLE,
    .bIndicationFlags = 0,
    .usDatatype = ECAT_OD_DTYPE_UNSIGNED8,/**< \todo what exactly shall be used here */
    .usAccessRights = ECAT_OD_READ_ALL,
    /* no SimpleVar, therefore no ulMaxFieldUnits value */
    .pszName = "Outputs",
    /* no SimpleVar, therefore no initial value */
    .ptSi00 = &g_tSiObj_2002[0],
    .ptSiBreak = &g_tSiObj_2002[ ARRCNT(g_tSiObj_2002) ],
  },
  ...  
}

add new PDO

Code Block
languagecpp
static const uint32_t s_ab1602_Elements[] =
{
  PDOMAPPING(0x2002, 1, 8),
};

static const uint8_t s_b1602_NumElements = ARRCNT(s_ab1602_Elements);

SUBOBJECT_DESCRIPTION_T g_tSiObj_1602[] =
{
  {
    .bSubIndex = 0,
    .bIndicationFlags = 0,
    .usAccessRights = ECAT_OD_READ_ALL,
    .usDatatype = ECAT_OD_DTYPE_UNSIGNED8,
    .ulMaxFieldUnits = 1,
    .pszName = "Number of elements",
    .pvInitialValue = &s_b1602_NumElements,
    .ulInitialValueLength = sizeof(s_b1602_NumElements),
  },
  {
    .bSubIndex = 1,
    .bIndicationFlags = 0,
    .usAccessRights = ECAT_OD_READ_ALL,
    .usDatatype = ECAT_OD_DTYPE_UNSIGNED32,
    .ulMaxFieldUnits = 1,
    .pszName = 0,
    .pvInitialValue = &s_ab1602_Elements[0],
    .ulInitialValueLength = sizeof(s_ab1602_Elements[0]),
  },
};

add the new PDO to the SyncManager object

Code Block
languagecpp
static const uint16_t s_aus1C12_Entries[] = { 0x1600, 0x1601 , 0x1602 };
...
SUBOBJECT_DESCRIPTION_T tSiObj_1C12[] =
{
   ...
  {
    .bSubIndex = 3,
    .bIndicationFlags = 0,
    .usAccessRights = ECAT_OD_READ_ALL|ECAT_OD_WRITE_PREOP, /* for PDO Assignment*/
    .usDatatype = ECAT_OD_DTYPE_UNSIGNED16,
    .ulMaxFieldUnits = 1,
    .pszName = 0,
    .pvInitialValue = &s_aus1C12_Entries[2],
    .ulInitialValueLength = sizeof(s_aus1C12_Entries[2]),
  },
};

add new custom subobject

Code Block
languagecpp
static const uint8_t s_b2002_NumElements;

SUBOBJECT_DESCRIPTION_T g_tSiObj_2002[] =
{
  {
    .bSubIndex = 0,
    .bIndicationFlags = 0,
    .usAccessRights = ECAT_OD_READ_ALL,
    .usDatatype = ECAT_OD_DTYPE_UNSIGNED8,
    .ulMaxFieldUnits = 1,
    .pszName = "Number of elements",
    .pvInitialValue = &s_b2002_NumElements,
    .ulInitialValueLength = sizeof(s_b2002_NumElements),
  },
  {
    .bSubIndex = 1,
    .bIndicationFlags = 0,
    .usAccessRights = ECAT_OD_ACCESS_ALL,
    .usDatatype = ECAT_OD_DTYPE_UNSIGNED8,
    .ulMaxFieldUnits = 1,
    .pszName = "Outputdata10",
    .pvInitialValue = 0,
    .ulInitialValueLength = 0,
  },
};
static const uint8_t s_b2002_NumElements = ARRCNT(g_tSiObj_2002) - 1; /* SI 00 does not counts */


3. Ecat_SetIoSizeReq

Ecat_SetIoSizeReq is a special request with that the application can tell the stack a changed IO size. This is necessary for dynamic PDO changes.

Go to the file AppECS_DemoApplicationFunctions.c.

Here go to the function AppECS_Write_ObjectInd(...)

Here is a new source code:

Code Block
languagecpp
uint32_t AppECS_Write_ObjectInd(APP_DATA_T *ptAppData, CIFX_PACKET* ptPkt)
{
  ...
  switch ( ptInd->tData.usIndex )
    {
      ...
      case 0x1C12:
         lRet = OD_WriteInd_PDOAssignmentParameter(&tAppECSData, ptAppData, ptReq);
         break;
      case 0x1C13:
         lRet = OD_WriteInd_PDOAssignmentParameter(&tAppECSData, ptAppData, ptReq);
         break;
      default:
         lRet = CIFX_INVALID_PARAMETER;
         break;
    }
  ...
}




Code Block
languagecpp
static uint32_t  OD_CalculatePdoOffsets(APP_ECS_DATA_T *ptAppEcsData, APP_DATA_T *ptAppData, ODV3_WRITE_OBJECT_REQ_T* ptPck)
{
  ...
  switch (ptPck->tData.usIndex)
  {
    case 0x1C12:
    {
      for (j = 0;  j < ECS_NUMBER_OF_RX_SUBINDX_INCL_SUB0; j++)
      {
        /* add offset of PDO to list and calculate next offset,
         * usTotalInpuSize was set to 0 before 1st function call*/
        ptAppEcsData->tAssignment.tAssign1C12Temp.OffsetInProcessData[j] = ptAppEcsData->usTotalOutputSize;
        if (ptAppEcsData->tAssignment.tAssign1C12Temp.SubindexEntry[j] == 0x1600)
        {
          /* calculate next offset */
          ptAppEcsData->usTotalOutputSize += 6;
        }
        else if (ptAppEcsData->tAssignment.tAssign1C12Temp.SubindexEntry[j] == 0x1601)
        {
          /* calculate next offset */
          ptAppEcsData->usTotalOutputSize += 4;
        }
        else if (ptAppEcsData->tAssignment.tAssign1C12Temp.SubindexEntry[j] == 0x1602)
        {
          /* calculate next offset */
          ptAppEcsData->usTotalOutputSize += 1;
        }
      }
	  ...
    }
    break;
	...
  }
return lRet;
}

...