Reading ‘ro’ Objects from Powerlink Control Node

Hi,
I have successfully established communication between a X20CP1686X PLC and a third-party Powerlink control node. The XDD file provided includes objects with ‘rw’ (read-write) and ‘ro’ (read-only) access. After importing this XDD file in automation studio, I can see the tags with ‘rw’ access under ‘Device Specific Parameters’. However, the ‘ro’ objects are not visible.

I attempted to add the ‘AsEPL’ library but am unsure how to use its functions to read the object data from the control node. Could someone please guide me on the correct approach to resolve this issue? Additionally, if there are any examples of handling such data, it would be greatly appreciated.

Thanks for the assistance!

Hi,
in Ansi C i use this function:

void sasSdo(void)
{
brsstrcpy((UDINT)&HandlePyhNode.strInterface,“IF3”);
RegisterObj[0].index = 0x20F9;
RegisterObj[0].subindex = 2;
RegisterObj[0].datalen = sizeof(RegisterObj[0].ReadValue);

switch(SdoHandling.state)
{
	
	case SDO_IDLE:
		if(SdoHandling.bWrite)
		{
			SdoHandling.bWrite = 0;
			SdoHandling.state = SDO_WRITE;
		}
		else if (SdoHandling.bRead)
		{
			SdoHandling.bRead = 0;
			SdoHandling.state = SDO_READ;
		}
		break;
	
	case SDO_WRITE:
		if(BC_Obj[0].bModulOK)
		{
			plkSdoWrite.enable 				= 1;
			plkSdoWrite.pDevice 			= HandlePyhNode.strInterface;  // TODO
			//plkSdoWrite.node 				= HandlePyhNode.NodeNrArray[HandlePyhNode.CurNodeNr];		BC_Obj.usiNodeNr;
			plkSdoWrite.node 				= BC_Obj[HandlePyhNode.CurNodeNr].usiNodeNr; // .NodeNrArray[HandlePyhNode.CurNodeNr];
			plkSdoWrite.index 				= RegisterObj[0].index;
			plkSdoWrite.subindex 			= RegisterObj[0].subindex;
			plkSdoWrite.datalen 			= RegisterObj[0].datalen;
			plkSdoWrite.pData 				= (UDINT)&RegisterObj[0].SendValue;
				
			SdoHandling.state 				= SDO_WRITE_WAIT;
		}
		else
		{
			SdoHandling.state 				= SDO_ERR;
		}
		break;
	
	case SDO_WRITE_WAIT:
		if(plkSdoWrite.status == ERR_FUB_BUSY)
		{	
		}
		else if(plkSdoWrite.status == ERR_OK)
		{	
			plkSdoWrite.enable = 0;	
			SdoHandling.bWriteDone = 1;
			SdoHandling.state = SDO_IDLE;
		}
		else
		{
			SdoHandling.state = SDO_ERR;
		}
		
		break;
	
	case SDO_READ:
		if(BC_Obj[0].bModulOK)
		{
			
			plkSdoRead.enable 				= 1;
			plkSdoRead.pDevice 				= HandlePyhNode.strInterface;
			plkSdoRead.node 				= BC_Obj[HandlePyhNode.CurNodeNr].usiNodeNr;
			plkSdoRead.index 				= RegisterObj[0].index;
			plkSdoRead.subindex			 	= RegisterObj[0].subindex;
			plkSdoRead.datalen 				= RegisterObj[0].datalen;
			plkSdoRead.pData 				= (UDINT)&RegisterObj[0].ReadValue;
				
			SdoHandling.state 				= SDO_READ_WAIT;
		}
		else
		{
			SdoHandling.state 				= SDO_ERR;
		}
		break;
	
	case SDO_READ_WAIT:
		if(plkSdoRead.status != ERR_FUB_BUSY)
		{
			
			if(plkSdoRead.status == ERR_OK)
			{
				plkSdoRead.enable = 0;
				SdoHandling.bReadDone = 1;
				SdoHandling.state = SDO_IDLE;
			}
			else
			{
				SdoHandling.state = SDO_ERR;
			}
		}
		break;
	
	case SDO_ERR:
	
		break;
}
	
	EplSDOWrite(&plkSdoWrite);
	EplSDORead(&plkSdoRead);
		
		
return 0;

}

i create the following local user types:


and declarat the following variables:

The idea is to trigger a one-time write or read using the variables bWrite and bRead.
If you need further help I could reduce this example even further.

Best regards Stefan

2 Likes

Hi Stefan,

Thank you for your guidance on reading and writing an object in ANSI C programming. I followed your example, but unfortunately, it’s not working for me. I’m unsure if my code is logically correct. I didn’t find the way to check ModuleOk status.

Could you please review my code and correct any mistakes? Additionally, could you simplify the code for reading an object only? I’ve included the code and the variables I used below.

Thank you for your help!

/*Cyclic code*/
#include <bur/plctypes.h>

#ifdef _DEFAULT_INCLUDES
	#include <AsDefault.h>
