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
go to the file: AppECS_DemoObjectDictionary.h
add new Objects
Code Block |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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 |
---|
|
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;
}
|
...