Main

#info=SFCCHART
@I1:0,0=1;Initialization\n
@T2:1,0=1;
@S3:2,0=2;Starting Motion Engine\n
@T4:3,0=2;
@S44:4,0=3;
@T45:5,0=3;
@S6:6,0=4;
@O8:7,0=0;
@d9:7,1=0;
@d17:7,2=103;
@T28:8,0=4;
@T25:8,1=101;
@T18:8,2=201;
@S29:9,0=5;Manual Mode\n
@S43:9,1=101;Automatic Mode\n
@S37:9,2=201;Standby\n
@T30:10,0=5;
@T27:10,1=102;
@T20:10,2=202;
@O14:11,0=0;
@c15:11,1=0;
@c21:11,2=107;
@J16:12,0=4;
#endinfo
_step _init GS1;
#sfc=GS1(0,0)
__BEGIN_P1
Printf('Initialize Motion Engine', 0, 0, 0, 0);
// Initialize the motion engine
MLMotionInit(1000.0);
Profiles(MLPR_CREATE_PROFILES);

__END_ACTION
__BEGIN_P0
Printf('Create PLCopen Axes', 0, 0, 0, 0);
// Create PLCopen axes
// This will call the PLCopen compiled code
PLCopen(0);
__END_ACTION
#sfc=end
_next GT1;
_trans GT1;
#sfc=GT1(0,1)
MLSTATUS_INITIALISED = MLMotionStatus()
#sfc=end
_next GS2;
_step GS2;
#sfc=GS2(0,2)
__BEGIN_P1
Printf('Start Motion Engine', 0, 0, 0, 0);
// Start the motion engine
MLMotionStart();
__END_ACTION
__BEGIN_P0
Axis1.AXIS_NUM := 1;
LowerRotary.AXIS_NUM := 2;
UpperRotary.AXIS_NUM := 3;
LinearZAxis.AXIS_NUM := 4;

__END_ACTION
#sfc=end
_next GT2;
_trans GT2;
#sfc=GT2(0,3)
MLSTATUS_RUNNING = MLMotionStatus()
#sfc=end
_next GS3;
_step GS3;
#sfc=GS3(0,4)
__BEGIN_N
Inst_MC_CamTblSelect( TRUE, 'Profile1', TRUE, FALSE, FALSE );
Inst_MC_CamTblSelect1( TRUE, 'Profile2', TRUE, FALSE, FALSE );
Inst_MC_ReadParam( TRUE, LowerRotary, 1017 );
LowerECATAddress := Inst_MC_ReadParam.Value;
__END_ACTION
__BEGIN_P0
LinearStartingPos := ActPosLinear;
LinearClearedPosition := LinearStartingPos - 45;
Profile1ID := Inst_MC_CamTblSelect.CamTableID;
Profile2ID := Inst_MC_CamTblSelect1.CamTableID;
__END_ACTION
#sfc=end
_next GT3;
_trans GT3;
#sfc=GT3(0,5)
Inst_MC_CamTblSelect.Done AND Inst_MC_CamTblSelect1.Done
#sfc=end
_next GS4;
_step GS4;
#sfc=GS4(0,6)
__BEGIN_P0
OpenButton := FALSE;
__END_ACTION
#sfc=end
_next GT4, GT101, GT201;
_trans GT4;
#sfc=GT4(0,8)
MachineState = 0
#sfc=end
_next GS5;
_trans GT101;
#sfc=GT101(1,8)
MachineState = 1
#sfc=end
_next GS101;
_trans GT201;
#sfc=GT201(2,8)
MachineState = 2
#sfc=end
_next GS201;
_step GS5;
#sfc=GS5(0,9)
__BEGIN_N
//Jog commands for rotary axes
Inst_MC_MoveVelocity( Jog1Plus, Axis1, JogVelocity, Manual_A1_Accel, Manual_A1_Decel, 0, 0, 0 );
Inst_MC_MoveVelocity( Jog1Minus, Axis1, JogVelocity, Manual_A1_Accel, Manual_A1_Decel, 0, 1, 0 );
Inst_MC_MoveVelocity1( Jog2Plus, LowerRotary, JogVelocity2, Manual_A2_Accel, Manual_A2_Decel, 0, 0, 0 );
Inst_MC_MoveVelocity1( Jog2Minus, LowerRotary, JogVelocity2, Manual_A2_Accel, Manual_A2_Decel, 0, 1, 0 );
//Stop jog moves if button on HMI is no longer pushed
ON Not Jog1Plus AND Not Jog1Minus DO
   Inst_MC_Halt( FALSE, Axis1, 10000, 0, 0 );
   Inst_MC_Halt( TRUE, Axis1, 10000, 0, 0 );
