Send and retreive data using AsTCP

Can someone help me figure this out?

// This program uses the AsTCP standard library for TCP communication

PROGRAM _CYCLIC
VAR
// TCP Function Blocks
TcpClient1 : TcpOpen; // TCP client instance
TcpSend1 : TcpSend; // TCP send instance
TcpRecv1 : TcpRecv; // TCP receive instance
TcpClose1 : TcpClose; // TCP close instance

// Communication Variables
Hostname : STRING[50] := '192.168.1.10'; // Hostname for socket connection
PortNumber : UINT := 502;               // Port number
ConnectionID : DINT := -1;              // Connection ID for AsTCP
IsConnected : BOOL := FALSE;            // Connection status
WaitForAnswer : BOOL := FALSE;          // Flag for waiting for answer
Command : BYTE;                         // Current Command
BytesToRead : UINT := 0;                // Bytes to read
SendDataBuffer : ARRAY[0..255] OF BYTE; // Buffer for sending data
RecvDataBuffer : ARRAY[0..255] OF BYTE; // Buffer for receiving data
Status : UDINT;                         // Status variable for TCP operations

// Application-Specific Variables
Init_Data : INIT_DATA;                  // Struct for initialization data
ESA_Init : ESA_INIT;                    // Struct for ESA data

END_VAR

// Open Socket Connection using AsTCP
IF NOT IsConnected THEN
TcpClient1.enable := TRUE;
TcpClient1.pHost := ADR(Hostname); // Pointer to the hostname or IP address
TcpClient1.port := PortNumber; // Port number
TcpClient1.flags := 0; // Default connection flags
TcpClient1.pStatus := ADR(Status); // Pointer to status variable
TcpClient1.ident := ConnectionID; // Connection ID (output)

TcpOpen(TcpClient1);

IF TcpClient1.status = 0 THEN
    IsConnected := TRUE;
    ConnectionID := TcpClient1.ident;
    Command := 16#31;                   // Example Command
    BytesToRead := 1;
    WaitForAnswer := TRUE;
END_IF;

END_IF;

// Initialize Data and Send to Server
IF IsConnected THEN
// Populate Init_Data structure
Init_Data.RecordType := 16#01; // Example Record Type
Init_Data.TargetAngle := REAL_TO_INT(TargetAngle * 100);
Init_Data.V_Width := REAL_TO_INT(DieWidth * 100);
Init_Data.V_Radius := REAL_TO_INT(DieRadius * 100);
Init_Data.V_Angle := REAL_TO_INT(DieAngle * 100);
Init_Data.PrebendAngle := REAL_TO_INT(PrebendAngle * 100);
Init_Data.SheetThickness := REAL_TO_INT(SheetThickness * 100);
Init_Data.ClampingPoint := REAL_TO_INT(ClampingPoint * 100);
Init_Data.BendingRadius := REAL_TO_INT(BendingRadius * 100);
Init_Data.ProgrammedPressure := REAL_TO_INT(ProgrammedPressure);
Init_Data.EstimatedSpringBack := REAL_TO_INT(EstimatedSpringBack * 100);
Init_Data.CompensationFactor := CompensationFactor;
Init_Data.LeftCorrection := REAL_TO_INT(LeftCorrection * 100);
Init_Data.RightCorrection := REAL_TO_INT(RightCorrection * 100);
Init_Data.SensorPositionLeft := REAL_TO_INT(SensorPositionLeft * 100);
Init_Data.SensorPositionRight := REAL_TO_INT(SensorPositionRight * 100);
Init_Data.GlasScaleDist := REAL_TO_INT(GlassScaleDistance * 100);
Init_Data.MachineLength := MachineLength;
Init_Data.SensorSelection := 5; // Both sensors
Init_Data.bMeasureSpringBack := MeasureSpringBack;
Init_Data.EstimatedSpringBack2 := REAL_TO_INT(Prebend2 * 100);
Init_Data.DieIndex := DieIndex;
Init_Data.BendingMethod := BendingMethod;
Init_Data.SubBendMethod := SubBendMethod;

// Send Init_Data over TCP
TcpSend1.enable := TRUE;
TcpSend1.ident := ConnectionID;
TcpSend1.pData := ADR(Init_Data);
TcpSend1.datalen := SIZEOF(Init_Data);
TcpSend1.pStatus := ADR(Status);

TcpSend(TcpSend1);

IF TcpSend1.status = 0 THEN
    // Populate ESA_Init structure
    ESA_Init.MaterialIndex := MaterialIndex;
    ESA_Init.ExposureTimeCorrection := 100;            // Example Correction in %

    TcpSend1.enable := TRUE;
    TcpSend1.pData := ADR(ESA_Init);
    TcpSend1.datalen := SIZEOF(ESA_Init);

    TcpSend(TcpSend1);

    WaitForAnswer := TRUE;
    BytesToRead := 1;
END_IF;

END_IF;

// Close Connection (Optional)
IF WaitForAnswer AND NOT TcpRecv1.enable THEN
TcpClose1.enable := TRUE;
TcpClose1.ident := ConnectionID;
TcpClose1.pStatus := ADR(Status);

TcpClose(TcpClose1);

IF TcpClose1.status = 0 THEN
    IsConnected := FALSE;
    ConnectionID := -1;
END_IF;

END_IF;
END_PROGRAM

Am I the only one who cannot see any questions? What is your issue?

the question is at the very top.
I keep getting errors on the build starting with the VAR

OK, but the VAR part should not be inside the cyclic part of the task. For variable declaration, you have a special file *.var.

I have remarked that portion out and declared them manually .
now I get this issue

// Open Socket Connection using AsTCP
IF NOT IsConnected THEN
	TcpClient1.enable := TRUE;
	TcpClient1.pIfAddr := ADR(Hostname); // Pointer to the hostname or IP address
	TcpClient1.port := PortNumber; // Port number
	TcpClient1.options := 0; // Default connection flags
	TcpClient1.status := ADR(OStatus); // Pointer to status variable
	TcpClient1.ident := ConnectionID; // Connection ID (output)

Data type mismatch: Cannot convert UDINT to UINT.|1140|Ln: 49, Col: 21|C:\projects\OptibendESAnCYB_20241213_VALMONT_M6041\Logical\LaserCheck\LCTCP\Main.st|
No write access to variable ‘ident’ allowed.|1138|Ln: 50, Col: 20|C:\projects\OptibendESAnCYB_20241213_VALMONT_M6041\Logical\LaserCheck\LCTCP\Main.st|

if you insert library sample from object catalog, you do not need to declare anything.

Conversation you have to solve in your code. Since you can not copy longer data type to smaller one. And second problem, looks like you are trying to write ID to FUB output. This is not allowed.


I do have it in there

OK, so you have a user application library. That is fine. Still, data type conversion is the programmer’s responsibility. And you can not write to the FUB output. So, you have to solve this in your code as well.


The data types seem to be the same

ADR of any datatype is always UDINT

1 Like


Is this not the correct way to call the FB?

Is this not the correct way to call the FB?

not in case of ST

A function block is called in Structured Text (ST) by writing the name of the function block instance:

B&R Online Help

in this case it looks TcpClient1 is your instance variable

Does this look correct?

PROGRAM _CYCLIC


// Open Socket Connection using AsTCP
IF NOT IsConnected THEN
	TcpClient1.enable := TRUE;
	TcpClient1.pIfAddr := ADR(Hostname); // Pointer to the hostname or IP address
	TcpClient1.port := PortNumber; // Port number
	TcpClient1.options := 0; // Default connection flags
	//TcpClient1.status := ADR(OStatus); // Pointer to status variable
	//TcpClient1.ident := ConnectionID; // Connection ID (output)
	TcpClientstatus := ADR(OStatus);
	TcpClient1ident := ConnectionID;

	TcpClient1 := (TcpClient1);

	IF TcpClient1.status = 0 THEN
		IsConnected := TRUE;
		ConnectionID := TcpClient1.ident;
	//	Command := 16#31;                   // Example Command
		BytesToRead := 1;
		WaitForAnswer := TRUE;
	END_IF;
	
