Hi!
Is there any way to spot error in the code that works right 99% of time?
For those who want to dive deeper into my code:
I got program which sends a product to the machines in First in First out manner, but sometimes one of them get stuck and won't accept demand call.
Basically there are 2 variables who deal with it. One to which keeps the signal after push button is released, second to tell that machine is in already in queue and ignore following calls.
Problem occurs when one of them isn't back to false at the end of the cycle, so the program thinks that machine is in queue, when actually it is not.
It is a minor thing, operators have simply to restart production, that's basically 20s break(or I can reset it by writing said variables to false, but I'm not always available).
Easy solution is that I can simply put a reset button, but this won't sate my ego. Any ideas?
The variables which end _unit are cycling between 0 or 1 and their MAX constant.
FVL. is global variable list
Is there any way to spot error in the code that works right 99% of time?
For those who want to dive deeper into my code:
I got program which sends a product to the machines in First in First out manner, but sometimes one of them get stuck and won't accept demand call.
Basically there are 2 variables who deal with it. One to which keeps the signal after push button is released, second to tell that machine is in already in queue and ignore following calls.
Problem occurs when one of them isn't back to false at the end of the cycle, so the program thinks that machine is in queue, when actually it is not.
It is a minor thing, operators have simply to restart production, that's basically 20s break(or I can reset it by writing said variables to false, but I'm not always available).
Easy solution is that I can simply put a reset button, but this won't sate my ego. Any ideas?
The variables which end _unit are cycling between 0 or 1 and their MAX constant.
FVL. is global variable list
Code:
//Production Mode
FVL.Status_Cleaning := 0;
CASE FVL.Status_Production OF
0:(*Initialisation*)
FVL.Termination_TON(IN := UVL.Start_Production_Mode AND UVL.Safety_OK, PT := T#11S);
IF FVL.Termination_TON.Q THEN
FVL.Termination_TON(IN := FALSE);
FVL.Status_Production := 1;
END_IF
1:(*Work*)
(*Conveyors*)
IF UVL.Current_InFeed_Conveyor_Unit >= 2 AND UVL.Current_InFeed_Conveyor_Unit <= 5 THEN
FVL.Conveyor[UVL.Current_InFeed_Conveyor_Unit](Force_Start_1 := TRUE, Force_Soft := FALSE,
ifWiping := FALSE, tTON := T#0S, tTOF := T#0S, tTW := T#0S);
END_IF
FVL.Conveyor[1](Force_Start_1 := FVL.TerminateFirstIn <> 0, Force_Soft := FALSE,
ifWiping := TRUE, tTON := T#3S, tTOF := T#0S, tTW := TVL.InFeed_Load);
FVL.Conveyor[6](Force_Start_1 := FVL.Conveyor_6_Timer.Q, Force_Soft := FALSE,
ifWiping := FALSE, tTON := T#0S, tTOF := T#0S, tTW := T#0S);
FVL.Conveyor[7](Force_Start_1 := FVL.Conveyor_7_Button_Control.Q, Force_Soft := FALSE,
ifWiping := FALSE, tTON := T#0S, tTOF := T#0S, tTW := T#0S);
FVL.Conveyor[8](Force_Start_1 := FVL.Conveyor_8_Button_Control.Q, Force_Soft := FALSE,
ifWiping := FALSE, tTON := T#0S, tTOF := T#0S, tTW := T#0S);
[B](*InFeed FIFO*)
actFIFO();
(*Button holders*)
IF UVL.InFeedDevice_Unit_Enabler THEN
IF FVL.BaaderDevices[UVL.Current_InFeedDevice_Unit].Call_Button.Q AND FVL.BaaderDevices[UVL.Current_InFeedDevice_Unit].FeedBack.Q AND NOT FVL.Button_isQueued[UVL.Current_InFeedDevice_Unit] THEN
FVL.Button_Holder[UVL.Current_InFeedDevice_Unit] := TRUE;
END_IF
END_IF[/B]
(*Flipper Control*)
IF FVL.Queue_Clock >= 1 AND FVL.Queue_Clock <= UVL.MAX_InFeedDevices_Units AND FVL.Queue[1] <> 0 THEN
IF FVL.Queue_Clock <= FVL.Queue[1] AND FVL.Queue[1] <> UVL.MAX_InFeedDevices_Units THEN
FVL.BaaderDevices[FVL.Queue_Clock].Flipper.in := TRUE;
ELSE
FVL.BaaderDevices[FVL.Queue_Clock].Flipper.in := FALSE;
END_IF
END_IF
IF NOT UVL.Start_Production_Mode OR NOT UVL.Safety_OK THEN
FVL.Status_Production := 2;
END_IF
2:(*Termination*)
(*Terminate Flippers*)
IF UVL.InFeedDevice_Unit_Enabler THEN
FVL.BaaderDevices[UVL.Current_InFeedDevice_Unit].Flipper(in := FALSE, tTOF := T#0S,
tTON := T#0S, tTW := T#0S, ifWiping := FALSE);
END_IF
(*Terminate Conveyors*)
IF UVL.InFeedConveyor_Unit_Enabler THEN
FVL.Conveyor[UVL.Current_InFeed_Conveyor_Unit](Force_Start_1 := FALSE, Force_Soft := FALSE,
ifWiping := FALSE, tTON := T#0S, tTOF := T#0S, tTW := T#0S);
END_IF
[B](*Terminate FIFO*)
FVL.Queue[UVL.Current_InFeedDevice_Unit] := 0;
FVL.Button_Holder[UVL.Current_InFeedDevice_Unit] := FALSE;
FVL.Button_isQueued[UVL.Current_InFeedDevice_Unit] := FALSE;
FVL.Queue_Clock := 1;
FVL.Queue_Lowest := 0;
FVL.TerminateFirstIn := 0;
FVL.TerminateFirstIn_TON(IN := FALSE);[/B]
(*EOT*)
FVL.Termination_TON(IN := TRUE, PT := T#5S);
IF FVL.Termination_TON.Q THEN
FVL.Termination_TON(IN := FALSE);
FVL.Status_Production := 0;
END_IF
END_CASE
Code:
(*actFIFO()*)
(*InFeed FIFO*)
FVL.Queue[0] := UVL.MAX_InFeedDevices_Units + 1;
FVL.Queue[UVL.MAX_InFeedDevices_Units + 1] := 0;
IF FVL.Queue_Clock >= 1 AND FVL.Queue_Clock <= UVL.MAX_InFeedDevices_Units THEN
(*Move queue*)
IF FVL.Queue[FVL.Queue_Clock] = 0 AND FVL.Queue[FVL.Queue_Clock + 1] <> 0 THEN
FVL.Queue[FVL.Queue_Clock] := FVL.Queue[FVL.Queue_Clock + 1];
FVL.Queue[FVL.Queue_Clock + 1] := 0;
END_IF
(*Find lowest vacant*)
IF FVL.Queue_Lowest < 1 AND FVL.Queue_Lowest > UVL.MAX_InFeedDevices_Units THEN
FVL.Queue_Lowest := 1;
ELSIF FVL.Queue[FVL.Queue_Clock] = 0 AND FVL.Queue[FVL.Queue_Clock - 1] <> 0 THEN
FVL.Queue_Lowest := FVL.Queue_Clock;
END_IF
IF FVL.BaaderDevices[FVL.Queue_Clock].Call_Button.Q AND FVL.BaaderDevices[FVL.Queue_Clock].FeedBack.Q THEN
FVL.Button_Holder[FVL.Queue_Clock] := TRUE;
END_IF
(*Assign button number to the vacant lowest queue *)
FVL.Button_R_TRIG[FVL.Queue_Clock](CLK := FVL.Button_Holder[FVL.Queue_Clock]);
IF FVL.Button_R_TRIG[FVL.Queue_Clock].Q AND NOT FVL.Button_isQueued[FVL.Queue_Clock] THEN
FVL.Button_isQueued[FVL.Queue_Clock] := TRUE;
FVL.Queue[FVL.Queue_Lowest] := FVL.Queue_Clock;
FVL.Button_Holder[FVL.Queue_Clock] := FALSE;
END_IF
IF FVL.Queue[FVL.Queue_Clock] = UVL.MAX_InFeedDevices_Units AND FVL.Queue[FVL.Queue_Clock + 1] <> 0 AND FVL.Queue[1] <> UVL.MAX_InFeedDevices_Units THEN
FVL.Queue[FVL.Queue_Clock] := FVL.Queue[FVL.Queue_Clock + 1];
FVL.Queue[FVL.Queue_Clock + 1] := UVL.MAX_InFeedDevices_Units;
END_IF
FVL.Queue_Clock := FVL.Queue_Clock + 1;
ELSE
FVL.Queue_Clock := 1;
END_IF
(*Terminate First Place*)
IF FVL.Queue[1] <> 0 THEN
CASE FVL.TerminateFirstIn OF
0: IF NOT FVL.BaaderDevices[FVL.Queue[1]].FeedBack.Q THEN
FVL.TerminateFirstIn := 2;
ELSE
FVL.TerminateFirstIn := 1;
END_IF
1: FVL.TerminateFirstIn_TON(IN := TRUE, PT := TVL.InFeed_Next_Cycle);
IF FVL.TerminateFirstIn_TON.Q THEN
FVL.TerminateFirstIn_TON(IN := FALSE);
FVL.TerminateFirstIn := 2;
END_IF
2: FVL.Button_isQueued[FVL.Queue[1]] := FALSE;
FVL.Button_Holder[FVL.Queue[1]] := FALSE;
FVL.TerminateFirstIn := 0;
FVL.Queue[1] := 0;
END_CASE
END_IF
Last edited: