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