END_IF;

// Initialize Data and Send to Server
IF IsConnected THEN
	// Populate Init_Data structure
	Init_Data.RecordType := 16#01; // Example Record Type
	Init_Data.TargetAngle := REAL_TO_INT(TargetAngle * 100);
	Init_Data.V_Width := REAL_TO_INT(DieWidth * 100);
	Init_Data.V_Radius := REAL_TO_INT(DieRadius * 100);
	Init_Data.V_Angle := REAL_TO_INT(DieAngle * 100);
	Init_Data.PrebendAngle := REAL_TO_INT(PrebendAngle * 100);
	Init_Data.SheetThickness := REAL_TO_INT(SheetThickness * 100);
	Init_Data.ClampingPoint := REAL_TO_INT(ClampingPoint * 100);
	Init_Data.BendingRadius := REAL_TO_INT(BendingRadius * 100);
	Init_Data.ProgrammedPressure := REAL_TO_INT(ProgrammedPressure);
	Init_Data.EstimatedSpringBack := REAL_TO_INT(EstimatedSpringBack * 100);
	Init_Data.CompensationFactor := CompensationFactor;
	Init_Data.LeftCorrection := REAL_TO_INT(LeftCorrection * 100);
	Init_Data.RightCorrection := REAL_TO_INT(RightCorrection * 100);
	Init_Data.SensorPositionLeft := REAL_TO_INT(SensorPositionLeft * 100);
	Init_Data.SensorPositionRight := REAL_TO_INT(SensorPositionRight * 100);
	Init_Data.GlasScaleDist := REAL_TO_INT(GlassScaleDistance * 100);
	Init_Data.MachineLength := MachineLength;
	Init_Data.SensorSelection := 5; // Both sensors
	Init_Data.bMeasureSpringBack := MeasureSpringBack;
	Init_Data.EstimatedSpringBack2 := REAL_TO_INT(Prebend2 * 100);
	Init_Data.DieIndex := DieIndex;
	Init_Data.BendingMethod := BendingMethod;
	Init_Data.SubBendMethod := SubBendMethod;

	// Send Init_Data over TCP
	TcpSend1.enable := TRUE;
	TcpSend1.ident := ConnectionID;
	TcpSend1.pData := ADR(Init_Data);
	TcpSend1.datalen := SIZEOF(Init_Data);
	//TcpSend1.status := ADR(SStatus);

	TcpSend1 := (TcpSend1);

	IF TcpSend1.status = 0 THEN
		// Populate ESA_Init structure
		ESA_Init.MaterialIndex := MaterialIndex;
		ESA_Init.ExposureTimeCorrection := 100;            // Example Correction in %

		TcpSend1.enable := TRUE;
		TcpSend1.pData := ADR(ESA_Init);
		TcpSend1.datalen := SIZEOF(ESA_Init);

		TcpSend1 := (TcpSend1);

		WaitForAnswer := TRUE;
		BytesToRead := 1;
	END_IF;
	
END_IF;

// Close Connection (Optional)
IF WaitForAnswer AND NOT TcpRecv1.enable THEN
	TcpClose1.enable := TRUE;
	TcpClose1.ident := ConnectionID;
	//TcpClose1.status := ADR(RStatus);

	TcpClose1 := (TcpClose1);

	IF TcpClose1.status = 0 THEN
		IsConnected := FALSE;
		ConnectionID := -1;
	END_IF;
	
END_IF;
END_PROGRAM

Does this look correct?

still not.

TcpClient1();

and

TcpSend1();

is correct. And the parentheses can even be omitted.

And your function blocks must always be called cyclically, which is probably not the case within the IF / END_IF.

1 Like

Got it thanks for your help