# 06- Interfacing ctrlX CORE with IO-Link master using EtherCAT

This video will teach you how to interface ctrlX CORE with IO-Link master using EtherCAT. The following are the examples covered in the video:

{% embed url="<https://www.youtube.com/watch?v=2bgYXHP2zOQ>" %}

### Video Timeline:

[0:00](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=0s) - Introduction\
[0:50](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=50s) - What are we going to see?\
[1:25](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=85s) - Connections\
[2:11](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=131s) - Adding IO-Link master in the networks\
[6:28](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=388s) - Assign memories for IO-Link devices\
[11:27](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=687s) - Example 1: Actuating Signal Lamp using Distance sensor\
[19:45](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=1185s) - Example 2: Reading Vendor and Product ID of the IO-Link device using AoE\
[28:35](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=1715s) - Example 3: Reading the set-point of the sensor using AoE \
[31:52](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=1912s) - Example 4: Writing the set-point of the sensor using AoE \
[34:10](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=2050s) - Example 5: Visualizing IO-Link data on the Node-RED dashboard \
[37:49](https://www.youtube.com/watch?v=2bgYXHP2zOQ\&t=2269s) - Outroduction

### **Hardware and Software information**

* Software: ctrlX Works Software Version: 1.18.1
* Hardware: ctrlX CORE Plus

### **ESI description for IO-Link master AL1332**

{% embed url="<https://www.ifm.com/de/de/product/AL1332?tab=documents>" %}

### **Exam**ple 1: How to actuate IO-Link actuator using IO-Link sensor connected to ctrlX CORE via IO-Link master device AL1332.&#x20;

{% code title="GVL declaration" overflow="wrap" lineNumbers="true" %}

```iecst
{attribute 'qualified_only'}
VAR_GLOBAL
	//Distance Sensor
	rawbyte0 AT %IB0 : BYTE;
	rawbyte1 AT %IB1 : BYTE;

	//SignalLamp
	//Segment1
	segment1 AT %QB5 : BYTE;
	segment2 AT %QB4 : BYTE;
	segment3 AT %QB3 : BYTE;
	segment4 AT %QB2 : BYTE;
	segment5 AT %QB1 : BYTE;
END_VAR
```

{% endcode %}

{% code title="PLC variable declaration" overflow="wrap" lineNumbers="true" %}

```iecst
PROGRAM PLC_PRG
VAR
	wData : WORD;
	iDistance : INT;
	bOutput : BOOL;
	bySegment1 : BYTE;
END_VAR
```

{% endcode %}

{% code title="PLC code" overflow="wrap" lineNumbers="true" %}

```iecst
// -------------------- Reading Distance sensor process output --------------------

//Concatinate the byte 0 and byte 1
wData := IL_ConcatByte(GVL.rawbyte0,GVL.rawbyte1);

//Right shift the word by 4 bit
iDistance := WORD_TO_INT(SHR(wData,4));

//Defining limits
IF iDistance > 200 THEN
	iDistance := 200;
END_IF

IF iDistance < 5 THEN
	iDistance := 5;
END_IF

//Set point output
bOutput := GVL.rawbyte1.0;

//SignalLamp condition
IF bOutput = TRUE THEN
  // 2= Green
	GVL.segment1 := 2;
	GVL.segment2 := 2;
	GVL.segment3 := 2;
	GVL.segment4 := 2;
	GVL.segment5 := 2;
	ELSE //4= RED
	GVL.segment1 := 4;
	GVL.segment2 := 4;
	GVL.segment3 := 4;
	GVL.segment4 := 4;
	GVL.segment5 := 4;
END_IF
```

{% endcode %}

### **Exam**ple 2: How to read Vendor and Product ID of IO-Link device in PLC Engineering app using AoE protocol?

{% code title="GVL declaration" overflow="wrap" lineNumbers="true" %}

```iecst
{attribute 'qualified_only'}
VAR_GLOBAL
	//Distance Sensor
	rawbyte0 AT %IB0 : BYTE;
	rawbyte1 AT %IB1 : BYTE;

	//SignalLamp
	//Segment1
	segment1 AT %QB5 : BYTE;
	segment2 AT %QB4 : BYTE;
	segment3 AT %QB3 : BYTE;
	segment4 AT %QB2 : BYTE;
	segment5 AT %QB1 : BYTE;
END_VARde
```

{% endcode %}

{% code title="PLC variable declaration" overflow="wrap" lineNumbers="true" %}

```iecst
PROGRAM PLC_PRG
VAR
	wData : WORD;
	iDistance : INT;
	bOutput : BOOL;
	bySegment1 : BYTE;
	
// ---------------- Read AoE -----------------------------	

//Name of instance
	strMasterName : STRING := 'ethercatmaster';

//Ethercat address of ifm AL1332
	uiEthercatAddr : UINT := 1005;
	strTargetNetId   : IL_ECAT_AOE_NET_ID := (Byte0:= 172, Byte1:=31, Byte2:= 254, Byte3:= 254, Byte4:= 0, Byte5:= 1);

//Vendor variable declaration for IO Link read
	strVendor : STRING(32) := '';  //Variable in which the read result (vendor) value will be copied
	fbIOLinkRead_Vendor: IL_ECATAoeRead;
		
	uiIoLinkPortNbr_Vendor  : UINT := 1;//X1 = Plug, the IO-Link device is connected
	wIoLinkIndex_Vendor     : WORD := 16;   //IO-Link index = 16 (vendor)
	byIoLinkSubIndex_Vendor : BYTE := 0; 	//IO-Link Subindex = 0 (vendor)
	
	bVendor_Error: BOOL;
	bVendor_Done: BOOL;
	bRead_Vendor: BOOL;

	
// X01 Product ID variable declaration for IO Link Read
	strProductID : STRING(32) := '';  //Variable in which the read result (Product ID) value will be copied
	fbIOLinkRead_ProductID: IL_ECATAoeRead;
		
	uiIoLinkPortNbr_ProductID  : UINT := 1;	//X1 = Plug, the IO-Link device is connected
	wIoLinkIndex_ProductID     : WORD := 19;//IO-Link index = 19 (product ID)
	byIoLinkSubIndex_ProductID : BYTE :=0;//IO-Link Subindex = 0 (product ID)
	
	bProductID_Error: BOOL;
	bProductID_Done: BOOL;
	bRead_ProductID: BOOL;
	
END_VAR
```

{% endcode %}

{% code title="PLC code" overflow="wrap" lineNumbers="true" %}

```iecst
//Read Aoe vendor ID
	//Read function
	fbIOLinkRead_Vendor(
	Execute:= bRead_Vendor,  //Execute bit 						
	MasterName:= ADR(strMasterName), //Instance name
	SlaveAddress:= uiEthercatAddr,  //EtherCAT address of IO-Link master
	TargetNetId:= strTargetNetId ,  //Refer from ctrlX I/O
	TargetPort:= 16#1000 + uiIoLinkPortNbr_Vendor, //ADS communication port = 16#1000 + IO-Link port number 
	IndexGroup:= 16#F302, //Fixed for IFM IO-Link
	//IDXOFFS Index Offset 
	//Bits 0-7: IO-Link subindex
	//Bits 8-15: 00000000
	//Bits 16-31: IO-Link index
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_Vendor),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_Vendor)), 
	SizeOfValue:= SIZEOF(strVendor), //Byte requirement
	ValueAdr:= ADR(strVendor)); //Value
	
IF TRUE = fbIOLinkRead_Vendor.Done THEN
	bVendor_Error := FALSE;  // Reset error
	bVendor_Done := TRUE;    
END_IF;

IF TRUE = fbIOLinkRead_Vendor.Error THEN
	bVendor_Error := TRUE;   // Error handling
	bVendor_Done := FALSE;
END_IF;
	
//Read Aoe Product ID
	fbIOLinkRead_ProductID(
	Execute:= bRead_ProductID, 
	MasterName:= ADR(strMasterName), 
	SlaveAddress:= uiEthercatAddr, 
	TargetNetId:= strTargetNetId , 
	TargetPort:= 16#1000 + uiIoLinkPortNbr_ProductID, 
	IndexGroup:= 16#F302, 
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_ProductID),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_ProductID)), 
	SizeOfValue:= SIZEOF(strProductID), 
	ValueAdr:= ADR(strProductID), 
);

// -------------------- Reading Distance sensor process output --------------------

//Concatinate the byte 0 and byte 1
wData := IL_ConcatByte(GVL.rawbyte0,GVL.rawbyte1);

//Right shift the word by 4 bit
iDistance := WORD_TO_INT(SHR(wData,4));

//Defining limits
IF iDistance > 200 THEN
	iDistance := 200;
END_IF

IF iDistance < 5 THEN
	iDistance := 5;
END_IF

//Set point output
bOutput := GVL.rawbyte1.0;

//SignalLamp condition
IF bOutput = TRUE THEN
	GVL.segment1 := 2;
	GVL.segment2 := 2;
	GVL.segment3 := 2;
	GVL.segment4 := 2;
	GVL.segment5 := 2;
	ELSE
	GVL.segment1 := 4;
	GVL.segment2 := 4;
	GVL.segment3 := 4;
	GVL.segment4 := 4;
	GVL.segment5 := 4;
END_IF
```

{% endcode %}

### **Exam**ple 3: How to read the Set-Point of distance sensor in crtlX CORE?

{% code title="GVL declaration" overflow="wrap" lineNumbers="true" %}

```iecst
{attribute 'qualified_only'}
VAR_GLOBAL
	//Distance Sensor
	rawbyte0 AT %IB0 : BYTE;
	rawbyte1 AT %IB1 : BYTE;

	//SignalLamp
	//Segment1
	segment1 AT %QB5 : BYTE;
	segment2 AT %QB4 : BYTE;
	segment3 AT %QB3 : BYTE;
	segment4 AT %QB2 : BYTE;
	segment5 AT %QB1 : BYTE;
END_VAR
```

{% endcode %}

{% code title="PLC variable declaration" overflow="wrap" lineNumbers="true" %}

```iecst
PROGRAM PLC_PRG
VAR
	wData : WORD;
	iDistance : INT;
	bOutput : BOOL;
	bySegment1 : BYTE;
	
// ---------------- Read AoE -----------------------------	

//Name of instance
	strMasterName : STRING := 'ethercatmaster';

//Ethercat address of ifm AL1332
	uiEthercatAddr : UINT := 1005;
	strTargetNetId   : IL_ECAT_AOE_NET_ID := (Byte0:= 172, Byte1:=31, Byte2:= 254, Byte3:= 254, Byte4:= 0, Byte5:= 1);

//Vendor variable declaration for IO Link read
	strVendor : STRING(32) := '';  				//Variable in which the read result (vendor) value will be copied
	fbIOLinkRead_Vendor: IL_ECATAoeRead;
		
	uiIoLinkPortNbr_Vendor  : UINT := 1;			//X1 = Plug, the IO-Link device is connected
	wIoLinkIndex_Vendor     : WORD := 16;    		//IO-Link index = 16 (vendor)
	byIoLinkSubIndex_Vendor : BYTE := 0; 		//IO-Link Subindex = 0 (vendor)
	
	bVendor_Error: BOOL;
	bVendor_Done: BOOL;
	bRead_Vendor: BOOL;

	
// X01 Product ID variable declaration for IO Link Read
	strProductID : STRING(32) := '';  			//Variable in which the read result (Product ID) value will be copied
	fbIOLinkRead_ProductID: IL_ECATAoeRead;
		
	uiIoLinkPortNbr_ProductID  : UINT := 1;		//X1 = Plug, the IO-Link device is connected
	wIoLinkIndex_ProductID     : WORD := 19;    	//IO-Link index = 19 (product ID)
	byIoLinkSubIndex_ProductID : BYTE :=0; 		//IO-Link Subindex = 0 (product ID)
	
	bProductID_Error: BOOL;
	bProductID_Done: BOOL;
	bRead_ProductID: BOOL;

// X01 Set point of Variable declaration for IO Link Read  
	uiSetPointRead: UINT;
	uiSetPointRead_swap: UINT; //Varible for byte swap output
	bRead_SetPoint: BOOL;
	
	fbIOLinkRead_ProductID_SetPoint: IL_ECATAoeRead;

	uiIoLinkPortNbr_ProductID_SetPoint  : UINT := 1;		//X1 = Plug, the IO-Link device is connected
	wIoLinkIndex_ProductID_SetPoint     : WORD := 60;    	//IO-Link index = 60 (Set Point)
	byIoLinkSubIndex_ProductID_SetPoint : BYTE := 1; 		//IO-Link Subindex = 1 (Set Point)
	
	bProductID_SetPoint_Error: BOOL;
	bProductID_SetPoint_Done: BOOL;
	
END_VAR
```

{% endcode %}

{% code title="PLC code" overflow="wrap" lineNumbers="true" %}

```iecst
//Read Aoe vendor ID
	
	//Read function
	fbIOLinkRead_Vendor(
	Execute:= bRead_Vendor,  //Execute bit 						
	MasterName:= ADR(strMasterName), //Instance name
	SlaveAddress:= uiEthercatAddr,  //EtherCAT address of IO-Link master
	TargetNetId:= strTargetNetId ,  //Refer from ctrlX I/O
	TargetPort:= 16#1000 + uiIoLinkPortNbr_Vendor, //ADS communication port = 16#1000 + IO-Link port number 
	IndexGroup:= 16#F302, //Fixed for IFM IO-Link
	//IDXOFFS Index Offset 
	//Bits 0-7: IO-Link subindex
	//Bits 8-15: 00000000
	//Bits 16-31: IO-Link index
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_Vendor),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_Vendor)), 
	SizeOfValue:= SIZEOF(strVendor), //Byte requirement
	ValueAdr:= ADR(strVendor)); //Value
	
IF TRUE = fbIOLinkRead_Vendor.Done THEN
	bVendor_Error := FALSE;  // Reset error
	bVendor_Done := TRUE;    
END_IF;

IF TRUE = fbIOLinkRead_Vendor.Error THEN
	bVendor_Error := TRUE;   // Error handling
	bVendor_Done := FALSE;
END_IF;
	
//Read Aoe Product ID
	fbIOLinkRead_ProductID(
	Execute:= bRead_ProductID, 
	MasterName:= ADR(strMasterName), 
	SlaveAddress:= uiEthercatAddr, 
	TargetNetId:= strTargetNetId , 
	TargetPort:= 16#1000 + uiIoLinkPortNbr_ProductID, 
	IndexGroup:= 16#F302, 
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_ProductID),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_ProductID)), 
	SizeOfValue:= SIZEOF(strProductID), 
	ValueAdr:= ADR(strProductID), 
);

//Read Aoe Product ID Set Point
fbIOLinkRead_ProductID_SetPoint(
	Execute:= bRead_SetPoint, 
	MasterName:= ADR(strMasterName), 
	SlaveAddress:= uiEthercatAddr, 
	TargetNetId:= strTargetNetId , 
	TargetPort:= 16#1000 + uiIoLinkPortNbr_ProductID_SetPoint, 
	IndexGroup:= 16#F302, 
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_ProductID_SetPoint),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_ProductID_SetPoint)), 
	SizeOfValue:= SIZEOF(uiSetPointRead), 
	ValueAdr:= ADR(uiSetPointRead), 
);

//Byte swap of Set Point read
uiSetPointRead_swap := WORD_TO_UINT(IL_SwapWord(uiSetPointRead));

IF TRUE = fbIOLinkRead_ProductID_SetPoint.Done THEN
	bProductID_SetPoint_Error := FALSE;  // Reset error
	bProductID_SetPoint_Done := TRUE;
END_IF;

IF TRUE = fbIOLinkRead_ProductID_SetPoint.Error THEN
	bProductID_SetPoint_Error := TRUE;  // Error handling
	bProductID_SetPoint_Done := FALSE;
END_IF;

// -------------------- Reading Distance sensor process output --------------------

//Concatinate the byte 0 and byte 1
wData := IL_ConcatByte(GVL.rawbyte0,GVL.rawbyte1);

//Right shift the word by 4 bit
iDistance := WORD_TO_INT(SHR(wData,4));

//Defining limits
IF iDistance > 200 THEN
	iDistance := 200;
END_IF

IF iDistance < 5 THEN
	iDistance := 5;
END_IF

//Set point output
bOutput := GVL.rawbyte1.0;

//SignalLamp condition
IF bOutput = TRUE THEN
	GVL.segment1 := 2;
	GVL.segment2 := 2;
	GVL.segment3 := 2;
	GVL.segment4 := 2;
	GVL.segment5 := 2;
	ELSE
	GVL.segment1 := 4;
	GVL.segment2 := 4;
	GVL.segment3 := 4;
	GVL.segment4 := 4;
	GVL.segment5 := 4;
END_IF
```

{% endcode %}

### **Exam**ple 4: How to write the Set-Point of distance sensor in crtlX CORE?

{% code title="GVL declaration" overflow="wrap" lineNumbers="true" %}

```iecst
{attribute 'qualified_only'}
VAR_GLOBAL
	//Distance Sensor
	rawbyte0 AT %IB0 : BYTE;
	rawbyte1 AT %IB1 : BYTE;

	//SignalLamp
	//Segment1
	segment1 AT %QB5 : BYTE;
	segment2 AT %QB4 : BYTE;
	segment3 AT %QB3 : BYTE;
	segment4 AT %QB2 : BYTE;
	segment5 AT %QB1 : BYTE;
END_VAR
```

{% endcode %}

{% code title="PLC variables declaration" overflow="wrap" lineNumbers="true" %}

```iecst
PROGRAM PLC_PRG 
VAR 

wData : WORD; 
iDistance : INT; 
bOutput : BOOL; 
bySegment1 : BYTE;

// ---------------- Read AoE -----------------------------
//Name of instance
strMasterName : STRING := 'ethercatmaster';
//Ethercat address of ifm AL1332 
uiEthercatAddr : UINT := 1005; strTargetNetId : IL_ECAT_AOE_NET_ID := (Byte0:= 172, Byte1:=31, Byte2:= 254, Byte3:= 254, Byte4:= 0, Byte5:= 1);

//Vendor variable declaration for IO Link read 
strVendor : STRING(32) := ''; //Variable in which the read result (vendor) value will be copied 
fbIOLinkRead_Vendor: IL_ECATAoeRead;
uiIoLinkPortNbr_Vendor  : UINT := 1;//X1 = Plug, the IO-Link device is connected
wIoLinkIndex_Vendor     : WORD := 16; 	//IO-Link index = 16 (vendor)
byIoLinkSubIndex_Vendor : BYTE := 0; 	//IO-Link Subindex = 0 (vendor)
bVendor_Error: BOOL;
bVendor_Done: BOOL;
bRead_Vendor: BOOL;

// X01 Product ID variable declaration for IO Link Read 
strProductID : STRING(32) := ''; //Variable in which the read result (Product ID) value will be copied 
fbIOLinkRead_ProductID: IL_ECATAoeRead;
uiIoLinkPortNbr_ProductID  : UINT := 1;	//X1 = Plug, the IO-Link device is connected
wIoLinkIndex_ProductID     : WORD := 19; //IO-Link index = 19 (product ID)
byIoLinkSubIndex_ProductID : BYTE :=0; 	//IO-Link Subindex = 0 (product ID)
bProductID_Error: BOOL;
bProductID_Done: BOOL;
bRead_ProductID: BOOL;

// X01 Set point of Variable declaration for IO Link Read 
uiSetPointRead: UINT;
uiSetPointRead_swap: UINT; //Varible for byte swap output
bRead_SetPoint: BOOL;
fbIOLinkRead_ProductID_SetPoint: IL_ECATAoeRead;
uiIoLinkPortNbr_ProductID_SetPoint  : UINT := 1;//X1 = Plug, the IO-Link device is connected
wIoLinkIndex_ProductID_SetPoint     : WORD := 60;//IO-Link index = 60 (Set Point)
byIoLinkSubIndex_ProductID_SetPoint : BYTE := 1; //IO-Link Subindex = 1 (Set Point)
bProductID_SetPoint_Error: BOOL;
bProductID_SetPoint_Done: BOOL;

//------------------Write AoE------------------------- 
uiSetPointWrite : UINT := 25;
uiSetPointWrite_swap: UINT;
bWrite_SetPoint: BOOL;
fbIOLinkWrite_ProductID_SetPoint_write: IL_ECATAoeWrite;
bProductID_SetPoint_Write_Error: BOOL;
bProductID_SetPoint_Write_Done: BOOL;

END_VAR
```

{% endcode %}

{% code title="PLC code" overflow="wrap" lineNumbers="true" %}

```iecst
//Read Aoe vendor ID
	
	//Read function
	fbIOLinkRead_Vendor(
	Execute:= bRead_Vendor,  //Execute bit 						
	MasterName:= ADR(strMasterName), //Instance name
	SlaveAddress:= uiEthercatAddr,  //EtherCAT address of IO-Link master
	TargetNetId:= strTargetNetId ,  //Refer from ctrlX I/O
	TargetPort:= 16#1000 + uiIoLinkPortNbr_Vendor, //ADS communication port = 16#1000 + IO-Link port number 
	IndexGroup:= 16#F302, //Fixed for IFM IO-Link
	//IDXOFFS Index Offset 
	//Bits 0-7: IO-Link subindex
	//Bits 8-15: 00000000
	//Bits 16-31: IO-Link index
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_Vendor),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_Vendor)), 
	SizeOfValue:= SIZEOF(strVendor), //Byte requirement
	ValueAdr:= ADR(strVendor)); //Value
	
IF TRUE = fbIOLinkRead_Vendor.Done THEN
	bVendor_Error := FALSE;  // Reset error
	bVendor_Done := TRUE;    
END_IF;

IF TRUE = fbIOLinkRead_Vendor.Error THEN
	bVendor_Error := TRUE;   // Error handling
	bVendor_Done := FALSE;
END_IF;
	
//Read Aoe Product ID
	fbIOLinkRead_ProductID(
	Execute:= bRead_ProductID, 
	MasterName:= ADR(strMasterName), 
	SlaveAddress:= uiEthercatAddr, 
	TargetNetId:= strTargetNetId , 
	TargetPort:= 16#1000 + uiIoLinkPortNbr_ProductID, 
	IndexGroup:= 16#F302, 
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_ProductID),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_ProductID)), 
	SizeOfValue:= SIZEOF(strProductID), 
	ValueAdr:= ADR(strProductID), 
);

//Read Aoe Product ID Set Point
fbIOLinkRead_ProductID_SetPoint(
	Execute:= bRead_SetPoint, 
	MasterName:= ADR(strMasterName), 
	SlaveAddress:= uiEthercatAddr, 
	TargetNetId:= strTargetNetId , 
	TargetPort:= 16#1000 + uiIoLinkPortNbr_ProductID_SetPoint, 
	IndexGroup:= 16#F302, 
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_ProductID_SetPoint),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_ProductID_SetPoint)), 
	SizeOfValue:= SIZEOF(uiSetPointRead), 
	ValueAdr:= ADR(uiSetPointRead), 
);

//Byte swap of Set Point read
uiSetPointRead_swap := WORD_TO_UINT(IL_SwapWord(uiSetPointRead));

IF TRUE = fbIOLinkRead_ProductID_SetPoint.Done THEN
	bProductID_SetPoint_Error := FALSE;  // Reset error
	bProductID_SetPoint_Done := TRUE;
END_IF;

IF TRUE = fbIOLinkRead_ProductID_SetPoint.Error THEN
	bProductID_SetPoint_Error := TRUE;  // Error handling
	bProductID_SetPoint_Done := FALSE;
END_IF;


//Write Aoe Product ID Set Point
	//uiSetPointWrite_conv := ROR(SetPointWrite,8);
	uiSetPointWrite_swap := WORD_TO_UINT(IL_SwapWord(uiSetPointWrite));
	fbIOLinkWrite_ProductID_SetPoint_write(
	Execute:= bWrite_SetPoint, 
	MasterName:= ADR(strMasterName), 
	SlaveAddress:= uiEthercatAddr, 
	TargetNetId:= strTargetNetId, 
	TargetPort:= 16#1000 + uiIoLinkPortNbr_ProductID_SetPoint, 
	IndexGroup:= 16#F302, 
	IndexOffset:= (16#FFFF0000 AND SHL(ANY_TO_UDINT(wIoLinkIndex_ProductID_SetPoint),16))
					OR (16#000000FF AND ANY_TO_UDINT(byIoLinkSubIndex_ProductID_SetPoint)), 
	ValueAdr:= ADR(uiSetPointWrite_swap), 	
	SizeOfValue:= SIZEOF(uiSetPointWrite_swap), 
	//SizeOfValue:= 2,
);

IF TRUE = fbIOLinkWrite_ProductID_SetPoint_write.Done THEN
	bProductID_SetPoint_Write_Error := FALSE;// FB Finished -> Product name was read,
	bProductID_SetPoint_Write_Done := TRUE;
END_IF;

IF TRUE = fbIOLinkWrite_ProductID_SetPoint_write.Error THEN
	bProductID_SetPoint_Write_Error := TRUE;// Error handling
	bProductID_SetPoint_Write_Done := FALSE;
END_IF;


// -------------------- Reading Distance sensor process output --------------------

//Concatinate the byte 0 and byte 1
wData := IL_ConcatByte(GVL.rawbyte0,GVL.rawbyte1);

//Right shift the word by 4 bit
iDistance := WORD_TO_INT(SHR(wData,4));

//Defining limits
IF iDistance > 200 THEN
	iDistance := 200;
END_IF

IF iDistance < 5 THEN
	iDistance := 5;
END_IF

//Set point output
bOutput := GVL.rawbyte1.0;

//SignalLamp condition
IF bOutput = TRUE THEN
	GVL.segment1 := 2;
	GVL.segment2 := 2;
	GVL.segment3 := 2;
	GVL.segment4 := 2;
	GVL.segment5 := 2;
	ELSE
	GVL.segment1 := 4;
	GVL.segment2 := 4;
	GVL.segment3 := 4;
	GVL.segment4 := 4;
	GVL.segment5 := 4;
END_IF
```

{% endcode %}

### Example 5: Visualize the parameters on the Node-RED dashboard

<figure><img src="/files/32hf5E6pDI10XdZWReUS" alt="Node-RED Dashboard"><figcaption><p>Node-RED Dashboard</p></figcaption></figure>

{% file src="/files/ARdzIomXXsn8crYgPlPk" %}
Node-RED flow
{% endfile %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.codeandcompile.com/product-reviews/smart-devices/ctrlx-core/06-interfacing-ctrlx-core-with-io-link-master-using-ethercat.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
