Versions Compared

Key

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

About

This example illustrates the process of configuring and utilizing Dynamic PDOs (Process Data Objects) within an EtherCAT SubDevice, leveraging the CoE (CANopen over EtherCAT) protocol. Dynamic PDOs facilitate flexible data transfer between slave and master devices, allowing for the dynamic configuration of data points and their associated attributes.

Prerequisites

The actual distribution of the examples can be found here: EtherCAT Slave Examples.

The cifXApplicationDemo project with corresponding ECS_DynamicPDO example can be found in the netXStudio:

...

The active target corresponding to the netX90 use case can be selected as shown on the picture below:

...

Info

This example is based on the ECS CoE Custom OD example, which provides important details on working with CoE object dictionary

In this example, the configuration and usage of Dynamic PDO are demonstrated through the following basic steps:

  • Create a new PDO

  • Add the PDO to SyncManager

  • Add Handler for Dynamic PDO

To conclude, we will demonstrate how to assess the behavior using TwinCAT.

Create a new PDO

In the initial step, a new PDO must be defined in the AppECS_DemoApplication_Config.h file by incorporating the object description as illustrated below:

Code Block
languagec
   {
        .eCommand = OD_CREATE_OBJECT,
        .pszName = "3. RxPDO",
        .uCreate.tObject = {
            .usIndex = 0x1602,
            .bMaxNumOfSubObjs = 2,
            .bObjectCode = ODV3_OBJCODE_RECORD,
            .usAccessFlags = 0,
            .bValueInfo = 0,
            .bIndicationFlags = 0,
            .usDataType = ECAT_OD_DTYPE_PDO_MAPPING,
            .usAccessRights = ECAT_OD_ACCESS_ALL,
            .ulMaxFieldUnits = 0,
        },
        .tInitial = {NULL, 0},
        .tDefault = {NULL, 0},
        .tMinimum = {NULL, 0},
        .tMaximum = {NULL, 0},
    },

Then, the new PDO element shall be created :

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

static const uint8_t s_b1602_NumElements = HIL_CNT_ELEMENT(s_ab1602_Elements);

Finally, the new PDO shall be added to the Sync Manager:

Code Block
languagec
static const uint16_t s_aus1C12_Entries[] = { 0x1600, 0x1601, 0x1602};
    {
        .eCommand = OD_CREATE_SUBOBJECT,
        .pszName = NULL,
        .uCreate.tSubObject = {
            .usIndex = 0x1C12,
            .bSubindex = 3,
            .bValueInfo = ODV3_VALUE_INFO_INITIAL_VALUE,
            .bIndicationFlags = 0,
            .usDataType = ECAT_OD_DTYPE_UNSIGNED16,
            .usAccessRights = ECAT_OD_READ_ALL | ECAT_OD_WRITE_PREOP,
            .ulMaxFieldUnits = 1,
        },
        .tInitial = {&s_aus1C12_Entries[2], sizeof(s_aus1C12_Entries[2])},
    },

Add the handling of dynamic PDO

To effectively manage the changes in dynamic PDOs during runtime, the application must be enhanced with a function that notifies the stack of any alterations in the input/output size.

The relevant function is located within the specified file: AppECS_DemoApplication_DynPDO_Handler.cnamed as AppECSCustomOd_WriteObjectInd().

This function provides the code, which reacts on write access to the SyncManager objects 0x1C12 and 0x1C13.

Code Block
languagec
uint32_t AppECSCustomOd_WriteObjectInd( APP_ECS_CHANNEL_HANDLER_RSC_T *ptEcsRsc,
                                        CIFX_PACKET* ptPacket )
{
  uint32_t ulRet = CIFX_NO_ERROR;
  uint8_t bSendPck = true;
  ODV3_WRITE_OBJECT_REQ_T* ptRes = (ODV3_WRITE_OBJECT_REQ_T*) ptPacket;
  ODV3_WRITE_OBJECT_REQ_T *ptReq = (ODV3_WRITE_OBJECT_REQ_T*) ptPacket;

  switch(ptRes->tData.usIndex)
  {
    case 0x1C12:
      PRINTF("case 0x1C012:" NEWLINE);
    case 0x1C13:
      PRINTF("case 0x1C013:" NEWLINE);
      bSendPck = false; /*Pkt_SendPacket inside function*/
      ulRet = AppECS_OD_WriteInd_PDOAssignmentParameter(ptEcsRsc, ptReq);
      break;
    default:
        ulRet = ERR_ODV3_OBJECT_DOES_NOT_EXIST;
      break;
    }
   if(false != bSendPck)
   {
    ptRes->tHead.ulSta = ulRet;
    ptRes->tHead.ulCmd |= 0x01;
    ptRes->tHead.ulLen = sizeof(ptRes->tData);
    ulRet=  Pkt_SendPacket( ptEcsRsc->hPktIfRsc, (CIFX_PACKET *) ptRes, APPECS_DEMOAPPLICATION_TIMEOUT);
   }
  return ulRet;
}

The function AppECS_OD_WriteInd_PDOAssignmentParametercontains two other functions AppECS_OD_CalculatePdoOffsets() and AppECS_SetIoSizeReq().

When the EtherCAT MainDevice writes to the SyncManager object of the SubDevice, the SubDevice application must identify the addressed PDO. Subsequently, the application calculates the new size of the PDO and utilizes AppECS_SetIoSizeReq() to notify the EtherCAT stack of this updated size.

In this example, the PDO 0x1602, which has a size of 1 byte, is defined. To accommodate this new PDO, it is essential to modify the AppECS_OD_CalculatePdoOffsets() function.

Checking behaviour with TwinCAT

In order to check the result with TwinCAT, please the new ESI file to the TwinCAT ESI file folder. In the new project now activate PDO assignment.

...

The new PDO 0x1602 shall be visible in the list of objects:

...

The PDO will be displayed in the Startup tab, as the MainDevice downloads the PDO to the SyncManager object.

...

The task has been successfully completed, and you are free to modify and enhance this example as you see fit, tailoring it to meet your specific requirements.

Conclusion

By implementing these steps and utilizing the features of Dynamic PDOs, you can develop adaptable and efficient EtherCAT SubDevices that respond effectively to evolving communication needs.