END_DO;
ON Not Jog2Plus AND Not Jog2Minus DO
   Inst_MC_Halt1( FALSE, LowerRotary, 10000, 0, 0 );
   Inst_MC_Halt1( TRUE, LowerRotary, 10000, 0, 0 );
END_DO;
//Relative moves in Manual mode
Inst_MC_MoveRelative( RelMove1, Axis1, RelDistance, JogVelocity, Manual_A1_Accel, Manual_A1_Decel, 0, 0 );
Inst_MC_MoveRelative1( RelMove2, LowerRotary, RelDistance, JogVelocity, Manual_A1_Accel, Manual_A1_Decel, 0, 0 );
Inst_MC_MoveRelative4( RelMove3, UpperRotary, RelDistance, JogVelocity, Manual_A1_Accel, Manual_A1_Decel, 0, 0 );
Inst_MC_MoveRelative5( RelMove4, LinearZAxis, RelDistance, LinearVelocity, Manual_A2_Accel, Manual_A2_Decel, 0, 0 );
//Absolute moves in Manual mode
Inst_MC_MoveAbsolute( AbsMove1, Axis1, AbsPosition, JogVelocity, Manual_A1_Accel, Manual_A1_Decel, 0, 0, 0 );
Inst_MC_MoveAbsolute1( AbsMove2, LowerRotary, AbsPosition, JogVelocity2, Manual_A2_Accel, Manual_A2_Decel, 0, 0, 0 );


__END_ACTION
#sfc=end
_next GT5;
_step GS101;
#sfc=GS101(1,9)
__BEGIN_P1
//Reset state machine to zero
StepCounter := 0;
StopCycle := FALSE;
__END_ACTION
__BEGIN_N
(*
Case statement to control sequence of different moves commanded including
relative, absolute, s-curved, gearing, camming, superimposed and phasing.
Alternate between commanding moves and waiting for them to be finished before moving to next
case in the sequence.
*)
CASE StepCounter OF
0://Move Linear axis up so that two rotary axis are not engaged
Inst_MC_MoveAbsolute2( FALSE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
StepCounter := 1;
1://Wait until linear axis is moved up out of the way, then command relative move to rotary axes
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
IF Inst_MC_MoveAbsolute2.Done THEN
   Inst_MC_MoveRelative6( FALSE, UpperRotary, 90, 500, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative7( FALSE, LowerRotary, -90, 500, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative6( TRUE, UpperRotary, 90, 500, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative7( TRUE, LowerRotary, -90, 500, 10000, 10000, 0, 0 );
   StepCounter:= 2;
END_IF;
2://Wait until relative rotary moves are done, then lower the linear axis so hole punch pegs engage
Inst_MC_MoveRelative6( TRUE, UpperRotary, 90, 500, 10000, 10000, 0, 0 );
Inst_MC_MoveRelative7( TRUE, LowerRotary, -90, 500, 10000, 10000, 0, 0 );
IF Inst_MC_MoveRelative6.Done AND Inst_MC_MoveRelative7.Done THEN
   Inst_MC_MoveAbsolute2( FALSE, LinearZAxis, LinearStartingPos, 500, 10000, 10000, 0, 0, 0 );
   Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearStartingPos, 500, 10000, 10000, 0, 0, 0 );
   StepCounter := 3;
END_IF;
3://Wait until linear axis absolute move is complete, then command relative move to rotary axes
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearStartingPos, 500, 10000, 10000, 0, 0, 0 );
IF Inst_MC_MoveAbsolute2.Done THEN
   Inst_MC_MoveRelative6( FALSE, UpperRotary, 90, 500, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative7( FALSE, LowerRotary, -90, 500, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative6( TRUE, UpperRotary, 90, 500, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative7( TRUE, LowerRotary, -90, 500, 10000, 10000, 0, 0 );
   StepCounter:= 4;
END_IF;
4://Wait until relative rotary moves are done, then raise linear axis to pegs cleared position
Inst_MC_MoveRelative6( TRUE, UpperRotary, 90, 500, 10000, 10000, 0, 0 );
Inst_MC_MoveRelative7( TRUE, LowerRotary, -90, 500, 10000, 10000, 0, 0 );
IF Inst_MC_MoveRelative6.Done AND Inst_MC_MoveRelative7.Done THEN
   Inst_MC_MoveAbsolute2( FALSE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
   Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
   StepCounter := 5;
END_IF;
5://Wait until linear absolute move is complete, then command jerk limited relative moves to rotary axes
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
IF Inst_MC_MoveAbsolute2.Done THEN
   Inst_MC_MoveRelative6( FALSE, UpperRotary, 90, 500, 100, 100, 50, 0 );
   Inst_MC_MoveRelative7( FALSE, LowerRotary, -90, 500, 100, 100, 50, 0 );
   Inst_MC_MoveRelative6( TRUE, UpperRotary, 90, 500, 100, 100, 50, 0 );
   Inst_MC_MoveRelative7( TRUE, LowerRotary, -90, 500, 100, 100, 50, 0 );
   StepCounter:= 6;
END_IF;
6://Wait for jerk limited relative moves on rotary axes are complete, then change drive parameter and lower linear axis
Inst_MC_MoveRelative6( TRUE, UpperRotary, 90, 500, 100, 100, 50, 0 );
Inst_MC_MoveRelative7( TRUE, LowerRotary, -90, 500, 100, 100, 50, 0 );
IF Inst_MC_MoveRelative6.Done AND Inst_MC_MoveRelative7.Done THEN
   Inst_DriveParamWrite( FALSE, any_to_int(LowerECATAddress), 'VL.LIMITP', 2000 );
   Inst_DriveParamWrite( TRUE, any_to_int(LowerECATAddress), 'VL.LIMITP', 2000 );
   Inst_MC_MoveAbsolute2( FALSE, LinearZAxis, LinearStartingPos, 500, 200, 200, 100, 0, 0 );
   Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearStartingPos, 500, 200, 200, 100, 0, 0 );
   StepCounter := 7;
END_IF;
7://Wait until linear axis is lowered, then start gear relationship on the rotary axes
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearStartingPos, 500, 200, 200, 100, 0, 0 );
IF Inst_MC_MoveAbsolute2.Done THEN
   Inst_MC_GearIn3( FALSE, Axis1, UpperRotary, 3, 1, 10000, 10000, 0, 0 );
   Inst_MC_GearIn4( FALSE, Axis1, LowerRotary, -3, 1, 10000, 10000, 0, 0 );
   Inst_MC_GearIn3( TRUE, Axis1, UpperRotary, 3, 1, 10000, 10000, 0, 0 );
   Inst_MC_GearIn4( TRUE, Axis1, LowerRotary, -3, 1, 10000, 10000, 0, 0 );
   StepCounter:= 8;
END_IF;
8://Once rotary axes are geared, start a relative move on the master axis and raise the linear axis
Inst_MC_GearIn3( TRUE, Axis1, UpperRotary, 3, 1, 10000, 10000, 0, 0 );
Inst_MC_GearIn4( TRUE, Axis1, LowerRotary, -3, 1, 10000, 10000, 0, 0 );
IF Inst_MC_GearIn3.InGear AND Inst_MC_GearIn4.InGear THEN
   Inst_MC_MoveRelative8( FALSE, Axis1, 720, 300, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative8( TRUE, Axis1, 720, 300, 10000, 10000, 0, 0 );
   Inst_MC_MoveAbsolute2( FALSE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
   Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
   StepCounter := 9;
END_IF;
9://Wait for the linear axis to be raised
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearClearedPosition, 500, 10000, 10000, 0, 0, 0 );
IF Inst_MC_MoveAbsolute2.Done THEN
   StepCounter := 10;
END_IF;
10://Move the linear axis to the bottom position so hole punch pegs are engaged
Inst_MC_MoveAbsolute2( FALSE, LinearZAxis, LinearStartingPos, 500, 200, 200, 100, 0, 0 );
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearStartingPos, 500, 200, 200, 100, 0, 0 );
StepCounter := 11;
11://Wait for master relative move and the linear move to finish, then start CAM relationship on two rotary axes
Inst_MC_MoveAbsolute2( TRUE, LinearZAxis, LinearStartingPos, 500, 200, 200, 100, 0, 0 );
Inst_MC_MoveRelative8( TRUE, Axis1, 720, 300, 10000, 10000, 0, 0 );
IF Inst_MC_MoveRelative8.Done AND Inst_MC_MoveAbsolute2.Done THEN
   Inst_MC_CamIn2( FALSE, Axis1, UpperRotary, 0, 0, 360, 360, 0, Profile1ID, 0 );
   Inst_MC_CamIn3( FALSE, Axis1, LowerRotary, 0, 0, 360, 360, 0, Profile2ID, 0 );
   Inst_MC_CamIn2( TRUE, Axis1, UpperRotary, 0, 0, 360, 360, 0, Profile1ID, 0 );
   Inst_MC_CamIn3( TRUE, Axis1, LowerRotary, 0, 0, 360, 360, 0, Profile2ID, 0 );
   StepCounter := 12;
END_IF;
12://Once CAM relationship is started, command relative move to the master
Inst_MC_CamIn2( TRUE, Axis1, UpperRotary, 0, 0, 360, 360, 0, Profile1ID, 0 );
Inst_MC_CamIn3( TRUE, Axis1, LowerRotary, 0, 0, 360, 360, 0, Profile2ID, 0 );
IF Inst_MC_CamIn2.InSync AND Inst_MC_CamIn3.InSync THEN
   Inst_MC_MoveRelative8( FALSE, Axis1, 720, 300, 10000, 10000, 0, 0 );
   Inst_MC_MoveRelative8( TRUE, Axis1, 720, 300, 10000, 10000, 0, 0 );
   StepCounter := 13;
END_IF;
13://Once master relative move is complete, start up a new gear relationship on the rotary axes
Inst_MC_MoveRelative8( TRUE, Axis1, 720, 300, 10000, 10000, 0, 0 );
IF Inst_MC_MoveRelative8.Done THEN
   Inst_MC_GearIn3( FALSE, Axis1, UpperRotary, 1, 1, 10000, 10000, 0, 0 );
   Inst_MC_GearIn4( FALSE, Axis1, LowerRotary, -1, 1, 10000, 10000, 0, 0 );
   Inst_MC_GearIn3( TRUE, Axis1, UpperRotary, 1, 1, 10000, 10000, 0, 0 );
   Inst_MC_GearIn4( TRUE, Axis1, LowerRotary, -1, 1, 10000, 10000, 0, 0 );
   StepCounter := 14;
END_IF;
14://Wait until Gear relationships have started, then command a velocity move with to the master
Inst_MC_GearIn3( TRUE, Axis1, UpperRotary, 1, 1, 10000, 10000, 0, 0 );
Inst_MC_GearIn4( TRUE, Axis1, LowerRotary, -1, 1, 10000, 10000, 0, 0 );
IF Inst_MC_GearIn3.InGear AND Inst_MC_GearIn4.InGear THEN
   Inst_MC_MoveVelocity4( FALSE, Axis1, 300, 10000, 10000, 0, 0, 0 );
   Inst_MC_MoveVelocity4( TRUE, Axis1, 300, 10000, 10000, 0, 0, 0 );
   Inst_ECATWriteSdo( FALSE, 16#3622, 0, 4, any_to_int(LowerECATAddress), 2470 );
   Inst_ECATWriteSdo( TRUE, 16#3622, 0, 4, any_to_int(LowerECATAddress), 2470 );
   Inst_TON( FALSE, T#2s );
   StepCounter := 15;
END_IF;
15://Start a timer, and after two seconds command a superimposed move to both rotary axes
Inst_TON( TRUE, T#2s );
IF Inst_TON.Q THEN
   Inst_MC_MoveSuperimp3( FALSE, UpperRotary, 360, 300, 10000, 10000, 0, 0 );
   Inst_MC_MoveSuperimp4( FALSE, LowerRotary, -360, 300, 10000, 10000, 0, 0 );
   Inst_MC_MoveSuperimp3( TRUE, UpperRotary, 360, 300, 10000, 10000, 0, 0 );
   Inst_MC_MoveSuperimp4( TRUE, LowerRotary, -360, 300, 10000, 10000, 0, 0 );
   Inst_TON( FALSE, T#2s );
   StepCounter := 16;
END_IF;
16://Wait for superimposed moves to finish and then move to next case
Inst_MC_MoveSuperimp3( TRUE, UpperRotary, 360, 300, 10000, 10000, 0, 0 );
Inst_MC_MoveSuperimp4( TRUE, LowerRotary, -360, 300, 10000, 10000, 0, 0 );
IF Inst_MC_MoveSuperimp3.Done AND Inst_MC_MoveSuperimp4.Done THEN
   StepCounter := 17;
END_IF;
17://Restart timer and wait two seconds, then phase adjust both rotary axes
Inst_TON( TRUE, T#2s );
IF Inst_TON.Q THEN
   Inst_MC_Phasing( FALSE, AXIS1, UpperRotary, -180, 150, 10000, 10000, 0, 0 );
   Inst_MC_Phasing1( FALSE, AXIS1, LowerRotary, -180, 150, 10000, 10000, 0, 0 );
   Inst_MC_Phasing( TRUE, AXIS1, UpperRotary, -180, 150, 10000, 10000, 0, 0 );
   Inst_MC_Phasing1( TRUE, AXIS1, LowerRotary, -180, 150, 10000, 10000, 0, 0 );
   StepCounter := 18;
END_IF;
18://Wait for phase adjustments to complete, then move to next case
Inst_MC_Phasing( TRUE, AXIS1, UpperRotary, -180, 150, 10000, 10000, 0, 0 );
Inst_MC_Phasing1( TRUE, AXIS1, LowerRotary, -180, 150, 10000, 10000, 0, 0 );
IF Inst_MC_Phasing.Done AND Inst_MC_Phasing1.Done THEN
   Inst_TON( FALSE, T#2s );
   StepCounter := 19;
END_IF;
19://Start timer, then after two seconds stop the velocity move on the master axis
Inst_TON( TRUE, T#2s );
IF Inst_TON.Q THEN
   Inst_MC_Halt7( FALSE, Axis1, 10000, 0, 0 );
   Inst_MC_Halt7( TRUE, Axis1, 10000, 0, 0 );
   StepCounter := 20;
END_IF;
20://Wait until master axis has stopped, then check StopCycle Boolean variable to decide if program should continue to cycle
Inst_MC_Halt7( TRUE, Axis1, 10000, 0, 0 );
IF Inst_MC_Halt7.Done THEN
   If StopCycle THEN
      StepCounter := 99;
   ELSE
      StepCounter :=100;
   END_IF;
END_IF;

99://Waiting state if StopCycle is set to true in HMI
100://Increase cycle counter and restart at the first case
CycleCount := CycleCount + 1;
StepCounter := 0;
END_CASE;

__END_ACTION
__BEGIN_P0
//Reset state machine to zero and stop all axes
StepCounter := 0;
Inst_MC_Halt7( FALSE, UpperRotary, 10000, 0, 0 );
Inst_MC_Halt7( TRUE, UpperRotary, 10000, 0, 0 );
Inst_MC_Halt8( FALSE, LowerRotary, 10000, 0, 0 );
Inst_MC_Halt8( TRUE, LowerRotary, 10000, 0, 0 );
Inst_MC_Halt9( FALSE, LinearZAxis, 10000, 0, 0 );
Inst_MC_Halt9( TRUE, LinearZAxis, 10000, 0, 0 );
Inst_MC_Halt10( FALSE, Axis1, 10000, 0, 0 );
Inst_MC_Halt10( TRUE, Axis1, 10000, 0, 0 );
__END_ACTION
#sfc=end
_next GT102;
_step GS201;
_next GT202;
_trans GT5;
#sfc=GT5(0,10)
MachineState <> 0
#sfc=end
_next GS4;
_trans GT102;
#sfc=GT102(1,10)
MachineState <> 1
#sfc=end
_next GS4;
_trans GT202;
#sfc=GT202(2,10)
MachineState <> 2
#sfc=end
_next GS4;