Search code examples
twincat

Breaking the code inside a method assigns wrong online values


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: Online values when method is called

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: enter image description here

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: enter image description here


Solution

  • 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.)