Can't get SMC_SmoothPath to work

bertus
2025-12-17
7 hours ago
  • bertus - 2025-12-17

    Hello all,

    I am trying to run a XY trajectory from a static G-Code file.
    Everything works except the smoothing/blending of the corners.

    My setup:

    • Codesys v3.5sp18
    • Raspberry Pi 4
    • CODESYS Control for Raspberry Pi SL, using demo license.
    • Zero axes (only using the interpolator).

    The order of processing for my decoding is:

    1. SMC_NCDecoder (ok)
    2. SMC_SmoothMerge (ok)
    3. SMC_SmoothPath (not ok)
    4. SMC_LimitDynamics
    5. SMC_CheckVelocities

    I created following instances and buffers:

    fbNCDecoder: SMC_NCDecoder;
    fbSmoothMerge: SMC_SmoothMerge;
    fbSmoothPath: SMC_SmoothPath;
    fbLimitDynamics: SMC_LimitDynamics;
    fbCheckVelocities: SMC_CheckVelocities;
    aNCDecoderBuffer: ARRAY[0..49] OF SMC_GeoInfo; // buffer stage 1 (fbNCDecoder)
    aSmoothMergeBuffer: ARRAY[0..19] OF SMC_GeoInfo; // buffer stage 2 (fbSmoothMerge)
    aSmoothPathBuffer: ARRAY[0..99] OF SMC_GeoInfo; // buffer stage 3 (fbSmoothPath)
    aLimitDynamicsBuffer: ARRAY[0..39] OF SMC_GeoInfo; // buffer stage 4 (fbLimitDynamics)
    

    My original G-Code file has a lot of short G1 elements but this example, I reduced it to a simple square:

    N000 G51 D10
    N010 G38 O1 
    N020 G00 X0 Y0 F50 E1000 E-1000 
    N030 G01 X0 Y-37.5 
    N040 G01 X-75 Y-37.5 
    N050 G01 X-75 Y37.5 
    N060 G01 X0 Y37.5 
    N070 G01 X0 Y0 
    N080 G50 
    N090 G39 O1 
    

    In the Codesys CNC settings, I have these instances activated:

    • SMC_SmoothMerge
    • SMC_SmoothPath
    • SMC_LimitDynamics
    • SMC_CheckVelocities

    And with those settings (and the path-preprocessing button actived), the G-Code viewer shows the square with nicely blended corners (see attached picture).
    However, when running it on the PLC, it doesn't blend the corners at all.

    Below the relevant part of my code. The process is started with bDecode.

    // stage 1: decoding G-code
    fbNCDecoder(
      ncprog := square,
      bExecute:= bDecode,
      bAbort:= NOT bDecode,
      nSizeOutQueue := SIZEOF(aNCDecoderBuffer),
      pbyBufferOutQueue := ADR(aNCDecoderBuffer)
      );
    
    // stage 2: merge short linear segments
    fbSmoothMerge(
      bExecute := bDecode,
      poqDataIn := fbNCDecoder.poqDataOut,
      nSizeOutQueue := SIZEOF(aSmoothMergeBuffer),
      pbyBufferOutQueue := ADR(aSmoothMergeBuffer),
      piMaxDifference := PI_MAX_DIFFERENCE,
      usiMaxDegree := 5,
      wFeatureFlag := 1,
      wAdditionalParamNumber := 0,
      dMinimumCurvatureRadius := D_MIN_CURVATURE_RADIUS
      );
    
    // stage 3: smooth corners
    fbSmoothPath(
      bExecute := bDecode,
      bAbort := NOT bDecode,
      poqDataIn := fbSmoothMerge.poqDataOut,
      eMode := SMC_SMOOTHPATHMODE.SP_SPLINE5_MIN_CURVATURE,
      eAddAxMode := SMC_SMOOTHPATHADDAXMODE.SPAA_NONE,
      nSizeOutQueue := SIZEOF(aSmoothPathBuffer),
      pbyBufferOutQueue := ADR(aSmoothPathBuffer),
      dAngleTol := D_ANGLE_TOL,
      bSymmetricalDistances := TRUE,
      bImprovedSymmetricCuts := TRUE
      );
    
    // stage 4: keep acc/dec and velocity within limits
    fbLimitDynamics(
      bExecute := bDecode,
      bAbort := NOT bDecode,
      poqDataIn := fbSmoothPath.poqDataOut,
      wAxis := 16#07,
      nSizeOutQueue := SIZEOF(aLimitDynamicsBuffer),
      pbyBufferOutQueue := ADR(aLimitDynamicsBuffer),
      bIncludePathSettings := TRUE,
      dMaxVel := 2500,
      dMaxAccDec := 10000
      );
    
    // stage 5: check the path speed
    fbCheckVelocities(
      bExecute := bDecode,
      bAbort := NOT bDecode,
      poqDataIn := fbLimitDynamics.poqDataOut,
      dAngleTol := D_ANGLE_TOL);
    
    pathQueue := fbCheckVelocities.poqDataOut;
    
    // repeat until MaxDuration 
    ...
    

    Any idea what I'm doing wrong? Is smooth path supposed to work at all when using a demo license?

    Thanks.

     
  • gseidel - 2025-12-17

    Hi bertus,

    I cannot see any problem in the code you posted. Just some ideas:

    • What is the value of D_ANGLE_TOL?
      -
    • Do you need the assignment bAbort := NOT bDecoder? Does it help to leave it out?

    • Any errors (e.g. SMC_SmoothPath.Error/ErrorID) or PLC log messages?

    • What if you comment out SMC_SmoothMerge and SMC_LimtiDynamics, is corner smoothing still not working?

    • Is bDecode written from a different task (e.g. visu)? Then I would recommend to assign to a local variable (bDecodeLocal := bDecode) and use that for all FBs. Otherwise, FBs might see different values of bDecode in a single cycle, which will cause problems.

    Regards,

    Georg

     
  • bertus - 2025-12-18

    Hi Georg, thanks for your time.

    What is the value of D_ANGLE_TOL?

    It is set to 0.01.

    Do you need the assignment bAbort := NOT bDecoder? Does it help to leave it out?

    This seems to make no difference.

    Any errors (e.g. SMC_SmoothPath.Error/ErrorID) or PLC log messages?

    No errors or log messages.

    What if you comment out SMC_SmoothMerge and SMC_LimtiDynamics, is corner smoothing still not working?

    Indeed.

    Is bDecode written from a different task (e.g. visu)? Then I would recommend to assign to a local variable (bDecodeLocal := bDecode) and use that for all FBs. Otherwise, FBs might see different values of bDecode in a single cycle, which will cause problems.

    It is a local variable, written from a state machine inside this program.

    But there is new information:

    During some trial and error, I tried skipping "stage 2: merge short linear segments" (SMC_SmoothMerge). And suddenly it rounds the corners, see attached image.

    • Looking a bit closer, I noticed that (with the original program) after a download (cold start?), it in fact did round the corners, but only once. Ever next cycle in which the NC program was executed, the corners where not rounded.
    • Not sure if there is any relation, but SMC_SmoothMerge is also the only FB which has no bAbort input.
    • Perhaps I need to reset it (or any buffers) by other means?
     
  • gseidel - 2025-12-23

    Hi bertus,

    thanks for the additional information. Setting bAbort on a restart is not needed. Calling all FBs starting from the decoder up to checkvelocities with bExecute = FALSE and then giving a new rising edge on bExecute is what should be done.

    Do you also restart the Interpolator? (I don't think that has anything to do with the issue, but still...)

    Best regards,

    Georg

     
  • bertus - 6 days ago

    Thanks. I will do more investigation and testing next week.

     
  • blitz - 7 hours ago

    Hi @bertus

    I have a similar situation:

    • just like in your case I can see that rounding works correctly only for the first element,

    • additionally in my case on a path made of lines where I am testing this every second line is skipped. The interpolator jumps to every second iActObjectSourceNo.

     

Log in to post a comment.