I have a function block, inside of which I have a method. When the method is called, it takes it's input REAL variable and sets the function block's internal variable, also type REAL. Now, for some reason, when i put a breakpoint inside the method, the value for that variable is completely wrong, and is always assigned the same value. Here is the code
METHOD PUBLIC LowerTheObject : BOOL
VAR_INPUT
nSpeedSetpoint : INT; // 0-32767 (0-21mm/min)
fInsertionDistance : REAL; // Milimeters
END_VAR
IF bEnable AND eMotionStateInternal = E_FeedState.IDLE AND bInhibitMovementDown THEN
LowerTheObject := TRUE;
eMotionStateInternal := E_FeedState.AUTOMATIC_LOWERING;
THIS^.fLoweringStartPosition := THIS^.fPosition;
THIS^.nSpeedSetpoint := nSpeedSetpoint;
THIS^.fInsertionDepth := TO_REAL(fInsertionDistance);
ELSE
LowerTheObject := FALSE;
END_IF
When I call this method here is what happens:
Now comes the interesting part, which took me a while to even see it. The value of the variable is WRONG only, when I break the code inside the method. Breaking the code inside the function block, the variable gets assigned correct value:
To wrap it up, I am as confused as ever. Why does braking the code assign the wrong value? This is very wrong, the code can't be debugged properly. Is this a bug in this build of the TwinCAT?
I can guarantee that no other place in the code sets the value of the fInsertionDepth
. I even added the TO_REAL(), in case the compiler did something weird I am not seeing. It seems like a memory allocation issue to me, I have tried restarting the PC, cleaning solution, re-activating the configuration, nothing helps.
Does anyone have a clue what might be happening, why is the variable fInsertionDepth get the 9.4 * 10^-38 when using a breakpoint, no matter what value is beeing assinged to it? I am running the solution on a local development machine, windows10, 64 bit as well as 64 bit CPU, never saw these issues before. Using TwinCAT 3, build 4024.25.
EDIT: I have managed to make a project where this is very obviously replicated - I am not sure how/where to add attachments, so here is the code:
PROGRAM MAIN
VAR
END_VAR
ProgramExecution();
// Program that will containt FBs
PROGRAM ProgramExecution
VAR
fbTest : FB_Base;
END_VAR
fbTest();
// Base FB
FUNCTION_BLOCK FB_Base
VAR
fbTest : FB_Sub;
fValue : REAL := 10.0;
bStart : BOOL;
END_VAR
IF bStart THEN
bStart := FALSE;
fbTest.Method1(fValue := fValue);
END_IF
fbTest();
// Second FB, that is instantiated inside the base FB
FUNCTION_BLOCK FB_Sub
VAR
fValue : REAL;
bCall : BOOL;
END_VAR
// Method within the second FB
METHOD PUBLIC Method1 : BOOL
VAR_INPUT
fValue : REAL;
END_VAR
IF TRUE THEN
Method1 := TRUE;
THIS^.fValue := fValue;
ELSE
Method1 := FALSE;
END_IF
Here is the resulting error when breaking on the expression where the value is beeing assinged:
It is a glitch in displays, this value is assigned at some point, because you working in the stack memory (because the variable is declared in a method). In the PLC world you don't have any garbage collector, you just overwrite the address in every cycle. The number what you can see in when you break is some remaining data. Sometime the debug display not fast enough to collect everything when you break, especially if you change tab on the break. (This display issue is depend on your engineering PC not on the target PLC.)