#endif

void _CYCLIC ProgramCyclic(void)
{
	switch(SdoHandling.state){
		
		case SDO_IDLE:
			if(SdoHandling.bWrite)
			{
				SdoHandling.bWrite = 0;
				SdoHandling.state = SDO_WRITE;
			}
			else if (SdoHandling.bRead)
			{
				SdoHandling.bRead = 0;
				SdoHandling.state = SDO_READ;
			}
			break;
		
		case SDO_WRITE:
			RegisterObj.SendValue = 0x01;
//			if(ModuleOk == 1)
			{
				plkSdoWrite.enable 				= 1;
				plkSdoWrite.pDevice 			= "IF3"; 
				plkSdoWrite.node 				= 7;
				plkSdoWrite.index 				= 0x2300;
				plkSdoWrite.subindex 			= 0x01;
				plkSdoWrite.datalen 			= sizeof(RegisterObj.SendValue);
				plkSdoWrite.pData 				= (UDINT)&RegisterObj.SendValue;
				
				SdoHandling.state 				= SDO_WRITE_WAIT;
                                EplSDOWrite(&plkSdoWrite);
			}
//			else
//			{
//				SdoHandling.state 				= SDO_ERR;
//			}
			break;
		
		case SDO_WRITE_WAIT:
			if(plkSdoWrite.status == ERR_FUB_BUSY)
			{	
			}
			else if(plkSdoWrite.status == ERR_OK)
			{	
				plkSdoWrite.enable = 0;	
				SdoHandling.bWriteDone = 1;
				SdoHandling.state = SDO_IDLE;
			}
			else
			{
				SdoHandling.state = SDO_ERR;
			}
		
			break;
		case SDO_READ_WAIT:
			if(plkSdoRead.status != ERR_FUB_BUSY)
			{
			
				if(plkSdoRead.status == ERR_OK)
				{
					plkSdoRead.enable = 0;
					SdoHandling.bReadDone = 1;
					SdoHandling.state = SDO_IDLE;
				}
				else
				{
					SdoHandling.state = SDO_ERR;
				}
			}
			break;
		
		case SDO_READ:
			plkSdoRead.enable 				= 1;
			plkSdoRead.pDevice 				= "IF3";
			plkSdoRead.node 				= 7;
			plkSdoRead.index 				= 0x2300;
			plkSdoRead.subindex			 	= 01;
			plkSdoRead.datalen 				= sizeof(RegisterObj.readData);
			plkSdoRead.pData 				= (UDINT)&RegisterObj.ReadValue;
			EplSDORead(&plkSdoRead);
			break;
		case SDO_ERR:
			count_err++;	
			break;
	}
}

/* Variables */

/* Types */

/* Watch window */

Hello Kashif Khan,

1: “I didn’t find the way to check ModuleOk status.”

Typically (with the 3rd party Powerlink providers that I know) there is a data point in the I/O mapping called Module OK. This data point becomes TRUE if the module is present on the bus.

If you send requests to a Powerlink participant, you should be sure that it is ready for it.

In my example, I used the Module OK bit for this. If you remove the Module OK query (checking whether this node is on the bus), the EPL function block will give you an error if there are no nodes on the bus. Nothing more. You could therefore also remove this line for a test.

2: Could you please review my code and correct any mistakes?

I don’t see any error.

3: Additionally, could you simplify the code for reading an object only?

yes maybe next week.

I’ve included the code and the variables I used below.

Should I use your Project?

Best regards

Hi Stefan,

Please proceed with the project and let me know if you need anything from my side.

I have a couple of questions regarding the update of BC_Obj.bModulOK in your code:

  1. How and where are you updating this variable?
  2. While I understand there is a point in I/O mapping for module status, how can we access this in programming? Are there any specific library functions we should use?

I am interested in reading this object’s index/sub-index, not only once but cyclically. Please try this if you get time in next week.

Thank You Very much!

Hi,

You can find the slimmed down example in the appendix.

1: Cyclic objects
In principle, you cannot access Powerlink objects cyclically with the AsEPL library and the function blocks it contains. You also cannot access all Powerlink objects cyclically. If it is an object that is intended for cyclical querying, this Powerlink object must first be assigned to a cyclic object.

2: XML device description

Typically, Powerlink slaves have a hardware description file *.xdd (XML device description). This file can be imported into Automation Studio.


Once it has been imported, you can also activate cyclic data points depending on XDD. XDD is provided by 3rd party manufacturers.

Is there an XDD from the manufacturer?
What does this file look like?
Can you activate cyclic objects in it?

3: Workaround
3.1: Start the Cyclic Read after Cyclic read again and
Depending on how fast the cyclic transfer should be, it may be sufficient to carry out the acyclic read over and over again.

3.2: Powerlink Library
With the Powerlink library you can only set up a copy job for offsets in the frame, but not for cyclic objects. Someone has to create the mapping so that the data is at the right offset…

Best regards Stefan
SampleEPLSDO.zip (9.4 MB)