
FUNCTION_BLOCK PM_6DOFMotion (*Move Xbot  6 DOF*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		TargetX : REAL; (*Target X position [mm]*)
		TargetY : REAL; (*Target Y position [mm]*)
		TargetZ : REAL; (*Target Z position [mm]*)
		TargetRX : REAL; (*Target RX: Tilt around X-axis [rad]*)
		TargetRY : REAL; (*Target RY: Tilt around Y-axis [rad]*)
		TargetRZ : REAL; (*Target RZ: Tilt around Z-axis [rad]*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*PM_Stop Error*)
		ErrorID : UINT; (*Error ID*)
		TravelTime : REAL; (*Expected travel time*)
		Done : BOOL; (*Stop Done*)
		Busy : BOOL; (*Stop Busy*)
	END_VAR
	VAR
		CmdCount : USINT; (*Command Counter*)
		CmdLbl : UINT; (*Internal cmd label*)
		Xmm2m : REAL; (*Convert mm to m X*)
		Ymm2m : REAL; (*Convert mm to m Y*)
		Zmm2m : REAL; (*Convert mm to m Z*)
		RXmrad2rad : REAL; (*RX convert mrad to rad*)
		RYmrad2rad : REAL; (*RY convert mrad to rad*)
		RZmrad2rad : REAL; (*RZ convert mrad to rad*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_Activate (*Activate Xbot*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Busy : BOOL; (*Busy*)
		Done : BOOL; (*Done*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Cmd Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ArcMotion (*Move in an Arc*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		TargetX : REAL; (*ArcMode = 0: Target X position [mm], ArcMode = 1 Center X position [mm]*)
		TargetY : REAL; (*ArcMode = 0: Target Y position [mm], ArcMode = 1 Center Y position [mm]*)
		Radius : REAL; (*ArcMode = 0: Radius = radius [m], ArcMode = 1, Radius = Angle(rad)*)
		FinalTanSpeed : REAL; (*Final Tangential speed [m/s]*)
		MaxTanSpeed : REAL; (*Maximum Tangential speed [m/s]*)
		MaxAccel : REAL; (*Maximum Acceleration [m/s2]*)
		PositionMode : USINT; (*0 = Absolute positioning, 1 = Relative*)
		ArcMode : USINT; (*0 = Target position and arc radius mode, 1 = Arc center and rotation angle (|rad|) mode*)
		Direction : USINT; (*0 = Clockwise, 1 = Counter clockwise*)
		ArcType : USINT; (*0 = Minor Arc (shortest path arc) 1 = Major arc (longest arc path)*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		TravelTime : REAL; (*Expected travel time*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdCount : USINT; (*Command Counter*)
		Xmm2m : {REDUND_UNREPLICABLE} REAL := 0.0; (*Convert mm to m X*)
		Ymm2m : {REDUND_UNREPLICABLE} REAL := 0.0; (*Convert mm to m Y*)
		CmdLbl : UINT; (*Internal cmd label*)
		Radmm2m : {REDUND_UNREPLICABLE} REAL := 0.0; (*Convert mm to m Radius*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_AsyncMotion (*Move Async - Xbots find their own path*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..ASYNC_MAX_XBOT] OF USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		NumOfXbot : USINT; (*Number of Xbot to control. min 1 max 4*)
		CmdLabel : UINT; (*Command Label*)
		TargetX : ARRAY[0..ASYNC_MAX_XBOT] OF REAL; (*Target X position [mm]*)
		TargetY : ARRAY[0..ASYNC_MAX_XBOT] OF REAL; (*Target Y position [mm*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdCount : USINT; (*Command Counter*)
		CmdLbl : UINT; (*Internal cmd label*)
		Xmm2m : ARRAY[0..ASYNC_MAX_XBOT] OF REAL; (*Convert mm to m X*)
		Ymm2m : ARRAY[0..ASYNC_MAX_XBOT] OF REAL; (*Convert mm to m Y*)
		count : USINT; (*var FOR loop*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ConfigDigitalInput (*Configure Digital input*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		NumOfDi : USINT; (*Number of Digital input to configure. min 1 max 22*)
		DiID : ARRAY[0..DI_MAX_DI] OF USINT; (*Array of digital input ID. min = 0 max 127*)
		DigitalID : ARRAY[0..DI_MAX_DI] OF USINT; (*ActionID = 1, DigitalID, ActionID = 2, Motion Macro ID*)
		ActionID : ARRAY[0..DI_MAX_DI] OF USINT; (*0 = Trigger Only, 1 = Reset Digital Output, 2 = Run Motion Macro*)
		TriggerXbotID : ARRAY[0..DI_MAX_DI] OF USINT; (*XbotID for trigger*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		count : USINT; (*var FOR loop*)
		CmdCount : USINT;
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ConfigDigitalOutput (*Configure digital output*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		NumOfDo : USINT; (*Number of Digital Outputs to configure. min 1 max 5*)
		CmdLabel : UINT; (*Command Label*)
		PosFactorA : ARRAY[0..DO_MAX_DO] OF REAL; (*Position Factor A in AX+BY. Ignored if TriggerMode = 0.*)
		PosFactorB : ARRAY[0..DO_MAX_DO] OF REAL; (*Position Factor B in AX+BY. Ignored if TriggerMode = 0.*)
		DoCmdLabel : ARRAY[0..DO_MAX_DO] OF UINT; (*Cmd Label to monitor*)
		ForceThreshold : ARRAY[0..DO_MAX_DO] OF REAL; (*Force or Torque threshold (N or Nm)*)
		DoID : ARRAY[0..DO_MAX_DO] OF USINT; (*Array of digital output ID. min = 0 max 127*)
		EventID : ARRAY[0..DO_MAX_DO] OF USINT; (*1 = Motion Starting, 2 = Motion Ending, 3 = CmdLabel Cmd Starting, 4 = CmdLabel Cmd Ending, 5 = Displacement rising above threshold, 6 = Displacement falling below threshold, 7 = Force rising above theshold, 8 = Force falling below threshold, 128 = Motion state, 129 = CmdLabel state, 130 = Displacement state, 131 Force state*)
		TriggerMode : ARRAY[0..DO_MAX_DO] OF USINT; (*0 = X Only, 1 = Y Only, 2 = AX+BY*)
		DisplacementTrigger : ARRAY[0..DO_MAX_DO] OF REAL; (*Array of Displacement trigger treshold [mm]*)
		AxesID : {REDUND_UNREPLICABLE} ARRAY[0..DO_MAX_DO] OF USINT; (*Array of Streaming Axes ID. Bitmap Bit[5:0] : [RZ,RY,RX,Z,Y,X]*)
		TriggerXbotID : ARRAY[0..DO_MAX_DO] OF USINT; (*XbotID for trigger*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		count : USINT; (*var FOR loop*)
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
		DispTriggmm2m : ARRAY[0..DO_MAX_DO] OF REAL; (*Convert displacement trigger [mm] to [m]*)
		PosFacAmm2m : ARRAY[0..DO_MAX_DO] OF REAL; (*Position Factor A mm to m*)
		PosFacBmm2m : ARRAY[0..DO_MAX_DO] OF REAL; (*Position Factor B mm to m*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_Deactivate (*Deactive Xbot*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Busy : BOOL; (*Busy*)
		Done : BOOL; (*Done*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*internal Cmd Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_DigitalInput (*Payload Weighing*)
	VAR_INPUT
		DigitalInput : ARRAY[0..DIGITALINPUT_MAX_DI] OF BOOL;
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
	END_VAR
	VAR
		count : UINT; (*var FOR loop*)
		k : USINT; (*var FOR loop*)
		Sum : USINT; (*Internal sum to assign digital input*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_EditMacro (*Create macro*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		MacroID : USINT; (*Macro ID,  ID between 128 to 191*)
		MacroOption : USINT; (*0 = Clear motion commands in Macro, 2= End editing and save Macro, 4 = Query macro status *)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		MacroState : USINT; (*Macro State: 0 = Inactive, 1 = Active(Ready to be run)*)
		NumOfCmd : UINT; (*Number of motion commands in macro*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_FeedbackStreamConfig (*Configure Feedback stream*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		NumOfConfig : USINT; (*Number of feedback streams slots to configure (from 1 to 8)*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..FEEDBACKCONFIG_MAX_XBOT] OF USINT; (*XbotID*)
		StreamID : ARRAY[0..FEEDBACKCONFIG_MAX_XBOT] OF USINT; (*StreamID Valid stream Ids are in the range of [3,10] ??*)
		FeedbackMode : ARRAY[0..FEEDBACKCONFIG_MAX_XBOT] OF USINT; (*Feedback Mode (Bitmap) BIT structure [RZ,RY,RX,Z,Y,X]*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command counter*)
		count : USINT; (*var FOR loop*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ForceMode (*Force mode: Currently only in Z. Input for all 6DOF*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		ForceMode : USINT; (*0 = Exit Force mode (enter position mode) 1 = Enter Force mode*)
		XForce : REAL; (*Force X Axis [N]. Must be 0*)
		YForce : REAL; (*Force Y Axis [N]. Must be 0*)
		ZForce : REAL; (*Force Z Axis [N]: Allowable range: -10N to 15 N for XBOT M03-06, -40 to 60N for XBOT M03-11*)
		RXForce : REAL; (*RX Force [Nm] Must be 0*)
		RYForce : REAL; (*RY Froce [Nm] Must be 0*)
		RZForce : REAL; (*RZ Force [Nm] Must be 0*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GetFlywayStatus (*Get flyways status*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		FlywayID : USINT; (*Flyway ID*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Power : REAL; (*Power Consumption*)
		PaTemp : USINT; (*PA Temp*)
		CpuTemp : USINT; (*CPU Temp*)
		MotorTemp : USINT; (*Motor Temp*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GetMacroList
	VAR_INPUT
		FileDevice : STRING[80];
		Read : BOOL;
	END_VAR
	VAR_OUTPUT
		NumOfMacro : {REDUND_UNREPLICABLE} UDINT;
		MacroList : {REDUND_UNREPLICABLE} ARRAY[0..NUM_MACRO_FILES] OF STRING[260];
		Error : {REDUND_UNREPLICABLE} BOOL;
		Done : {REDUND_UNREPLICABLE} BOOL;
		Busy : {REDUND_UNREPLICABLE} BOOL;
		ErrorID : {REDUND_UNREPLICABLE} UINT;
	END_VAR
	VAR
		ReadDirState : READ_XML_DIRECTORY;
		DirInfo_0 : DirInfo;
		DirStatus : UINT;
		DirNum : UDINT;
		FileCount : INT;
		DirCreate_0 : DirCreate;
		DirRead_0 : DirRead;
		ReadData : fiDIR_READ_DATA;
		i : USINT;
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GetMoverProperties (*Read Xbot Settings*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to read settings from*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		MoverType : REAL; (*Mover Type*)
		PayloadWeight : REAL; (*Payload Weight g*)
		UserConfigCG : REAL; (*User configured Center of Gravity mm*)
		XMoverDim : REAL; (*Mover dimension in X mm*)
		YMoverDim : REAL; (*Mover dimension in Y mm*)
		AccLimit : REAL; (*Acceleration Limit*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GetPMCError (*Get PMC error codes*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		ErrorCode : ARRAY[0..PMC_MAX_ERROR] OF UDINT; (*ErrorCode*)
		NumberOfErrors : USINT; (*Number of errors (Max 7)*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GetPMCStatus (*Get PMC Status (Power, Temp)*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		NumOfXbot : UINT; (*Number of Xbot in system*)
		PMCState : USINT; (*PMC State*)
		Power : REAL; (*Power Consumption*)
		PaTemp : USINT; (*Maximum PA Temp*)
		CpuTemp : USINT; (*Maximum CPU Temp*)
		MotorTemp : USINT; (*Maximum Motor Temp*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Commad Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GetXbotStatus (*Get Xbot status*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID, Must be positive integer*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		XbotState : USINT; (*Xbot State*)
		CurrentMode : USINT; (*Bit 0 to 5 represent the control mode of X, Y, Z, RX, Ry, RZ. 0 = position controlled mode, 1 = Force controlled mode*)
		CurrCmdLabel : UINT; (*Current CmdLabel of executing command. If idle, returns 0xFFFF if idle.*)
		MotionBuffer : USINT; (*Motion Buffer status. 0 = buffer unblocked, 1 = buffer blocked. Bit *)
		NumOfMotionCmd : UINT; (*Number of motion commands in buffer*)
		XPos : REAL; (*X Position*)
		YPos : REAL; (*Y Position*)
		ZPos : REAL; (*Z Position*)
		RXPos : REAL; (*RX Position*)
		RYPos : REAL; (*RY Position*)
		RZPos : REAL; (*RZ Position*)
		GroupID : USINT; (*Group ID, if 0, Xbot is not in group*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Busy : BOOL; (*Busy*)
		Done : BOOL; (*Done*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_GroupOp (*Assign Xbots in group*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		NumOfXbot : USINT; (*Number of Xbot to control. min 1 max 4*)
		GroupID : USINT; (*ID of the Group, 0 = all group, max 10 groups*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..GROUP_MAX_XBOT] OF USINT; (*XbotID, 0 = All*)
		CmdLabel : UINT; (*Command Label*)
		GroupOption : USINT; (*0 = Add Xbot to empty group, 1 = Clear Group, 2 = Connect all Xbot, 3 = Disconnect Group, 4 = Block motion buffers for all XBOT in group, 5 = Release motion buffer for all XBOT in group, Query status of groups*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		NumXbotGroup : USINT; (*Number of xbot in group*)
		ConnectedStatus : USINT; (*Connected status. 0x0 = Disconnected. 0x1 = Connected*)
		GroupXbotID : ARRAY[0..GROUP_MAX_XBOT] OF USINT; (*List of Xbot ID in group. Listed in the order they were added.*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
		count : USINT; (*var FOR loop*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_Land (*Land Xbot*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to land shuttle. 0 means all.*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*PM_Stop Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Stop Done*)
		Busy : BOOL; (*Stop Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*internal Cmd Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_Levitate (*Levitate Xbot*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to Levitate shuttle. 0 means all.*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		CmdLabel : UINT; (*Command Label*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Cmd Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_LinearMotion (*Move Xbot linear*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		TargetX : REAL; (*Target X position [mm]*)
		CmdLabel : UINT; (*Command Label*)
		TargetY : REAL; (*Target Y position [mm*)
		FinalSpeed : REAL; (*Final speed [m/s]*)
		MaxSpeed : REAL; (*Maximum speed [m/s]*)
		MaxAccel : REAL; (*Maximum Acceleration [m/s2]*)
		PositionMode : USINT; (*0 = Absolute positioning, 1 = Relative*)
		PathType : USINT; (*0 = X and Y, 1 = First X then Y, 2 = First Y then X*)
	END_VAR
	VAR_OUTPUT
		TravelTime : REAL; (*Expected travel time*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdCount : USINT; (*Command Counter*)
		CmdLbl : UINT; (*Internal cmd label*)
		Xmm2m : REAL; (*Convert mm to m X*)
		Ymm2m : REAL; (*Convert mm to m Y*)
	END_VAR
END_FUNCTION_BLOCK

{REDUND_ERROR} FUNCTION_BLOCK PM_LoadMacroFromXml (*TODO: Add your comment here*) (*$GROUP=User,$CAT=User,$GROUPICON=User.png,$CATICON=User.png*)
	VAR_INPUT
		FileDevice : STRING[80];
		FileName : STRING[80];
		Load : BOOL;
		MacroID : USINT;
		MsgFrame : {REDUND_UNREPLICABLE} UDINT; (*Pointer to Profinet output message frame*)
		ReadFrame : {REDUND_UNREPLICABLE} UDINT; (*Pointer to profinet input message frame*)
	END_VAR
	VAR_OUTPUT
		Error : {REDUND_UNREPLICABLE} BOOL;
		Done : {REDUND_UNREPLICABLE} BOOL;
		NumberOfCommands : {REDUND_UNREPLICABLE} USINT;
		Busy : {REDUND_UNREPLICABLE} BOOL;
		ErrorInfo : {REDUND_UNREPLICABLE} InfoType;
	END_VAR
	VAR
		PM_ArcMotion_0 : PM_ArcMotion;
		PM_LinearMotion_0 : PM_LinearMotion;
		PM_EditMacro_0 : PM_EditMacro;
		PM_ShortAxisMotion_0 : PM_ShortAxisMotion;
		PM_WaitUntil_0 : PM_WaitUntil;
		PM_RunMacro_0 : PM_RunMacro;
		XmlState : XML_READ_STATE_ENUM;
		ErrorState : INT;
		FileOpen_0 : FileOpen;
		FileIdent : UDINT;
		FileRead_0 : FileRead;
		XmlData : ARRAY[0..10024] OF USINT;
		xmlCreateMemoryReader_0 : xmlCreateMemoryReader;
		XmlIdent : UDINT;
		xmlReadNextNode_0 : xmlReadNextNode;
		ElementName : STRING[80];
		ElementValue : STRING[80];
		AttrIndex : USINT;
		xmlReadAttributeNr_0 : xmlReadAttributeNr;
		AttributeName : STRING[80];
		AttributeValue : STRING[80];
		ErrorCount : USINT;
		xmlCloseMemoryReader_0 : xmlCloseMemoryReader;
		FileClose_0 : FileClose;
		Info : InfoType;
		WaitUntil : PMWaitUntilType;
		TargetPosition : PMTargetPositionType;
		ReadMacroStatus : UINT;
		IsClosed : BOOL;
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_MotionBuffer (*Handle motion buffer, block, release, clear*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID, 0 = All*)
		CmdLabel : UINT; (*Command Label*)
		BufferOption : USINT; (*0 = Block buffer, 1 = Release Buffer, 2 = Clear Buffer, 3 = Get motion buffer status*)
	END_VAR
	VAR_OUTPUT
		BufferStatus : USINT; (*0x0 = Buffer unblocked. 0x1 = Buffer blocked*)
		NumOfCmd : UINT; (*Number of motion commands in buffer*)
		FirstCmdLbl : UINT; (*Cmd label of the first motion command in the buffer. = 0xFFFE if buffer is empty*)
		FinalCmdLbl : UINT; (*Cmd label of the final motion command in the buffer. = 0xFFFE if buffer is empty*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_PayloadWeighing (*Payload Weighing*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*Xbot ID*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*PM_Stop Error*)
		Weight : REAL; (*Payload Weight [g]*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Stop Done*)
		Busy : BOOL; (*Stop Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT;
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_PlanetGroup (*Edit planet group*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		PlanetOption : USINT; (*0x0 = Remove planet Xbots from Star Xbot, 1 = Add planet Xbot to Star Xbot*)
		StarXbotID : USINT; (*Star Xbot ID*)
		NumOfPlanetXbot : USINT; (*NumberOfPlanetXbots*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..GROUP_MAX_XBOT] OF USINT; (*Planet XbotID*)
	END_VAR
	VAR_OUTPUT
		Busy : BOOL; (*Busy*)
		Done : BOOL; (*Done*)
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
	END_VAR
	VAR
		count : USINT; (*var FOR loop*)
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Cmd Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ReadFeedbackStream (*Read configured feedback stream*)
	VAR_INPUT
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		NumOfStream : {REDUND_UNREPLICABLE} USINT; (*Number of Xbots in stream*)
		StreamXbotID : {REDUND_UNREPLICABLE} ARRAY[0..MAX_FEEDBACK_AXIS] OF USINT; (*Xbot Stream ID. Starting form 3..10. ADD 3 to value.*)
		FeedbackMode : {REDUND_UNREPLICABLE} USINT; (*Feedback Mode (Bitmap) BIT structure [RZ,RY,RX,Z,Y,X]*)
		CycleTime : {REDUND_UNREPLICABLE} REAL; (*Cycle time for velocity calc*)
	END_VAR
	VAR_OUTPUT
		XPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*X Position [mm]*)
		YPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*Y Position [mm]*)
		ZPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*Z Position [mm]*)
		RXPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*RX Position [mm]*)
		RYPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*RY Position [mm]*)
		RZPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*RZ Position [mm]*)
		XForce : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*X Force [N]*)
		YForce : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*Y Force [N]*)
		ZForce : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*Z Force [N]*)
		RXForce : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*RX Force [Nm]*)
		RYForce : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*RY Force [Nm]*)
		RZForce : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*RZ Force [Nm]*)
		XbotID : ARRAY[0..MAX_FEEDBACK_AXIS] OF USINT;
		Velocity : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*X, Y velocity*)
	END_VAR
	VAR
		count : UINT; (*var FOR loop*)
		FeedbackCheck : BOOL; (*Check which feedbackmode is available.*)
		inc : INT; (*Internal inc variable*)
		OldYPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*Used to calculate x,y velocity*)
		OldXPos : ARRAY[0..MAX_FEEDBACK_AXIS] OF REAL; (*Used to calculate x,y velocity*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ReadState (*Read reply frame*)
	VAR_INPUT
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
	END_VAR
	VAR_OUTPUT
		PMCState : USINT; (*PMC State*)
		XbotStatus : ARRAY[0..READSTATE_MAX_XBOT] OF USINT; (*Array of Xbot status*)
		DoStatus : ARRAY[0..READSTATE_MAX_DO] OF BOOL; (*Array of Digital output status*)
		XPos : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*X Position [mm]*)
		YPos : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*Y Position [mm]*)
		ZPos : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*Z Position [mm]*)
		RXPos : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*RX Position [mm]*)
		RYPos : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*RY Position [mm]*)
		RZPos : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*RZ Position [mm]*)
		XForce : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*X Force [N]*)
		YForce : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*Y Force [N]*)
		ZForce : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*Z Force [N]*)
		RXForce : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*RX Force [Nm]*)
		RYForce : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*RY Force [Nm]*)
		RZForce : ARRAY[0..READSTATE_MAX_XBOT] OF REAL; (*RZ Force [Nm]*)
		XbotID : ARRAY[0..READSTATE_MAX_XBOT] OF UINT; (*Xbot ID*)
		NumOfXbot : UINT; (*Number of xbot*)
		ReplyCmdCount : USINT; (*Reply command counter. For logging purposes*)
		ReplyKeyword : UINT; (*Reply command keyword. For logging purposes*)
		ReplyCmdLbl : UINT; (*Reply command label. For logging purposes*)
		ReplyErrCode : UINT; (*Reply error code. For logging purposes*)
	END_VAR
	VAR
		count : USINT; (*var FOR loop*)
		index : USINT; (*Help index for Xbot status calc*)
		OldXbotID : UINT; (*PreviousXbotId. Used to detect max num of xbot*)
		CurrXbotID : UINT; (*Xbot ID for current Frame*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_RebootPMC (*Reebot PMC*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_RunMacro (*Run macro*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to run the command.  To create a loop - run the Macro ID once.*)
		CmdLabelOption : USINT; (*0 = Display motion label, 1 = Display macro label*)
		CmdLabel : UINT; (*Command Label*)
		MacroID : USINT; (*Macro ID,  ID between 128 to 255*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_SetMoverProperties (*Write Xbot Settings*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Edgepos*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		NumOfSettings : USINT; (*Number of Xbots to configure*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..WRITESETTING_MAX_XBOT] OF USINT; (*XbotID*)
		PropertyValue : ARRAY[0..WRITESETTING_MAX_XBOT] OF REAL; (*Property value*)
		PropertyID : ARRAY[0..WRITESETTING_MAX_XBOT] OF USINT; (*Property ID: 0 = Mover Type, 1 = User configured payload, 2 = User Configured CG in Z, 3 = Mover X Dimension, 4 = Reserved, 5 = Mover Y Dimension, 6  = Reserved, 7 = Acceleration Limit*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		PropertyValmm2m : ARRAY[0..WRITESETTING_MAX_XBOT] OF REAL; (*Convert mm 2 m*)
		CmdCount : USINT;
		count : USINT; (*var FOR loop*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_ShortAxisMotion (*Move Z, RZ, RX and RY*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		TargetZ : REAL; (*Target Z position [mm]*)
		TargetRX : REAL; (*Target RX: Tilt around X-axis [rad]*)
		TargetRY : REAL; (*Target RY: Tilt around Y-axis [rad]*)
		TargetRZ : REAL; (*Target RZ: Tilt around Z-axis [rad]*)
		SpeedZ : REAL; (*Z direction travel speed*)
		SpeedRX : REAL; (*RX direction rotation speed*)
		SpeedRY : REAL; (*RY direction rotation speed*)
		SpeedRZ : REAL; (*RZ direction rotation speed*)
		PositionMode : USINT; (*0 = Absolute positioning, 1 = Relative*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		TravelTime : REAL; (*Expected travel time*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
		Zmm2m : REAL; (*Convert mm to m Z*)
		RXmrad2rad : REAL; (*RX convert mrad to rad*)
		RYmrad2rad : REAL; (*RY convert mrad to rad*)
		RZmrad2rad : REAL; (*RZ convert mrad to rad*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_Shuffle (*Make this a C class later. Assign PM_LinearMotion*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : {REDUND_UNREPLICABLE} UDINT; (*Pointer to Profinet output message frame*)
		ReadFrame : {REDUND_UNREPLICABLE} UDINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..15] OF USINT; (*XbotID to move shuttle*)
		NumOfXbot : {REDUND_UNREPLICABLE} UINT; (*Pointer to profinet input message frame*)
		DistanceLimit : {REDUND_UNREPLICABLE} REAL; (*Pointer to profinet input message frame*)
		NumOfMoves : {REDUND_UNREPLICABLE} USINT; (*Pointer to profinet input message frame*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		PM_LinearMotion_0 : ARRAY[0..15] OF PM_LinearMotion;
		PM_Stop_0 : PM_Stop;
		ShuffleState : PMShuffle_enum;
		i : INT;
		Rand_f_0 : ARRAY[0..31] OF Rand_f;
		AllMoved : BOOL;
		MoveCounter : USINT;
		TON_0 : TON;
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_Stop (*Stop Xbot*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID to Stop shuttle. 0 means all.*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Cmd Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_StreamControl (*Configure Stream*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF USINT; (*Array of XbotID*)
		StreamID : {REDUND_UNREPLICABLE} ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF USINT; (*Array of StreamID*)
		StreamOption : USINT; (*StreamOption: 0 = Stop stream, 1 = Start Stream*)
		XOffset : ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF REAL; (* Array of X Offset start position [mm]*)
		YOffset : ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF REAL; (*Array of Y Offset start position [mm]*)
		AxesID : {REDUND_UNREPLICABLE} ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF USINT; (*Array of Streaming Axes ID. Bitmap Bit[5:0] : [RZ,RY,RX,Z,Y,X]*)
		CmdLabel : UINT; (*Command Label*)
		NumOfXbot : USINT; (*Number of Xbot to control. min 1 max 8*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		Xmm2m : ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF REAL; (*Convert mm to m X*)
		Ymm2m : ARRAY[0..STREAM_CONTROL_MAX_XBOT] OF REAL; (*Convert mm to m Y*)
		count : USINT; (*var FOR loop*)
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_SyncLinearMotion (*Move Xbots synchronously. Only linear movement*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..SYNC_MAX_XBOT] OF USINT; (*XbotID to move shuttle*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		CmdLabel : UINT; (*Command Label*)
		NumOfXbot : USINT; (*Number of Xbot to control. min 1 max 4*)
		TargetX : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Target X position [mm]*)
		TargetY : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Target Y position [mm*)
		FinalSpeed : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Final speed [m/s]*)
		MaxSpeed : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Maximum speed [m/s]*)
		MaxAccel : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Maximum Acceleration [m/s2]*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*PM_Stop Error*)
		TravelTime : REAL; (*Longest expected travel time among the xbots.*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Stop Done*)
		Busy : BOOL; (*Stop Busy*)
	END_VAR
	VAR
		CmdCount : USINT; (*Command Counter*)
		CmdLbl : UINT; (*Internal cmd label*)
		Xmm2m : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Convert mm to m X*)
	END_VAR
	VAR RETAIN
		Ymm2m : ARRAY[0..SYNC_MAX_XBOT] OF REAL; (*Convert mm to m Y*)
	END_VAR
	VAR
		count : USINT; (*var FOR loop*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_TrajectoryOp (*Follow trajectory*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} ARRAY[0..TRAJECTORY_MAX_XBOT] OF USINT; (*Array of XbotID*)
		TrajectoryID : {REDUND_UNREPLICABLE} ARRAY[0..TRAJECTORY_MAX_XBOT] OF USINT; (*Array of TrajectoryID*)
		CmdLabel : UINT; (*Command Label*)
		NumOfXbot : USINT; (*Number of Xbot to control. min 1 max 40*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		count : USINT; (*var FOR loop*)
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_UpdateSetPos (*Update Set position*)
	VAR_INPUT
		Execute : BOOL; (*Execute input. Updating each cycle when TRUE*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		StreamID : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF USINT; (*Array of StreamID*)
		XPos : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF REAL; (*Array of X set positions*)
		YPos : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF REAL; (*Array of Y set positions*)
		ZPos : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF REAL; (*Array of Z set positions*)
		RXPos : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF REAL; (*Array of RX set positions*)
		RYPos : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF REAL; (*Array of RY set positions*)
		RZPos : ARRAY[0..UPDATESTREAM_MAX_STREAMID] OF REAL; (*Array of RZ set positions*)
		NumOfStreamID : USINT;
	END_VAR
	VAR
		count : USINT; (*var FOR loop*)
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_WaitUntil (*Wait until event (time, trigger, threshold)*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to Profinet output message frame*)
		ReadFrame : REFERENCE TO ARRAY[0..MSG_LENGTH] OF USINT; (*Pointer to profinet input message frame*)
		XbotID : {REDUND_UNREPLICABLE} USINT; (*XbotID for Wait Command*)
		DigitalID : USINT; (*WaitMode = 1, DigitalID = ChannelID, WaitMode = 2 DigitalID = Fieldbus Digital Input ID *)
		PosFactorA : REAL; (*Position Factor A in AX+BY. Ignored by PMC if WaitMode <> 2 or 4*)
		PosFactorB : REAL; (*Position Factor B in AX+BY. Ignored by PMC if WaitMode <> 2 or 4*)
		DisplacementTrigger : REAL; (*Displacement trigger treshold [mm], ignored by PMC if WaitMode <> 4*)
		TriggerCmdLabel : UINT; (*Trigger command label*)
		TriggerMode : USINT; (*0 = X Only, 1 = Y Only, 2 = AX+BY*)
		TimeDelay : REAL; (*WaitMode = 0, Time delay [ms]*)
		TriggerType : USINT; (*WaitMode = 1,2  {0 = Rising Edge, 1 = Falling Edge, 2 = Equal to 1, 3 = Equal to 0}, WaitMode = 3 {0 = Staring Execution, 1= Finishing Execution, 2 0 During execution}, WaitMode = 4 { 0 = > threshold, 1 = < threhold, 2 = Rising above threshold, 3 = Falling below threshold}*)
		TriggerXbotID : USINT; (*XbotID for trigger*)
		WaitMode : USINT; (*0 = Time Delay mode, 1 = External Digital input mode, 2 = Fieldbus digital input mode, 3 = Command label mode, 4 = displacement mode*)
		CmdLabel : UINT; (*Command Label*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		CmdLbl : UINT; (*Internal cmd label*)
		CmdCount : USINT; (*Command Counter*)
		DispTriggmm2m : REAL; (*Convert displacement trigger [mm] to [m]*)
		PosFacAmm2m : REAL; (*Position Factor A mm to m*)
		PosFacBmm2m : REAL; (*Position Factor B mm to m*)
		TimeDelayms2s : REAL; (*Time delay ms to s*)
		Xmm2m : REAL;
	END_VAR
END_FUNCTION_BLOCK

FUNCTION_BLOCK PM_AsyncMotion_16 (*Async movement when shuttle > 8*)
	VAR_INPUT
		Execute : BOOL; (*Execute Cmd. Edge positive*)
		MsgFrame : {REDUND_UNREPLICABLE} UDINT; (*Pointer to Profinet output message frame*)
		ReadFrame : {REDUND_UNREPLICABLE} UDINT; (*Pointer to profinet input message frame*)
		NumOfXbot : USINT; (*Number of xbot*)
		XbotID : ARRAY[0..ASYNC16_NUM_XBOT] OF USINT; (*List of XBOT ID*)
		XTarget : ARRAY[0..ASYNC16_NUM_XBOT] OF REAL; (*List of X Target Position*)
		YTarget : ARRAY[0..ASYNC16_NUM_XBOT] OF REAL; (*List of Y Target Position*)
	END_VAR
	VAR_OUTPUT
		Error : BOOL; (*Error*)
		ErrorID : UINT; (*Error ID*)
		Done : BOOL; (*Done*)
		Busy : BOOL; (*Busy*)
	END_VAR
	VAR
		PM_AsyncMotion_0 : PM_AsyncMotion;
		PM_Shuffle_0 : PM_Shuffle;
		PM_ReadState_0 : PM_ReadState;
		SortedXPosition : ARRAY[0..ASYNC16_NUM_XBOT] OF REAL;
		SortedYPosition : ARRAY[0..ASYNC16_NUM_XBOT] OF REAL;
		SortedXbotID : ARRAY[0..ASYNC16_NUM_XBOT] OF USINT;
		XLimit : REAL;
		YLimit : REAL;
		LimitAxis : USINT; (*0 = X, 1 = Y*)
		i : INT;
		j : INT;
		k : INT;
		Async16State : ASYNC_MOVE_16_enum;
		temp : REAL;
		swapped : BOOL;
		LimitState : USINT;
		StandStill : BOOL;
		Side : ARRAY[0..1] OF Async16SideType;
		ErrorCountShuffle : USINT;
		Index : INT;
		InitXParam : REAL;
		InitYParam : REAL;
		TON_0 : TON;
		h : INT;
		InitParOK : BOOL;
		incMain : REAL;
		incSlave : REAL;
	END_VAR
END_FUNCTION_BLOCK

{REDUND_ERROR} FUNCTION ReadMacroParam : UINT (*TODO: Add your comment here*) (*$GROUP=User,$CAT=User,$GROUPICON=User.png,$CATICON=User.png*)
	VAR_INPUT
		TargetPosition : REFERENCE TO PMTargetPositionType;
		WaitUntil : REFERENCE TO PMWaitUntilType;
		AttributeValue : STRING[80];
		AttributeName : STRING[80];
	END_VAR
END_FUNCTION
