diff --git a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st index 3368f52cb..5aadeeefe 100644 --- a/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st +++ b/src/core/ctrl/src/AxoMessaging/Static/AxoMessenger.st @@ -60,9 +60,11 @@ NAMESPACE AXOpen.Messaging.Static VAR_INPUT _object : IAxoObject; END_VAR + IF AXOpen.Core.IsNullContext(_object.GetContext()) THEN RETURN; END_IF; + THIS.Initialize(_object); THIS.Serve(_object.GetContext()); diff --git a/src/core/ctrl/src/AxoTask/AxoTask.st b/src/core/ctrl/src/AxoTask/AxoTask.st index d04296e18..7fcde333c 100644 --- a/src/core/ctrl/src/AxoTask/AxoTask.st +++ b/src/core/ctrl/src/AxoTask/AxoTask.st @@ -1,6 +1,9 @@ USING AXOpen.Logging; USING AXOpen.Timers; +USING AXOpen.Messaging; +USING AXOpen.Messaging.Static; + NAMESPACE AXOpen.Core CLASS PUBLIC AxoTask EXTENDS AxoObject IMPLEMENTS IAxoTask, IAxoTaskState @@ -63,6 +66,14 @@ NAMESPACE AXOpen.Core /// Contains details about the error. /// ErrorDetails : STRING[254]; + + /// + /// Enable error message when task is not calling cyclically . + /// + {#ix-set:MessageText = "<#Cyclic Execute is not called.#>"} + {#ix-set:Help = "<#Check task calling in the code, task is not calling cyclically #>"} + _CyclicExecuteIsNotCalled : AXOpen.Messaging.Static.AxoMessenger; + END_VAR VAR PRIVATE @@ -192,10 +203,15 @@ NAMESPACE AXOpen.Core IF _isNullContext THEN Status := eAxoTaskState#Error; - ErrorDetails := 'NULL CONTEXT'; + ErrorDetails := 'NULL CONTEXT'; + RETURN; END_IF; + THIS.UpdateState(); + + _CyclicExecuteIsNotCalled.Serve(THIS); + IF Status = eAxoTaskState#Done AND THIS.IsNewInvokeCall() THEN Status := eAxoTaskState#Ready; END_IF; @@ -205,11 +221,11 @@ NAMESPACE AXOpen.Core // task should not be Invoked, if the execute method was not called in this or previous PLC cycle IF Status = eAxoTaskState#Ready THEN IF (THIS.IsExecuteCalledInThisPlcCycle() OR THIS.WasExecuteCalledInPreviousPlcCycle()) THEN - Status := eAxoTaskState#Kicking; - THIS.LogTask('Task invoked', eLogLevel#Verbose, THIS); - ELSE - THIS.LogTask('Cyclic execute is not called', eLogLevel#Debug, THIS); - END_IF; + Status := eAxoTaskState#Kicking; + THIS.LogTask('Task invoked', eLogLevel#Verbose, THIS); + ELSE + _CyclicExecuteIsNotCalled.Activate(eAxoMessageCategory#ProgrammingError); + END_IF; END_IF; Invoke := THIS; diff --git a/src/templates.simple/ctrl/src/Examples/PneumaticManipulator.st b/src/templates.simple/ctrl/src/Examples/PneumaticManipulator.st index 421d83729..96a091fd8 100644 --- a/src/templates.simple/ctrl/src/Examples/PneumaticManipulator.st +++ b/src/templates.simple/ctrl/src/Examples/PneumaticManipulator.st @@ -108,7 +108,7 @@ NAMESPACE examples.PneumaticManipulator /// /// Hardware output structure /// - Outputs : axosimple.Outputs; + Outputs : axosimple.Outputs; END_VAR THIS.Initialize(parent); THIS.Execute(Inputs, Outputs); @@ -341,7 +341,8 @@ NAMESPACE examples.PneumaticManipulator CLASS PUBLIC GroundSequence EXTENDS AXOpen.Core.AxoSequencerContainer VAR PUBLIC - Steps : ARRAY[0..20] OF AxoStep; + Steps : ARRAY[0..20] OF AxoStep; + MoveToWork : AxoTask; END_VAR VAR PRIVATE Components : REF_TO Components; @@ -357,6 +358,9 @@ NAMESPACE examples.PneumaticManipulator Components := _components; ProcessData := _processData; SUPER.Run(_parent); + + // MoveToWork.Initialize(THIS); + END_METHOD /// /// Contains logic of the steps of this sequence @@ -373,16 +377,24 @@ NAMESPACE examples.PneumaticManipulator THIS.SequenceMode := eAxoSequenceMode#RunOnce; // This is more verbose but also more versatile way of executing step logic. IF (Steps[0].Execute(THIS, TRUE, 'Move vertical cyclinder down.')) THEN + //------------------------------------------------------- + IF (components^.VerticalCylinder.MoveToHome.Invoke().IsDone()) THEN // <- waits for the task to be done. + THIS.MoveNext(); // <- This will move to the next step in the sequence. + END_IF; + //------------------------------------------------------- + END_IF; + + IF (Steps[4].Execute(THIS, TRUE, 'This will break down')) THEN + //------------------------------------------------------- + THIS.MoveNext(); //------------------------------------------------------- - IF (components^.VerticalCylinder.MoveToHome.Invoke().IsDone()) THEN // <- waits for the task to be done. - THIS.MoveNext(); // <- This will move to the next step in the sequence. - END_IF; -//------------------------------------------------------- END_IF; + // This is more concise way of writing steps when we execute only single task. THIS.AndThen(Steps[1], components^.GripperCylinder.MoveToHome); THIS.AndThen(Steps[2], components^.VerticalCylinder.MoveToHome); THIS.AndThen(Steps[3], components^.HorizontalCylinder.MoveToHome); + // This will close the sequence and will return to the first step. THIS.Close(Steps[20]); END_METHOD